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

  • 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)

Leave a Comment

Required

Required, hidden

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


Pages

Tweets

So many thoughtful, engaging, insightful, hilarious, conversations tonight with friends I've just met. This is what #railsconf is all about.

About 15 minutes ago from Liana Leahy's Twitter via Twitter for iPhone

Meta