Rails find_or_create_by where block runs in the find case?

Simon Woodside picture Simon Woodside · Mar 28, 2011 · Viewed 10.5k times · Source

The ActiveRecord find_or_create_by dynamic finder method allows me to specify a block. The documentation isn't clear on this, but it seems that the block only runs in the create case, and not in the find case. In other words, if the record is found, the block doesn't run. I tested it with this console code:

User.find_or_create_by_name("An Existing Name") do |u|
  puts "I'M IN THE BLOCK"
end

(nothing was printed). Is there any way to have the block run in both cases?

Answer

fl00r picture fl00r · Mar 28, 2011

As far as I understand block will be executed if nothing found. Usecase of it looks like this:

User.find_or_create_by_name("Pedro") do |u|
  u.money = 0
  u.country = "Mexico"
  puts "User is created"
end

If user is not found the it will initialized new User with name "Pedro" and all this stuff inside block and will return new created user. If user exists it will just return this user without executing the block.

Also you can use "block style" other methods like:

User.create do |u|
  u.name = "Pedro"
  u.money = 1000
end

It will do the same as User.create( :name => "Pedro", :money => 1000 ) but looks little nicer

and

User.find(19) do |u|
  ..
end

etc