<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>The Vose Way: Tag find_or_create</title>
    <link>http://www.chuckvose.com/articles/tag/find_or_create</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>A Blog about Butter, Cheese, and all things Vosian</description>
    <item>
      <title>find_or_create by params (extension to dynamic attribute based finders)</title>
      <description>&lt;p&gt;Rails has a dynamic method where you can do find_or_create_by_attr_name(attr) but it the method names get incredibly long very quickly. So &lt;span class="caps"&gt;SJS&lt;/span&gt; wrote &lt;a href="http://sami.samhuri.net/2007/4/11/activerecord-base-find_or_create-and-find_or_initialize"&gt;this article&lt;/a&gt; in which he tries to remedy the situation. His solution was pretty elegant but it still only worked for fields that were already defined in the database; if you often redefine setter methods it doesn&amp;#8217;t work at all.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s my attempt to remedy the situation.&lt;/p&gt;


&lt;pre&gt;
module ActiveRecordExtensions
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def find_or_create(params)
      begin
        return self.find(params[:id])
      rescue ActiveRecord::RecordNotFound =&amp;gt; e
        attrs = {}

        # search for valid attributes in params
        self.column_names.map(&amp;#38;:to_sym).each do |attrib|
          # skip unknown columns, and the id field
          next if params[attrib].nil? || attrib == :id

          attrs[attrib] = params[attrib]
        end

        # call the appropriate ActiveRecord finder method
        found = self.send("find_by_#{attrs.keys.join('_and_')}", *attrs.values) if !attrs.empty?

        if found &amp;#38;&amp;#38; !found.nil?
          return found
        else
          return self.create(params)
        end
      end
    end
    alias create_or_find find_or_create
  end
end

ActiveRecord::Base.send(:include, ActiveRecordExtensions)
&lt;/pre&gt;

	&lt;h3&gt;Newb instructions&lt;/h3&gt;


	&lt;p&gt;Create a file called active_record_extensions.rb in your the lib directory. Then add `require &amp;#8216;active_record_extensions&amp;#8217;` to your environment.rb at the bottom (without the ``). Restart your server and see what happens!&lt;/p&gt;</description>
      <pubDate>Wed, 12 Sep 2007 22:40:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:4db3f875-4a45-44ae-b887-f86835021ebb</guid>
      <author>vosechu@create-on.com (Chuck Vose)</author>
      <link>http://www.chuckvose.com/articles/2007/09/12/find_or_create-by-params-extension-to-dynamic-attribute-based-finders</link>
      <category>Rails</category>
      <category>Programming</category>
      <category>Rails</category>
      <category>find_or_create</category>
      <category>dynamic</category>
      <category>attribute</category>
      <category>based</category>
      <category>finders</category>
      <category>ActiveRecord</category>
      <category>find</category>
      <category>create</category>
    </item>
  </channel>
</rss>

