bcardarella / valid_attribute

Minimalist validation BDD for ActiveModel specs
178 stars 18 forks source link

MongoMapper EmbeddedDocument edge case involving _root_document #22

Closed bricestacey closed 12 years ago

bricestacey commented 12 years ago

I am writing a validation for a MongoMapper embedded document. It looks something like so:

if _root_document.settings.select { |s| s.feature_id == feature_id && s.name == name }.size > 1
  errors.add(:name, 'is not unique')
end

If I then try to test this using valid_attribute like so:

describe Setting do
  before do
    @feature = FactoryGirl.create(:feature)
    @feature.settings << subject
  end

  context 'given a setting with the name limit already exists' do
    before { @feature.settings << FactoryGirl.build(:setting, name: 'limit') }
    it { should_not have_valid(:name).when('limit') }
  end
end

It will fail even though it actually doesn't. The problem seems to stem from how valid_attribute clones the subject and then performs validations. At that point, the feature's embedded settings do not contain a reference to the cloned subject, but to the actual subject and so valid_attribute wrongly believes the setting is valid.

I've worked around this by emulating the behavior of valid_attribute without cloning and it works.

It's an obvious edge-case, not sure if it's worth working around, but wanted to let you know.

bcardarella commented 12 years ago

So there might need to be some adapter for the object cloning to pull in any embedded documents. Now that you brought this up I suspect the same problem will happen with ActiveRecord objects that also have associations that need to be validated against.

bcardarella commented 12 years ago

This should be solved with: 1f526c21be6498c6fe17764960c95a8450e1f492

I have turned off cloning by default and it can be forced by doing:

it { should have_valid(:name).when('Brian').clone }