Rails ActiveRecord: как мне узнать, найден или создан ли find_or_create_by?

#ruby-on-rails #activerecord

#ruby-on-rails #активный файл

Вопрос:

Если я сделаю

 widget = Widget.find_or_create_by_widgetid(:widgetid => "12345", :param2 => "folk") 
  

и т.д. Тогда как мне определить, является ли newobj найденным или только что созданным виджетом? Есть ли что-нибудь, что я могу протестировать условно widget , что подскажет мне?

Комментарии:

1. Вы могли бы проверить created_at атрибут и сравнить его с Time.now , чтобы тоже получить какое-то представление.

Ответ №1:

Я не верю, что есть способ определить, создан ли объект недавно или уже был там. Вместо этого вы могли бы использовать find_or_initialize_by_widgetid , который не сохраняет новый объект. Затем вы можете проверить, widget.new_record? который сообщит вам, был ли сохранен объект или нет. Вам пришлось бы поместить вызов сохранения в блок кода для нового объекта, но поскольку вы все равно хотите выполнить эту проверку, это не должно нарушать поток кода.

Итак:

 widget = find_or_initialize_by_widgetid(:widgetid => "12345", :param2 => "folk")
if widget.new_record?
  widget.save!
  # Code for a new widget
else
  # Code for an existing widget
end
  

Комментарии:

1. Я начал рассматривать возможность сделать это таким образом, спасибо, что подтвердили это как жизнеспособный вариант.

2. В зависимости от того, чего вы хотите достичь, вы также можете использовать find_or_initialize_by_widgetid с блоком. Блок будет выполнен только для вновь инициализированной записи.

3. find_or_create_by_ также принимает блок, который будет передан create и, таким образом, запускаться только при создании новой записи.

Ответ №2:

Rails 4

find_or_create_by (атрибуты и блок)

Теперь этот метод принимает блок, который передается в create, поэтому я бы выбрал:

 widget = Widget.find_or_create_by(:widgetid => "12345", :param2 => "folk") do |w|
  # if you got in here, this is a new widget
end
  

Другим способом сделать это в Rails 4 было бы:

 widget = Widget.where(:widgetid => "12345", :param2 => "folk").first_or_initialize

if widget.new_record?
  # this is a new widget
end
  

Ответ №3:

В зависимости от того, что вы хотите сделать, вы можете использовать блок:

 widget = find_or_create_by(widgetid: "12345") do |widget|
  widget.param2 = "folk"
  if widget.new_record?
    # Code for a new widget.
  else
    # Code for an existing widget.
  end
end
  

Комментарии:

1. На самом деле, как указано в artm выше (и в документации указано), блок передается только в ‘create’, поэтому нет необходимости проверять наличие нового.