I have two rails active record classes, School and Instructor linked by a has_and_belongs_to_many relationship.
I need to query my instructors_controller for instructors for a particular school and return an xml format response. Therefore, in the index method I have this code fragment:
school = School.find(params[:school_id]) @instructors = school.instructors
and later:
respond_to do |format| format.html # index.html.erb format.xml { render :xml => @instructors } format.json { render :json => @instructors } end
But it doesn't work. Look at this intriguing but baffling sequence:
ruby-1.9.2-p180 :023 > Instructor.all.first => #<Instructor id: 1, name: "Mrs. Smith", instructor_type_id: 1, created_at: "2011-07-24 18:19:40", updated_at: "2011-07-24 18:19:40"> ruby-1.9.2-p180 :026 > Instructor.all.first.class => Instructor(id: integer, name: string, instructor_type_id: integer, created_at: datetime, updated_at: datetime) ruby-1.9.2-p180 :024 > School.first.instructors.first => #<Instructor id: 1, name: "Mrs. Smith", instructor_type_id: 1, created_at: "2011-07-24 18:19:40", updated_at: "2011-07-24 18:19:40"> ruby-1.9.2-p180 :025 > School.first.instructors.first.class => Instructor(id: integer, name: string, instructor_type_id: integer, created_at: datetime, updated_at: datetime) ruby-1.9.2-p180 :021 > Instructor.all.first.to_xml => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<instructor>\n <created-at type=\"datetime\">2011-07-24T18:19:40Z</created-at>\n <id type=\"integer\">1</id>\n <instructor-type-id type=\"integer\">1</instructor-type-id>\n <name>Mrs. Smith</name>\n <updated-at type=\"datetime\">2011-07-24T18:19:40Z</updated-at>\n</instructor>\n"
Now for the punchline:
ruby-1.9.2-p180 :019 > School.first.instructors.first.to_xml NoMethodError: undefined method `type' for nil:NilClass from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activesupport-3.0.9/lib/active_support/whiny_nil.rb:48:in `method_missing' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activerecord-3.0.9/lib/active_record/serializers/xml_serializer.rb:230:in `compute_type' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:22:in `initialize' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:75:in `new' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:75:in `block in serializable_attributes' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:74:in `each' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:74:in `map' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:74:in `serializable_attributes' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:116:in `add_attributes_and_methods' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:103:in `block in serialize' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/builder-2.1.2/lib/builder/xmlbase.rb:134:in `call' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/builder-2.1.2/lib/builder/xmlbase.rb:134:in `_nested_structures' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/builder-2.1.2/lib/builder/xmlbase.rb:58:in `method_missing' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/builder-2.1.2/lib/builder/xmlbase.rb:31:in `tag!' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activemodel-3.0.9/lib/active_model/serializers/xml.rb:102:in `serialize' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/activerecord-3.0.9/lib/active_record/serializers/xml_serializer.rb:175:in `to_xml' from (irb):19 from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/railties-3.0.9/lib/rails/commands/console.rb:44:in `start' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/railties-3.0.9/lib/rails/commands/console.rb:8:in `start' from /usr/local/rvm/gems/ruby-1.9.2-p180@blueprint/gems/railties-3.0.9/lib/rails/commands.rb:23:in `<top (required)>' from script/rails:6:in `require' from script/rails:6:in `<main>'ruby-1.9.2-p180 :020 > Instructor.all.first.to_xml
What's going on here ?
Edit: Well, switching from xml to json solved the problem, (to_json does not exhibit the same strangeness as to_xml here), although I would still like to know the explanation for the above behavior.
Also, as I am relatively new to Rails, is there a better way to do what I want to do here ?