Reputation: 1568
I want a simple way to test my validations. My test focus are integrations, not validations, and I don't working with TDD. That being said, I want to replace:
# Estate model specs
describe "#name" do
it "is required" do
estate.name = nil
estate.valid?
expect(estate.errors).to have_key(:name)
end
end
describe "#company" do
it "is required" do
estate.company = nil
estate.valid?
expect(estate.errors).to have_key(:company)
end
end
# and so on..
to some like:
# Estate model specs
requiredFields = [:name, :company, :price, :region, :regions, :typologies, :image]
requiredFields.each do |requiredField|
describe "##{requiredField}" do
it "is required" do
estate[requiredField] = nil
estate.valid?
expect(estate.errors).to have_key(requiredField)
end
end
end
The fields name and price works, the problem is in associations:
Estate
is an instance of Estate
validations
with required fields
should be valid
#name
is required
#company
is required (FAILED - 1)
#price
is required
#region
is required (FAILED - 2)
...
I think that problem is estate[requiredField]
. If I change to company_id will work. How can I do something like estate.requiredField
in foreach?
Upvotes: 0
Views: 80
Reputation: 12818
Try to use object.send
estate.send("#{requiredField}=", value) # setter, estate.requiredField=value
estate.send(requiredField) # getter, estate.requiredField
Or use https://github.com/thoughtbot/shoulda-matchers for such kind of tests
Upvotes: 1
Reputation: 18803
You can perform estate.requiredField
using Ruby's send
method, which invokes its argument as a method on the receiver:
estate.send(requiredField)
Since you're assigning, you'll need to interpolate an =
into the field name. The foo=
method takes an argument, which you pass as continued arguments to send
after the method name:
estate.send("#{requiredField}=", nil)`
Something to be aware of is that since send
ends up calling the requested method from within the receiver, you might end up bypassing protected
or private
methods.
class Dog
private
def bark
puts 'Woof'
end
end
Dog.new.bark
# NoMethodError: private method 'bark' called for #<Dog:0x007fd28bad7590>
Dog.new.send :bark
# Woof
Upvotes: 2