Archive for February, 2008

Small Rspec revelations, RJS

Friday, February 29th, 2008

The closing scene of this series. Specing RJS templates. Again a topic which is not on the forefront of the RSpec community.  And again a blog post saved the day. It took me a little bit of time for figure out what kind of RJS type the response object should expect. To illustrate an example RSpec:


response.should have_rjs(:chained_replace_html, "some_id") do
response.should have_text(/some random text/)
end

The response object should have an RJS object but what type? According to the assert_select_rjs method, which the have_rjs method wraps, there are only a hand full of these types but apparently not all of them are listed. As I found out when my inline RJS:


render :update do |page|
page[update_div].update(text)
end

None of the mentioned types responded correctly. But I noticed that the blog post mentioned earlier used an other type. Browsing through the source code of assert_select_rjs I found my missing type: chained_replace_html. Hooray! Everything worked fine and dandy from there on.

One last hiccup was that code in the block passed to the have_rjs method does not scope by default the response.should directive, so this is wrong:


response.should have_rjs(:chained_replace_html, "some_id") do
have_text(/some random text/)
end

Obviously.

Small Rspec revelations, Modules

Wednesday, February 27th, 2008

It looks like this is going to be a three parter. For our current project we wanted to abstract some of the functionality which appeared in our models to a module. As we are taking TDD more seriously nowadays I set out to write a spec for the module first. Right. For a normal spec you need an instance of the object you are specing. But by their very nature models can not be instantiated! So how to write a spec then? Here you go:


before(:each) do
klass = Class.new { include FicklePricing }
@foo = klass.new
@foo.stub!(:id).and_return(1)
end

In this case we have created a class with does nothing but to include our module. And this almost empty class can by instantiated and used in this specs. Trivial example:


it "should respond_to price method" do
@item.should respond_to(:get_price)
end

Small Rspec revelations, ActionMailer

Tuesday, February 26th, 2008

At the office we are getting more and more serious about RSpec . Today we ran into two things we had not done so far. Specing an ActionMailer and a module. The Rails Way only covered Test::Unit and that looked dreadful. Way to much code. I still think I should be coding applications not tests. A quick google turned up not so much, nor did the RSpec site help. Fortunately someone on the RSpec mailinglist brought the subject up. With that I knew enough to get the tests working.


before(:each) do
ActionMailer::Base.delivery_method = :test
ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.deliveries = []
end

This before block set the method for delivery method to :test. Normally it default to :smtp and an other possibility is :sendmail. The second directive tells ActionMailer to actually send the emails(who would have guessed?). The deliveries array keeps track of every email sent.

Now you can just send your email as you usually would:


mail = Notifications.deliver_some_random_email("name")
ActionMailer::Base.deliveries.size.should == 1
mail.body.should =~ /name/

Rock on RSpec.

Building a RESTful CMS

Thursday, February 21st, 2008

Today is the day we at Innovationfactory finish the development of a site maintained by a CMS. As this was the first CMS we build in RESTful Rails initially we where unsure how to proceed. There is some discussion(and here and here) on whether or not the admin functionality should be seperated from the non admin functionality. On one hand this makes sense. As an admin you are doing something vastly different than a normal user visiting the site. On the other hand it doesn’t. Both the admin and visitor interact with the same resources. Only the view and options presented are differtent. In the end we choose to seperate the admin functionality from the visitors functionality, thus creating two controllers for one resource. We deemed this better as the underlying resource is still the same but the interaction is different. And interaction is taken care of in a controller. Hence two controllers for two distinct way of interacting with our resources.