Rails 3 속성이 변경되었는지 확인


153

Rails 3에서 업데이트하기 전에 속성 블록이 변경되었는지 확인해야합니다.

street1, street2, 도시, 주, 우편 번호

나는 같은 것을 사용할 수 있다는 것을 안다.

if @user.street1 != params[:user][:street1]
  then do something....
end

그러나 그 코드는 정말 길다. 더 깨끗한 방법이 있습니까?

답변:


282

ActiveModel :: Dirty를 확인하십시오 (기본적으로 모든 모델에서 사용 가능). 설명서는 정말 좋지만 다음과 같은 작업을 수행 할 수 있습니다.

@user.street1_changed? # => true/false

이것은 속성이 양식에서 변경되었는지 여부를 확인하려는 경우 도움이되지 않습니다 (OP가 수행하는 것으로 보입니다).
마크 프레이저

8
물론입니다. params 해시를 사용하여 값을 할당하면 값이 양식에서 제공됩니다.
피터 브라운

model.collection.changed_size_by와 같은 작업을 수행하려면 어떻게해야합니까? 나 같은
마우로 디아스

@MauroDias 당신은 그런 컬렉션 속성을 추적하기 위해 자신의 논리를 작성해야합니다.
피터 브라운

이것을 위해 테스트 라이브러리를 사용하려고합니다. 어쨌든 해결 방법이 될 수 있습니다. TY
Mauro Dias

54

이것이 여러 속성의 변경 사항을 확인하는 문제를 해결 한 방법입니다.

attrs = ["street1", "street2", "city", "state", "zipcode"]

if (@user.changed & attrs).any?
  then do something....
end

changed메소드는 해당 오브젝트에 대해 변경된 속성의 배열을 리턴합니다.

모두 @user.changedattrs내가 교회법을 얻을 수 있도록 배열이다 (참조 ary & other ary방법). 교집합의 결과는 배열입니다. any?배열 을 호출 하면 적어도 하나의 교차점이 있으면 사실입니다.

또한이 changed_attributes메소드는 원래 값으로 속성의 해시를 반환하고 원래 값 changes과 새 값으로 배열의 해시를 반환합니다.

이 메소드를 지원하는 버전에 대한 APIDock을 확인할 수 있습니다.

http://apidock.com/rails/ActiveModel/Dirty


1
이것은 좋은 방법입니다. 역사적으로 나는 if attrs.any?{|attr| @user.send("#{attr}_changed?")}여러 가지 속성 중 하나가 변경되었는지 확인하고 싶을 때-물론, 사용자 매개 변수를 send메소드에 던지는 것을 좋아하지 않기 때문에 내가 정의한 속성 만 사용 하여이 작업을 수행합니다 . ;)
nzifnab

14

ActiveModel::Dirty@model.update_attributes()변경 사항을 숨겨서 나를 위해 작동하지 않았습니다 . 그래서 이것은 update컨트롤러 의 메소드에서 변경 사항을 감지 한 방법입니다.

def update
  @model = Model.find(params[:id])
  detect_changes

  if @model.update_attributes(params[:model])
    do_stuff if attr_changed?
  end
end

private

def detect_changes
  @changed = []
  @changed << :attr if @model.attr != params[:model][:attr]
end

def attr_changed?
  @changed.include :attr
end

많은 속성 변경을 감지하려고하면 지저분해질 수 있습니다. 아마도 컨트롤러 에서이 작업을 수행해서는 안되지만 meh.


9
가치있는 일을 위해 previous_changes기본적으로 사용 가능한 이 작업을 수행 할 수 있습니다 .
Jason Galuten

2
#update_attributes변경 사항을 숨기지 않습니다. 레코드를 저장하므로 모델이 업데이트되고 변경 사항이 없습니다. 모델에서 필드를 변경하고 changed?저장하기 전에 확인 해야합니다. 즉. @ model.field = 'foo'또는@model.attributes = @model.attributes.merge(params[:model])
Grzegorz

9

레일 5.1+ 콜백

Ruby on Rails 5.1부터 attribute_changed?and 및 attribute_wasActiveRecord 메소드는 더 이상 사용되지 않습니다

saved_change_to_attribute?대신 사용attribute_changed?

@user.saved_change_to_street1? # => true/false

더 많은 예제는 여기


2

위의 답변이 더 좋지만 지식에 대해서는 또 다른 접근 방식이 있습니다 .'catagory '열 값을 객체 (@design)에 대해 변경하도록하십시오.

@design.changes.has_key?('catagory')

.changes는 키를 열 이름으로, 값을 각 열에 대해 두 개의 값 [old_value, new_value]을 갖는 배열로 해시를 반환합니다. 예를 들어 위의 카테고리는 @design의 'ABC'에서 'XYZ'로 변경되었습니다.

@design.changes   # => {} 
@design.catagory = 'XYZ'
@design.changes # => { 'catagory' => ['ABC', 'XYZ'] }

ROR의 참조 변경 사항

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.