Skip to content

Commit

Permalink
Allow belongs_to association names to be used in upsert params
Browse files Browse the repository at this point in the history
Fixes #186
  • Loading branch information
nviennot committed Feb 1, 2016
1 parent 2d7292b commit ae5b98b
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 1 deletion.
1 change: 1 addition & 0 deletions lib/no_brainer/criteria/first_or_create.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def upsert!(attrs, save_options={})

def _upsert(attrs, save_options)
attrs = attrs.symbolize_keys
attrs = model.association_user_to_model_cast(attrs)
unique_keys = get_model_unique_fields.detect { |keys| keys & attrs.keys == keys }
return where(attrs.slice(*unique_keys)).__send__(:_first_or_create, attrs, save_options) if unique_keys

Expand Down
10 changes: 10 additions & 0 deletions lib/no_brainer/document/association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ def inherited(subclass)
super
end

def association_user_to_model_cast(attrs)
Hash[attrs.map do |k,v|
association = association_metadata[k]
case association
when NoBrainer::Document::Association::BelongsTo::Metadata then association.cast_attr(k,v)
else [k,v]
end
end]
end

METHODS.each do |association|
define_method(association) do |target, options={}|
target = target.to_sym
Expand Down
9 changes: 9 additions & 0 deletions lib/no_brainer/document/association/belongs_to.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ def hook
add_callback_for(:after_validation)
end

def cast_attr(k, v)
return [k, v] if v.nil?
unless v.is_a?(target_model)
opts = { :model => owner_model, :attr_name => k, :type => target_model, :value => v }
raise NoBrainer::Error::InvalidType.new(opts)
end
[foreign_key, v.__send__(primary_key)]
end

def eager_load_owner_key; foreign_key; end
def eager_load_target_key; primary_key; end
end
Expand Down
14 changes: 13 additions & 1 deletion spec/integration/first_or_create_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@
end
end

context 'when matching a uniqueness validator' do
context 'when matching a uniqueness validator with validations' do
context 'when validations fail' do
before { SimpleDocument.field :field2, :required => true }

Expand All @@ -250,5 +250,17 @@
end
end
end

context 'when matching a uniqueness validator with a belongs_to' do
before { load_blog_models }
before { Comment.belongs_to :post, :uniq => true }
let(:post) { Post.create }

it 'upserts with model instances as foreign keys' do
Comment.upsert(:post => post)
Comment.upsert(:post => post)
Comment.count.should == 1
end
end
end
end

0 comments on commit ae5b98b

Please sign in to comment.