SEP | NOV | DEC
| 24 |
2006 | 2007 | 2008

7 captures 18 Aug 07 - 29 Mar 08 |

Close Help

# sjs

## geeky ramblings

## ActiveRecord::Base.find_or_create and find_or_initialize 0

Posted by sjs
on Wednesday, April 11

I’ve extended ActiveRecord with `find_or_create(params)` and `find_or_initialize(params)`. Those are actually just wrappers around `find_or_do(action, params)` which does the heavy lifting.

They work exactly as you’d expect them to work with possibly one gotcha. If you pass in an `id` attribute then it will just find that record directly. If it fails it will try and find the record using the other params as it would have done normally.

Enough chat, here’s the self-explanatory code:

    1
    2
    3
    4

    # extend ActiveRecord::Base with find_or_create and find_or_initialize.
    ActiveRecord::Base.class_eval do
      include ActiveRecordExtensions
    end

    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41

    module ActiveRecordExtensions
      def self.included(base)
        base.extend(ClassMethods)
      end

      module ClassMethods
        def find_or_initialize(params)
          find_or_do('initialize', params)
        end

        def find_or_create(params)
          find_or_do('create', params)
        end

        private

        # Find a record that matches the attributes given in the +params+ hash, or do +action+
        # to retrieve a new object with the given parameters and return that.
        def find_or_do(action, params)
          # if an id is given just find the record directly
          self.find(params[:id])

        rescue ActiveRecord::RecordNotFound => e
          attrs = {}     # hash of attributes passed in params

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

            attrs[attrib] = params[attrib]
          end

          # no valid params given, return nil
          return nil if attrs.empty?

          # call the appropriate ActiveRecord finder method
          self.send("find_or_#{action}_by_#{attrs.keys.join('_and_')}", *attrs.values)
        end
      end
    end

Continue reading...

- Tags: activerecord coding rails ruby
- Meta: 0 comments, permalink

##### Comments

Leave a response

Comment

Name:

Email Address:

Website:

Comment: