Archive for the ‘rubyonrails’ Category

Issues with Active Scaffold and Rails 2.1, Solved

Saturday, June 28th, 2008

If you are looking to upgrade to Rails 2.1 and you are using Active Scaffold, be aware it still has a few rough edges.

Make sure you install the Rails 2.1 branch of Active Scaffold:


git clone git://github.com/activescaffold/active_scaffold
cd active_scaffold
git branch -r (just lists the branches)
git checkout origin/rails-2.1

(Check out the full thread for Rails 2.1 and Active Scaffold compatibility)

Second, I had to patch vendor/plugins/active_scaffold/lib/extensions/generic_view_path.rb. On line 53, make it look like this:


if !@template.controller.is_a?(ActionMailer::Base) && @template.controller.class.uses_active_scaffold?

I had to add !@template.controller.is_a?(ActionMailer::Base) &&

All my tests are now passing!

I still love Active Scaffold, even though it’s a bit behind the times.

Nest Those Rails Resources Or Make Baby Semantic Web Cry

Wednesday, April 2nd, 2008

Proper web architecture dictates that a you should “Assign distinct URIs to distinct resources.” And Cool URIs for the Semantic Web states that:

There should be no confusion between identifiers for Web documents and identifiers for other resources. URIs are meant to identify only one of them, so one URI can’t stand for both a Web document and a real-world object.

So we know that a URI should refer to one and only one resource. (Of course, you may have many URIs all referring to the same resource.) So why do so many web sites have URIs like http://www.example.org/myaccount? That same URI is used to refer to any account in the system, depending on who is logged in. And that makes Baby Semantic Web cry.

Why is the baby sobbing? A generic URI like http://www.example.com/myaccount isn’t useful on the semantic web, because it’s very difficult to make meaningful statements about that URI. Let’s go and try.


http://www.example.com/myaccount is the account page of "Seth Ladd".

and


http://www.example.com/myaccount is the account page of "Bob Smith".

Hmm… so http://www.example.com/myaccount is the account page for both Seth and Bob? That doesn’t make much sense!

A better URI for an account page would be http://www.example.com/accounts/23232, which is easily unique for every user.

The moral of this story is that every one of your URIs should be unique. So let’s bring this all the way back to Rails and resources.

When building your resources, ask yourself, “If I GET this URI, will I see the same thing no matter who is logged in?” If the answer is “No” then you need to nest your resources so that the URI is unique and the same representation is returned no matter who you are logged in as.

For example, a typical URI would be http://www.example.com/books, which could easily be a collection of books for the user. The contents of that URI are relative to the person logged in, so we have a problem. To fully qualify the URI, we need to nest books inside of the user collection. We end up with http://www.example.com/users/1/books, which is unique and follows web architecture best practices. Now we can say unambiguous statements about the URI, thus populating the semantic web with more useful and meaningful triples.

RSpec is Fun

Wednesday, March 19th, 2008

I’ve been using RSpec with my latest project, and it’s a welcome change from the traditional Test::Unit for Ruby.

RSpec is a more natural way to write tests for your software. It seems to be much easier to compose tests, and anything that makes testing easier is OK in my book.

A specific example of why I’m falling for RSpec:

You can easily group common tests together, and include this grouping in your main tests. Of course you can do this in any number of ways with Test::Unit, but RSpec makes it so clean and obvious.

Here’s an example of a very common set of tests that I need to run again all my controllers:


describe "Requires Authorization", :shared => true do
  describe "when not logged in" do

    describe "when accessing index page" do
      it "should redirect to login page" do
        get 'index'
        response.should redirect_to(new_session_path)
      end
    end

    describe "when accessing new database page" do
      it "should redirect to login page" do
        get 'new'
        response.should redirect_to(new_session_path)
      end
    end

    describe "when accessing show database page" do
      it "should redirect to login page" do
        get 'show'
        response.should redirect_to(new_session_path)
      end
    end

    describe "when accessing destroy database page" do
      it "should redirect to login page" do
        get 'destroy'
        response.should redirect_to(new_session_path)
      end
    end

  end
end

In each of my controller tests, I only need to include:


describe DatabasesController do

  it_should_behave_like "Requires Authorization"

Take a look at that! Reads just like English, I would say.

If you haven’t made the jump to RSpec, I’d seriously recommend you give it a shot. You don’t need to abandon all of you existing unit tests. Both sets of tests will run just fine in your Rails project.

Active Record, Parent-Child Relationships, and Validations

Wednesday, March 19th, 2008

I’ve been reading through Advanced Rails Recipes, and so far I like the book. It has a nice collection of tips and tricks for the experienced Rails developer. This is the kind of book that you have to quickly scan through when you get it, so you know what tips are available. Remembering that the book has the solution for your problem at hand is the tough part.

One common requirement for web frameworks is being able to handle nested forms on submit. It’s too common to present to the user a complex form, representing many different, usually nested, objects. The difficulty isn’t really in displaying or formatting the nested HTML form itself, but in handling the submit. How do you save or update all of the objects easily and efficiently? What if there’s an error?

The excellent and always useful RailsCasts had a series of episodes that handle the nested form issue (Complex Forms 1, Complex Forms 2, and Complex Forms 3).

There’s a problem with their approach, and it’s cause is validations. There’s a chicken-and-the-egg problem, in that if you wish to add a validates_presence_of :parent_id in your nested child object (which you should, because it helps to enforce referential integrity), then you will not be able to save the parent and the child objects with a simple call to parent.save

Remember, the whole point of the RailsCasts, and this general problem, is that we wish to easily handle nested forms when submitted. We want to create a parent and its children with one simple submit.

Here’s what happens, thought:

  1. class Parent has many Children, class Child belongs to Parent. Class Child also validates_presence_of parent_id
  2. create a new parent
  3. create a new child with parent.children.build()
  4. call parent.save
  5. the save will fail, because child is invalid, because parent_id is null, because validations for children are run before parents are saved (and thus, create a PK)

(oh, and did you know that when saving a new parent that has new children, the parent will cascade the validations down to the children automatically? I didn’t know this was automatic)

Getting back to Advanced Rails Recipes, the author included the Complex Forms examples from RailsCasts. And there’s no mention of this validation issue. So, being the good beta book tester that I am, I created an errata suggesting the mention this problem with validations.

Note, someone with the name of Mina Naguib mentioned this problem in the comments for Complex Forms 1, although I haven’t tried it out (and sorry for not linking to the comment, the RailsCasts blog doesn’t provide an id for each comment).

So, IMO, this is a common requirement of web frameworks that I don’t believe Rails has solved cleanly and elegantly yet. I’ll keep looking around for a good solution. Suggestions welcome!

How Not To Write An API

Wednesday, December 19th, 2007

So a future version of Rails will get Pluggable Controller Caching. That’s a good idea, and good on Rails for formalizing this extensibility. Better than monkey patching.

Looking at the implementation, though, leaves me cold. Let’s look at a code snippet:


 def read(name, options = nil)
    super
    @ether.get(name)
 end

With some commentary:

Invoking super for each method call ensures that the proper messages get logged for each action

Wow, way to trust your users! </sarcasm> Requiring a call to super is very bad practice. Any time you are relying on a client of your class to call something, you’re risking someone forgetting to make the call.

It’s better to use the Strategy Pattern. Here, you finalize the API method (here it is read) and provide an abstract method or your subclasses. Marking the method as final (which I don’t think you can do in Ruby, but I digress) ensures that a subclass can’t override your functionality, and the abstract internal method ensures that your client doesn’t have to call back to super.

Here’s how I’d fix it:


 def read(name, options = nil)
    # some logging and error handling
    read_internal(name, options)
 end

protected

def read_internal(name, options = nil)
  raise "Subclasses must implement this method"
end

Ta-da! No more forcing the user to call super, thus making your algorithm safe and well encapsulated.

SQL Server Adapter for Rails 2.0

Thursday, December 13th, 2007

UPDATE: Everything works now. Turns out I had a plugin installed that monkey patched the SQL Server Adapter. This plugin was from an older version of Rails, and the Rails 2.0 adapters now extend from AbstractAdapter. Fixing the parent class in my plugin monkey patch (to extend from AbstractAdapter) fixed this up and now I no longer get the error.

I just installed the SQL Server Adapter Gem from gems.rubyonrails.org for my new Rails 2.0 project:


gem install activerecord-sqlserver-adapter --source=http://gems.rubyonrails.org

When I attempt to use it, I receive this error message:


TypeError: superclass mismatch for class SQLServerAdapter
        from /var/lib/gems/1.8/gems/activerecord-sqlserver-adapter-1.0.0/lib/active_record/connection_adapters/sqlserver_adapter.rb:190
        from /usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
        from /usr/lib/ruby/1.8/rubygems/custom_require.rb:27:in `require'
        from /home/sladd/development/workspace/DSES2/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:496:in `require'
        from /home/sladd/development/workspace/DSES2/vendor/rails/activerecord/lib/../../activesupport/lib/active_support/dependencies.rb:342:in `new_constants_in'

Any ideas? My database.yml looks like this:


development:
  adapter: sqlserver
  mode: odbc
  dsn: dses_rollup
  username: sa
  password:

Has anyone successfully installed the new SQL Server adapter as a gem into a Rails 2.0 project?

I’ve asked the Ruby on Rails Talk Google Group, so we’ll see if that turns up any help.

Rails Bug With Has Many Collections Empty? and Build

Thursday, November 8th, 2007

After my long rant about problems in Ruby on Rails has_many collections and empty? calls, we spent some more time and really condensed the problem. I can explain this problem much more clearly now.

Let’s take the following code:


f = Foo.new
f.bars.build
f.bars.empty?
pp f.bars

What do you think will be printed out when we pp f.bars?

Well, if you’re like me, you’d think it would return an array with one Bar in it. And, if you were like me, you’d be wrong.

Turns out that the call to f.bars.empty? doesn’t realize you’ve ever added a new Bar to the collection of bars. Therefore, it will go into the database and do a select count(*) to determine the size of the collection. It will return zero, because at this point you haven’t saved anything into the database. Not only is going to the database to determine the size of the collection wrong (in the line above, I’ve added a Bar though build so empty? should know there’s at least one), but empty? in the process is caching the empty collection!

Because of this caching, our last line of code here is printing out an empty array. This effectively deletes the original Bar we added via build.

This has to be a bug. In fact, I’m filing a bug at Rails’ Trac system.

How do you work around this? Just change your usage of empty? to length.zero?:


f = Foo.new
f.bars.build
f.bars.length.zero?
pp f.bars

The above code will work just fine!

Many thanks to Wenyi for researching this with me.

When Empty Isn’t Empty With Rails Active Record Collections

Sunday, November 4th, 2007

So I’m writing some Rails code, just playing around, and I run into a very strange situation. I’ve found a situation where Rails’ Active Record code is calculating the results to empty? incorrectly, even if I add elements to the collection. So I had a has_many collection with elements inside of it, but calls to length or empty were returning 0 and true.

Here’s my simple models:


class Query < ActiveRecord::Base
  has_many :measures
  validates_presence_of :cube_name

  def measure_attributes=(attrs)
    attrs.each {|a| measures.build(a)}
  end
end

and


class Measure < ActiveRecord::Base
  belongs_to :query
  acts_as_list :scope => :query
  has_one :condition, :as => :conditionable
end

Notice that in Query, I’ve added a measure_attributes method which automatically handles the construction of new Measure instances from the form parameters.

Here’s the simple nested form. From the models, a Query has many Measures:



<% form_for :query, :url => {:action => :new} do |f| %>
	Cube Name: <%= f.text_field :cube_name %>

	<% @query.measures.each do |measure| %>
		<div>
		<% fields_for "query[measure_attributes][]", measure do |mf| %>
			Measure Name: <%= mf.text_field :name %>
		<% end %>
		</div>
	<% end %>

	<%= submit_tag %>
<% end %>

Here’s what I was doing in my controller. Again, very simple:


class QueriesController < ApplicationController
  def new
    @query = Query.new(params[:query])
    @query.measures.build if @query.measures.empty?
  end
end

Now, I wouldn’t normally have the new method handle it this way (I would have both a create and a new), but this was test code. My check against empty? was basically saying “if this is the first time I’ve hit this method, throw in a blank Measure so the form will show at least show one Measure.”

Well, it turns out, that call to empty? is calculated by checking the database! Here’s the actual query:


SELECT count(*) AS count_all FROM measures WHERE (measures.query_id = NULL)

Even though I added Measures via measure_attributes, ActiveRecord here doesn’t seem to acknowledge that at this point.

When I rendered the new template after the form is submitted, the loop in the RHTML (@query.measures.each) doesn’t iterate, because it thinks there’s no measures.

Sigh.

So, here’s what we learned. Don’t call length or empty? on an Active Record managed has_many collection unless you understand how it’s calculating the size of the contents (via the database). (Also, I still don’t quite understand when it goes to the database and when it uses the actual items I’ve manually added.)

Here’s the best way to handle this situation, completely avoiding the call to empty?:


class QueriesController < ApplicationController
  def new
    @query = Query.new(params[:query])
    # add one so the form will have something to render in the beginning
    @query.measures.build
  end

  def create
    @query = Query.new(params[:query])
    render :action => ‘new’
  end
end

QOTD

Sunday, September 23rd, 2007

7 reasons I switched back to PHP after 2 years on Rails

PROGRAMMING LANGUAGES ARE LIKE GIRLFRIENDS: THE NEW ONE IS BETTER BECAUSE *YOU* ARE BETTER

Rails and Nested Singular Resources

Tuesday, July 31st, 2007

One of the reasons I love Rails is the built in support for REST. If you’re not yet writing your Rails applications RESTfully, then you’re not really writing web applications.

I’ll detail an example that I just created which I thought illustrated REST support quite nicely. In Rails, you can model singular or plural Resources. A plural Resource might be Users, which means you’ll have lots of Users in your system. In contrast, you can create singular Resources when there is only one instance of that Resource in the system.

A good example of a singular resource is an User’s avatar icon. For instance, most Web 2.0 applications let you upload a tiny picture that represents you. In Rails speak, we say a User has one Avatar Icon. An Avatar Icon belongs to a User.

When creating the URI space for these models (User, AvatarIcon) you use map.resources and map.resource inside of your routes.rb file. We want to enforce that an AvatarIcon belongs to an User in the URI space, and thus the modeling of the Resource. We can do that with the below routes:

  map.resources :users do |user|
    user.resource :avatar_icon
  end

Our URIs will look like this now:

  • /users - list all users
  • /users/1 - show a single user
  • /users/1/avatar_icon - a user’s avatar icon

You can see the difference between singular and plural even in the URIs. /users is plural to indicate that it identifies the collection of all users in the system. On the other hand, /users/1/avatar_icon is singular indicating that it identifies the single avatar icon for a single user.

Furthermore, when you use map.resources, Rails will create named routes for you. This makes referring to the URIs for the Resources much easier, as they are given logical, proper names. Now, here’s where I think it gets really cool. Refer to the routes example above, where we nested the avatar_icon resource inside the users resource. When we want to create the URI /users/1/avatar_icon, we can use the generated named route avatar_icon_path(@user).

Notice how we only need to specify the user in question when building the URI to a user’s avatar icon. There’s no ID for the avatar icon in the URI, so why specify that in the named route? When I saw that, I said, “Yes, that’s exactly how I would expect it to work.”

Way to go, Rails! Making RESTful development a first class citizen for web applications.