Skip to content

Commit

Permalink
Fixing dynamic finders on associations to properly send arguments to …
Browse files Browse the repository at this point in the history
…the find_by_* method. Closes issue #330.

Commit fdfc8e3 introduced a bugfix to prevent additional values passed
to a dynamic find_or_create_by_x methods from confusing the finder.
This patch also broke the essential behavior of this method on an
association by incorrectly sending arguments to the find_by_x methods.
The finder method would always see its inputs as a single array of
values instead of individual arguments, almost guaranteeing that the
finder call would be incorrect, and that we'd always create a new
record instead.

This patch adds a splat operator to the parameter array we send along to
the dynamic finder so that it receives its inputs correctly, and
includes an additional test to ensure that repeated calls to
find_or_create_by_x only creates one new record.
  • Loading branch information
caseydreier committed Apr 28, 2011
1 parent b0be721 commit 9f7ff62
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 1 deletion.
Expand Up @@ -381,7 +381,7 @@ def method_missing(method, *args, &block)
when /^find_or_create_by_(.*)$/ when /^find_or_create_by_(.*)$/
rest = $1 rest = $1
find_args = pull_finder_args_from(DynamicFinderMatch.match(method).attribute_names, *args) find_args = pull_finder_args_from(DynamicFinderMatch.match(method).attribute_names, *args)
return send("find_by_#{rest}", find_args) || return send("find_by_#{rest}", *find_args) ||
method_missing("create_by_#{rest}", *args, &block) method_missing("create_by_#{rest}", *args, &block)
when /^create_by_(.*)$/ when /^create_by_(.*)$/
return create($1.split('_and_').zip(args).inject({}) { |h,kv| k,v=kv ; h[k] = v ; h }, &block) return create($1.split('_and_').zip(args).inject({}) { |h,kv| k,v=kv ; h[k] = v ; h }, &block)
Expand Down
Expand Up @@ -82,6 +82,15 @@ def test_find_or_create_by_with_additional_parameters
assert_equal 4, post.comments.length assert_equal 4, post.comments.length
end end


def test_find_or_create_by_with_same_parameters_creates_a_single_record
author = Author.first
assert_difference "Post.count", +1 do
2.times do
author.posts.find_or_create_by_body_and_title('one', 'two')
end
end
end

def test_find_or_create_by_with_block def test_find_or_create_by_with_block
post = Post.create! :title => 'test_find_or_create_by_with_additional_parameters', :body => 'this is the body' post = Post.create! :title => 'test_find_or_create_by_with_additional_parameters', :body => 'this is the body'
comment = post.comments.find_or_create_by_body('other test comment body') { |comment| comment.type = 'test' } comment = post.comments.find_or_create_by_body('other test comment body') { |comment| comment.type = 'test' }
Expand Down

0 comments on commit 9f7ff62

Please sign in to comment.