#ruby-on-rails #activerecord #dynamic-finders
#ruby-on-rails #activerecord #динамические средства поиска
Вопрос:
Метод динамического поиска ActiveRecord find_or_create_by позволяет мне указать блок. В документации это неясно, но, похоже, что блок выполняется только в случае создания, а не в случае поиска. Другими словами, если запись найдена, блок не выполняется. Я тестировал это с помощью этого консольного кода:
User.find_or_create_by_name("An Existing Name") do |u|
puts "I'M IN THE BLOCK"
end
(ничего не было напечатано). Есть ли какой-либо способ запустить блок в обоих случаях?
Комментарии:
1. Я слишком часто сталкивался с таким поведением, поэтому обычно я отказываюсь от использования блока. Вместо этого я бы присвоил переменной результат
find_or_create_by_...
, а затем впоследствии оперировал бы с этой переменной.
Ответ №1:
Насколько я понимаю, блок будет выполнен, если ничего не найдено. Вариант его использования выглядит следующим образом:
User.find_or_create_by_name("Pedro") do |u|
u.money = 0
u.country = "Mexico"
puts "User is created"
end
Если пользователь не найден, он инициализирует нового пользователя с именем «Pedro» и всем этим материалом внутри блока и вернет нового созданного пользователя. Если пользователь существует, он просто вернет этого пользователя без выполнения блока.
Также вы можете использовать «стиль блока» и другие методы, такие как:
User.create do |u|
u.name = "Pedro"
u.money = 1000
end
Он будет делать то же самое, что и User.create( :name => "Pedro", :money => 1000 )
, но выглядит немного приятнее
и
User.find(19) do |u|
..
end
и т. Д
Ответ №2:
Мне не кажется, что на этот вопрос действительно дан ответ, поэтому я так и сделаю. Я думаю, это самый простой способ, которым вы можете этого добиться:
User.find_or_create_by_name("An Existing Name or Non Existing Name").tap do |u|
puts "I'M IN THE BLOCK REGARDLESS OF THE NAME'S EXISTENCE"
end
Приветствия!
Комментарии:
1. Вы использовали
tap
который вернет результатfind_or...
, так что фактически блок передается не в find, а в tap!2. Обратите внимание, что в случае, если ваша таблица имеет ограничение not null, которому не удовлетворяют поля, по которым вы выполняете поиск, вызов tap вызовет ActiveRecord::StatementInvalid