Find_Or_Create
May 19th, 2008
One of my very favorite rails methods is find_or_create. You can turn this tedious code:
review = Review.find_by_url(sitename)
if review.nil?
review = Review.new
review.url = sitename
review.staff_id = staff.id
review.save
end
Into this clean one liner:
Review.find_or_create_by_url(sitename, {:staff_id => staff.id})
The has_many :through blog has a great rundown on dynamic finders that I found really useful.
One point that got missed is that like the create method, find_or_create will autosave the new object to the database. This is unlike the new method which doesn’t create a new object in the database but rather creates a new object. Which of course means that you’ll need the save method to ensure your data gets back to the db. In this case, you may want to use find_or_initialize.
If you want to create a new object in the DB in one step (if doesn’t exist already), find_or_create is a great tool.
Entry Filed under: Ruby on Rails
6 Comments Add your own
Leave a Comment
Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
Trackback this post | Subscribe to the comments via RSS Feed

1. Radarek | October 23rd, 2008 at 2:30 pm
I tried find_or_create with :create_args params but it doesn’t work. Maybe it works with some plugin?
2. Adam Salter | January 16th, 2009 at 2:28 am
I’m also trying to do this… Rails 2.2.2
I get a ActiveRecord::UnknownAttributeError for create_args…
ie. create_args is not a valid attribute for find_or_create_by…
3. Adam Salter | January 16th, 2009 at 2:35 am
OK, I’ve got it.
It seems you don’t need :create_args at all… You do your find_by and any extra args are used in the create.
ie the above example should read:
Review.find_or_create_by_url(:url => sitename, :staff_id => staff.id)
4. Alex Grande | May 31st, 2009 at 6:40 pm
How do I do an else with find or create by?
Say I want to check if the item exists and if it doesn’t then I want to increase its popularity. So would I:
if review.nil?
#save it
else
#review.popularity++
end
??
5. Tyler Brown | June 15th, 2010 at 11:12 am
What if I want to find_or_create by more than one attribute? Say I have a model to handle a m:m relationship between Group & Member called GroupMember. I could have many entries where member_id = 4, but I don’t ever want there to be more than one entry where member_id = 4 and group_id = 7. Is it possible to do something like:
GroupMember.find_or_create(:member_id => 4, group_id => 7)
??
6. rifki fauzi | August 24th, 2010 at 12:39 am
@tyler
something like this :
GroupMember.find_or_create_by_member_id_and_group_id(4, 7)