find_or_build_by

written by Jan on August 20th, 2007 @ 03:27 PM

I recently discovered that ActiveRecord has a function Object.find_or_create_by_something. Great function, it really simplified some code at my part. One problem I had with it, thought, was when I assigned a theme as a part of a habtm relationship. Here’s an example:

1
2
3
4
5

post = Post.new
post.name = "Test Post"
post.categorie << Category.find_or_create_by_name('Whatever')
post.save!

The Category ‘Whatever’ gets created before the post is saved, thus validated. When I have an invalid post, the category is created anyhow. This is OK for Admin-input, but when users can do this, it’s not great. That’s why I wrote my own solution to the problem: Category.find_or_build_by_name(‘Whatever’). Here’s the code (not yet a plugin):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

module FindOrBuildBy
  def self.included(base)
    base.extend ClassMethods
    
    class << base
      alias_method_chain :method_missing, :build_by
    end
  end
  
  module ClassMethods
    def method_missing_with_build_by(method, *args, &block)
      method.to_s =~ /^find_or_build_by_(.*)$/ or return method_missing_without_build_by(method, *args, &block)
      
      fields = $1.split('_')
      values = args.slice!(0,fields.size)
      options = args[-1] || {}
      
      conditions = fields.inject({}) do |hash, name|
        hash.merge name.to_sym => values[fields.index(name)]
      end
      
      options.merge! :conditions => conditions
      
      find(:first, options) || self.new(conditions)
    end
  end
end

ActiveRecord::Base.send :include,FindOrBuildBy


Comments are closed

Options:

Size