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=""> <s> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed


Pages

Tweets

What does “making it” mean to you? When is what you have enough? The reality isn’t as glamorous, or as meaningful, or as fulfilling as it appears. twitter.com/aspleenic/stat…

Last month from Liana Leahy's Twitter via Twitter for iPhone

Meta