Skip to content
This repository
Browse code

Add find_or_create_by_* and find_or_initialize_by_* to relations

  • Loading branch information...
commit d511de0261003aae4913e3c24f76df6e03a35916 1 parent 8829d6e
Pratik lifo authored
23 activerecord/lib/active_record/relation.rb
@@ -142,6 +142,8 @@ def method_missing(method, *args, &block)
142 142
143 143 if match.finder?
144 144 find_by_attributes(match, attributes, *args)
  145 + elsif match.instantiator?
  146 + find_or_instantiator_by_attributes(match, attributes, *args, &block)
145 147 end
146 148 else
147 149 super
@@ -159,6 +161,27 @@ def find_by_attributes(match, attributes, *args)
159 161 end
160 162 end
161 163
  164 + def find_or_instantiator_by_attributes(match, attributes, *args)
  165 + guard_protected_attributes = false
  166 +
  167 + attributes_for_create = conditions = attributes.inject({}) {|h, a| h[a] = args[attributes.index(a)]; h}
  168 +
  169 + if args[0].is_a?(Hash)
  170 + guard_protected_attributes = true
  171 + conditions = args[0].with_indifferent_access.slice(*attributes).symbolize_keys
  172 + end
  173 +
  174 + record = where(conditions).first
  175 +
  176 + unless record
  177 + record = @klass.new { |r| r.send(:attributes=, attributes_for_create, guard_protected_attributes) }
  178 + yield(record) if block_given?
  179 + record.save if match.instantiator == :create
  180 + end
  181 +
  182 + record
  183 + end
  184 +
162 185 def create_new_relation(relation, readonly = @readonly, preload = @associations_to_preload, eager_load = @eager_load_associations)
163 186 Relation.new(@klass, relation, readonly, preload, eager_load)
164 187 end
21 activerecord/test/cases/relations_test.rb
@@ -254,5 +254,26 @@ def test_dynamic_find_all_by_attributes
254 254 assert_kind_of Array, davids
255 255 assert_equal [authors(:david)], davids
256 256 end
  257 +
  258 + def test_dynamic_find_or_initialize_by_attributes
  259 + authors = Author.scoped
  260 +
  261 + lifo = authors.find_or_initialize_by_name('Lifo')
  262 + assert_equal "Lifo", lifo.name
  263 + assert lifo.new_record?
  264 +
  265 + assert_equal authors(:david), authors.find_or_initialize_by_name(:name => 'David')
  266 + end
  267 +
  268 + def test_dynamic_find_or_create_by_attributes
  269 + authors = Author.scoped
  270 +
  271 + lifo = authors.find_or_create_by_name('Lifo')
  272 + assert_equal "Lifo", lifo.name
  273 + assert ! lifo.new_record?
  274 +
  275 + assert_equal authors(:david), authors.find_or_create_by_name(:name => 'David')
  276 + end
  277 +
257 278 end
258 279

0 comments on commit d511de0

Please sign in to comment.
Something went wrong with that request. Please try again.