Если вы хотите сравнить два экземпляра модели на основе их атрибутов, вы, вероятно, захотите исключить некоторые несущественные атрибуты из вашего сравнения, такие как: id
, created_at
и updated_at
,(Я бы посчитал, что это больше метаданных о записи, чем части самих данных записи.)
Это может не иметь значения при сравнении двух новых (несохраненных) записей (так как id
, created_at
и updated_at
будут nil
до сохранения), но я иногда считаю необходимым сравнить сохраненный объект с несохраненным (вкакой случай == даст вам ложь, так как ноль! = 5).Или я хочу сравнить два сохраненных объекта, чтобы выяснить, содержат ли они одинаковые данные (поэтому оператор ActiveRecord ==
не работает, потому что он возвращает false, если у них разныеid
, даже если они идентичны).
Мое решение этой проблемы - добавить что-то подобное в модели, которые вы хотите сравнивать, используя атрибуты:
def self.attributes_to_ignore_when_comparing
[:id, :created_at, :updated_at]
end
def identical?(other)
self. attributes.except(*self.class.attributes_to_ignore_when_comparing.map(&:to_s)) ==
other.attributes.except(*self.class.attributes_to_ignore_when_comparing.map(&:to_s))
end
Тогда в своих спецификациях я могу написать такие читаемые и лаконичные вещи, как это:
Address.last.should be_identical(Address.new({city: 'City', country: 'USA'}))
Я планирую разветвлять драгоценный камень active_record_attributes_equality
и изменить его, чтобы использовать это поведение так, чтобы это могло бытьлегко использовать повторно.
Некоторые вопросы, которые у меня есть, включают:
- Такой камень уже существует ??
- Как должен называться метод?Я не думаю, что переопределение существующего оператора
==
является хорошей идеей, поэтому сейчас я называю его identical?
.Но, возможно, что-то вроде practically_identical?
или attributes_eql?
будет более точным, поскольку он не проверяет, являются ли они строго идентичными ( некоторым атрибутам разрешено быть разными.)... attributes_to_ignore_when_comparing
слишком многословно.Не то чтобы это нужно было явно добавлять в каждую модель, если они хотят использовать значения по умолчанию для драгоценного камня.Возможно, допустим переопределение значения по умолчанию с помощью макроса класса, например ignore_for_attributes_eql :last_signed_in_at, :updated_at
Комментарии приветствуются ...
Обновление : вместо разветвления active_record_attributes_equality
, Я написал совершенно новый камень, active_record_ignored_attributes , доступный по http://github.com/TylerRick/active_record_ignored_attributes и http://rubygems.org/gems/active_record_ignored_attributes