For proper attribution, I'll note that a whole lot of the code in this post came directly from or was inspired by Multiple Table Inheritance with ActiveRecord.
In this post, I will show how to make EventBase attributes directly accessible from any class that calls acts_as_event (in my case, Event and Trip).
The Test
So, I start out by writing the test I want to be able to pass:
require 'spec_helper'
describe Trip do
describe "responds to" do
end
describe "functions properly" do
it " - saves EventBase correctly" do
tcount_before = Trip.find(:all).count
ebcount_before = EventBase.find(:all).count
@t = Trip.create
tid = @t.id
@t.respond_to?("event_base").should be_true
@t.save.should be_false
@t.event_base.description = "test description"
@t.save.should be_true
@dbt = Trip.find(@t.id)
@dbt.event_base.description.should == "test description"
Trip.find(:all).count.should == tcount_before + 1
EventBase.find(:all).count.should == ebcount_before + 1
@dbt.destroy
Trip.find(:all).count.should == tcount_before
EventBase.find(:all).count.should == ebcount_before
end
it " - can access attributes correctly" do
@t = Trip.create
@t.description = "test description"
@t.save.should be_true
@dbt = Trip.find(@t.id)
@dbt.description.should == "test description"
end
end
end
Here's what's new in the test:- I attempt to set the .description attribute directly on @t.
- I attempt to save @t.
- I retrieve the Trip record as @dbt
- I attempt to read the .description attribute
$ rspec trip_spec.rb --format documentation$ rspec trip_spec.rb --format documentation
I get:
Trip
functions properly
- saves EventBase correctly
- can access attributes correctly (FAILED - 1)
Failures:
1) Trip functions properly - can access attributes correctly
Failure/Error: @t.description = "test description"
NoMethodError:
undefined method `description=' for #
# ./trip_spec.rb:39:in `block (3 levels) in '
Finished in 0.47995 seconds
2 examples, 1 failure
Oh no! The test fails. Well, yeah, of course. Because I haven't done anything yet to make the attributes directly accessible...
Adding in Method Missing
So, our clue on how to fix this lies in the error message. Specifically, it says NoMethodError: undefined method `description='
Naturally, Trip doesn't have a .description method. The .description method is defined in EventBase. So, basically, what we need to do is to send missing method calls along to EventBase.
I did this by adding the following to InstanceMethods within the ActsAsEvent module:
module InstanceMethods
def event_base_with_build
event_base_without_build || build_event_base
end
def validate_event_base_properties
unless event_base.valid?
event_base.errors.each do |attr, message|
errors.add(attr, message)
end
end
end
def method_missing(meth, *args, &blk)
event_base.send(meth, *args, &blk)
rescue NoMethodError
super
end
end # InstanceMethods
Now when I run:
$ rspec trip_spec.rb --format documentation
I get:
Trip
functions properly
- saves EventBase correctly
- can access attributes correctly
Finished in 0.49288 seconds
2 examples, 0 failures
Success!
No comments:
Post a Comment