How to monkey patch Commontator::Comment (or any rails engine)? - ruby-on-rails

I just recently learned the term monkey patching, so I'm not sure if I have it right.
I am using the Commontator gem to provide commenting functionality on my Blog (Monologue::Post models) and my other models. I ran into an issue where I was trying to get the parent object from my comment (ie, what was commented on). It looks like I would have to do three joins. Rather than call that in my controller, I thought I could extend the gem's model to have a function comment_parent that would return the parent model.
I have this:
# config/initializers/comment_model_extenders.rb
module Commontator
class Comment < ActiveRecord::Base
def comment_parent
# do some magic
"return parent here"
end
end
end
I must be doing it wrong, because I am getting this error:
irb(main):010:0> c=Commontator::Comment
=> Commontator::Comment(id: integer, creator_type: string, creator_id: integer, editor_type: string, editor_id: integer, thread_id: integer, body: text, deleted_at: datetime, cached_votes_up: integer, cached_votes_down:
integer, created_at: datetime, updated_at: datetime)
irb(main):011:0> c.comment_parent
NoMethodError: undefined method `comment_parent' for #<Class:0xab743d0>
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.1.8/lib/active_record/dynamic_matchers.rb:26:in `method_missing'
from (irb):11
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/console.rb:90:in `start'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/console.rb:9:in `start'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:69:in `console'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
EDIT:
Based off of Fredrick's comments, I changed my code to be
...
def self.comment_parent
...
but the output is as follows:
irb(main):022:0* c=Commontator::Comment
=> Commontator::Comment(id: integer, creator_type: string, creator_id: integer, editor_type: string, editor_id: integer, thread_id: integer, body: text, deleted_at: datetime, cached_votes_up: integer, cached_votes_down:
integer, created_at: datetime, updated_at: datetime)
irb(main):023:0> c.comment_parent
=> "return parent here"
irb(main):024:0> test = c.find(1)
Commontator::Comment Load (35.7ms) SELECT "commontator_comments".* FROM "commontator_comments" WHERE "commontator_comments"."id" = $1 LIMIT 1 [["id", 1]]
=> #<Commontator::Comment id: 1, creator_type: "User", creator_id: 2, editor_type: nil, editor_id: nil, thread_id: 2, body: "Love this parser.", deleted_at: nil, cached_votes_up: 0, cached_votes_down: 0, created_at: "201
5-02-12 22:04:48", updated_at: "2015-02-12 22:04:48">
irb(main):025:0> test.comment_parent
NoMethodError: undefined method `comment_parent' for #<Commontator::Comment:0xad08a10>
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activemodel-4.1.8/lib/active_model/attribute_methods.rb:435:in `method_missing'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.1.8/lib/active_record/attribute_methods.rb:213:in `method_missing'
from (irb):25
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/console.rb:90:in `start'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/console.rb:9:in `start'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:69:in `console'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'

Looking at the library, your parent object has_one :thread, :as => :commontable, while the thread has_many :comments.
So, inside a Comment, thread.commontable should get you the other way around back up to your original parent.

Based on the comments, here is my solution:
In general, I wanted it to be called as an instance method, so my original code was correct. I was just calling it wrong. To call an instance method, do one of these:
Model.new.custom_method
or
my_model = Model.new #or .find(n)
my_model.custom_method
For my specific case, I found this solution:
module Commontator
class Comment < ActiveRecord::Base
def comment_parent
# do some magic
thread = Commontator::Thread.find(self.thread_id)
parent_class = thread.commontable_type.camelize.constantize
parent_class.find(thread.commontable_id)
end
end
end

Related

Testing model that acts_as_nested_set with RSpec

I have an Organization model that acts_as_nested_set, using awesome_nested_set:
class Organization < ActiveRecord::Base
acts_as_nested_set
attr_accessible :name, :location_id, :parent_id
has_many :org_prod_relationships, dependent: :destroy
has_many :products, through: :org_prod_relationships
def has_product?(prod)
org_prod_relationships.find_by_product_id(prod.id)
end
def add_product!(prod)
org_prod_relationships.create!(product_id: prod.id)
end
def publish_product!(prod)
self.descendants.each do |d|
d.add_product!(prod)
end
end
end
How can I write a test in RSpec for publish_product!, and/or is this the wrong approach to creating org_product_relationships in a nested set, and therefore hard to test? My non-working attempt is here (clipped from the larger spec file) https://gist.github.com/3911555.
EDIT: Updating to include the error message. Note, lines 79 and 80 are:
it { should have_product(product) }
its(:products) { should include(product) }
in the gist.
Failures:
1) Organization publishes_product
Failure/Error: it { should have_product(product) }
expected #has_product?(#<Product id: 34, name: "floo powder", created_at: "2012-10-21 14:15:08", updated_at: "2012-10-21 14:15:08", photo_file_name: nil, photo_content_type: nil, photo_file_size: nil, photo_updated_at: nil>) to return true, got false
# ./spec/models/organization_spec.rb:79:in `block (3 levels) in <top (required)>'
2) Organization publishes_product products
Failure/Error: its(:products) { should include(product) }
expected [] to include #<Product id: 35, name: "floo powder", created_at: "2012-10-21 14:15:08", updated_at: "2012-10-21 14:15:08", photo_file_name: nil, photo_content_type: nil, photo_file_size: nil, photo_updated_at: nil>
Diff:
## -1,2 +1,2 ##
-[#<Product id: 35, name: "floo powder", created_at: "2012-10-21 14:15:08", updated_at: "2012-10-21 14:15:08", photo_file_name: nil, photo_content_type: nil, photo_file_size: nil, photo_updated_at: nil>]
+[]
# ./spec/models/organization_spec.rb:80:in `block (3 levels) in <top (required)>'
Finished in 29.93 seconds
184 examples, 2 failures
Failed examples:
rspec ./spec/models/organization_spec.rb:79 # Organization publishes_product
rspec ./spec/models/organization_spec.rb:80 # Organization publishes_product products
I think you have to reload an object. Try the following:
#organization.products.reload
After you publish products in the before statements. Basically once the #organization is saved, calling #organization.products has a force_reload=false. Reference: http://guides.rubyonrails.org/association_basics.html#has_many-association-reference
Also since you asked, given that you have set up the relationships, you actually should be able to define your methods using the products relationship:
def has_product?(prod)
products.include? prod
end
def add_product!(prod)
products << prod
end
I think if you define the methods that way, you may not have to reload because the organization.products association is already updated.
Hope that helps.

How to solve the method missing error in rails console

I've a model Dish and PriceDeal as follows
class Dish < ActiveRecord::Base
has_one :price_deal
end
class Dish < ActiveRecord::Base
belongs_to :dish
end
In rails console, I want to retrive the discountPercent value like this.
1.9.2p290 :130 > pd=PriceDeal.find(17)
=> #<PriceDeal id: 17, name: "deal1", description: "my deal1", discountPercent: 20.0, discountCash: nil, dish_id: 2, created_at: "2012-03-22 07:42:08", updated_at: "2012-04-16 11:16:49">
1.9.2p290 :131 > pd.discountPercent
=> 20.0
I got the expected result.
But when I try to get the value like this,
1.9.2p290 :132 > pd1 = PriceDeal.where(:dish_id => 2)
=> [#<PriceDeal id: 17, name: "deal1", description: "my deal1", discountPercent: 20.0, discountCash: nil, dish_id: 2, created_at: "2012-03-22 07:42:08", updated_at: "2012-04-16 11:16:49">]
1.9.2p290 :133 > pd1.discountPercent
NoMethodError: undefined method `discountPercent' for #<ActiveRecord::Relation:0xa134958>
from /home/ragunathjawahar/.rvm/gems/ruby-1.9.2-p290#rails3tutorial/gems/activerecord-3.0.11/lib/active_record/relation.rb:374:in `method_missing'
from (irb):133
from /home/ragunathjawahar/.rvm/gems/ruby-1.9.2-p290#rails3tutorial/gems/railties-3.0.11/lib/rails/commands/console.rb:44:in `start'
from /home/ragunathjawahar/.rvm/gems/ruby-1.9.2-p290#rails3tutorial/gems/railties-3.0.11/lib/rails/commands/console.rb:8:in `start'
from /home/ragunathjawahar/.rvm/gems/ruby-1.9.2-p290#rails3tutorial/gems/railties-3.0.11/lib/rails/commands.rb:23:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
I got error,
How to get the value of discountPercent from pd1.
Thanks.
The reason why this is happening is because when you use where, you get back not a single object of type PriceDeal, but you get an object of type ActiveRecord::Relation, which for all intents and purposes is an array.
Notice how you got:
[#<PriceDeal id: 17, name: "deal1", ... >]
Instead of just:
#<PriceDeal id: 17, name: "deal1", ... >
The braces ([]) mean that it's an array. So you'll have to do this:
pd1.first.discountPercent
The reason why the where method returns an array is because you can have multiple items returned. Imagine doing:
PriceDeal.where("discountPercent >= 0")
You'd probably get a lot of records from that.
pd=PriceDeal.find(17)
It will return only one particular column.so you will not get no method error.
when you are using Modelname.where("conditions").The results will be array.so you will get no method error.Because your method is not present to array.

Mongoid giving error while saving field with particular name

I am using mongoid in rails app. rails 3.0.10 ruby 1.9.2p0
When I am trying to use field like "test", "link", "desc" etc.
say
Content.new(:test => 'ggg')
Content.new(:link => 'ggg')
Content.new(:desc => 'ggg')
Content is model which uses "Mongoid::Document"
it gives following error. (this error is for field "test")
I think mongoid uses some library which contents above field names as functions which
might create problem. Is there any way to come around this problem.
ArgumentError: wrong number of arguments (0 for 2..3)
from /usr/lib/ruby/gems/1.9.1/gems/activemodel-3.0.10/lib/active_model/dirty.rb:155:in `test'
from /usr/lib/ruby/gems/1.9.1/gems/activemodel-3.0.10/lib/active_model/dirty.rb:155:in `attribute_will_change!'
from /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.2.4/lib/mongoid/attributes.rb:102:in `block (2 levels) in write_attribute'
from /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.2.4/lib/mongoid/attributes.rb:100:in `tap'
from /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.2.4/lib/mongoid/attributes.rb:100:in `block in write_attribute'
from /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.2.4/lib/mongoid/attributes.rb:170:in `assigning'
from /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.2.4/lib/mongoid/attributes.rb:98:in `write_attribute'
from /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.2.4/lib/mongoid/attributes/processing.rb:95:in `process_attribute'
from /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.2.4/lib/mongoid/attributes/processing.rb:25:in `block in process'
from /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.2.4/lib/mongoid/attributes/processing.rb:23:in `each_pair'
from /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.2.4/lib/mongoid/attributes/processing.rb:23:in `process'
from /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.2.4/lib/mongoid/document.rb:128:in `block in initialize'
from /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.2.4/lib/mongoid/relations/builders.rb:47:in `building'
from /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.2.4/lib/mongoid/document.rb:125:in `initialize'
from (irb):1:in `new'
from (irb):1
from /usr/lib/ruby/gems/1.9.1/gems/railties-3.0.10/lib/rails/commands/console.rb:44:in `start'
from /usr/lib/ruby/gems/1.9.1/gems/railties-3.0.10/lib/rails/commands/console.rb:8:in `start'
from /usr/lib/ruby/gems/1.9.1/gems/railties-3.0.10/lib/rails/commands.rb:23:in `<top (required)>'
from /home/harshal/simple-cms/branches/1.0/script/rails:6:in `require'
from /home/harshal/simple-cms/branches/1.0/script/rails:6:in `<top (required)>'
from -e:1:in `load'
from -e:1:in `<main>'
Using the latest everything, ruby(1.9.3), rails(3.2.3), mongoid(2.4.7) I tried the following things:
Model with no set fields, all dynamic:
class Content
include Mongoid::Document
end
Rails console:
1.9.3p125 :011 > c = Content.new(:test => "test", :link=> "link", :desc => "desc")
=> #<Content _id: 4f7f49f5add3617fae000003, _type: nil, test: "test", link: "link", desc: "desc">
1.9.3p125 :012 > c.save
=> true
1.9.3p125 :013 > Content.first
=> #<Content _id: 4f7f49f5add3617fae000003, _type: nil, test: "test", link: "link", desc: "desc">
1.9.3p125 :014 >
Model with all fields statically set:
class Content
include Mongoid::Document
field :test, :type => String
field :link, :type => String
field :desc, :type => String
end
Rails console again:
Loading development environment (Rails 3.2.3)
1.9.3p125 :001 > c = Content.new
=> #<Content _id: 4f7f4652add3617ec4000001, _type: nil, test: nil, link: nil, desc: nil>
1.9.3p125 :002 > c.test = 'tyler'
=> "tyler"
1.9.3p125 :003 > c.save
=> true
1.9.3p125 :004 > Content.first
=> #<Content _id: 4f7f4652add3617ec4000001, _type: nil, test: "tyler", link: nil, desc: nil>

Rails 3.1: Creating objects via .build seems to conflict with validates_presence_of

I am having trouble combining a validation of a foreign key field, and making use of the .build method to create objects. See the classes below.
class Parent < ActiveRecord::Base
belongs_to :family
has_one :family_user
validates_presence_of :name
validates_associated :family
validates_presence_of :family_id
end
class Family < ActiveRecord::Base
belongs_to :organization
has_many :parents
...
end
This generally works fine, but in the app I want to use the build method. For example, the following code in both a spec and in the rails console fails because it is looking for a family_id on the Parent record.
fam = Family.new(:organization_id => 1)
fam.children.build(:name => "Billy Jones")
fam.parents.build(:name => "Mister Jones")
fam.save!
Without validates_presence_of :family_id this code works, and indeed a family_id is properly recorded.
Question: is there a way to validate that a family_id is indeed recorded, while also being able to use .build?
For reference, an error in the console is:
ruby-1.9.2-p290 :082 > fam = Family.new(:organization_id => 1)
=> #<Family id: nil, organization_id: 1, created_at: nil, updated_at: nil, url_token: nil>
ruby-1.9.2-p290 :083 > fam.children.build(:name => "Billy Jones")
=> #<Child id: nil, family_id: nil, name: "Billy Jones", gender: nil, birth_date: nil, desired_start_date: nil, application_date: nil, notes: nil, custom1: nil, custom2: nil, custom3: nil, custom4: nil, created_at: nil, updated_at: nil>
ruby-1.9.2-p290 :084 > fam.parents.build(:name => "Mister Jones")
=> #<Parent id: nil, family_id: nil, name: "Mister Jones", address: nil, phone: nil, email: nil, notes: nil, created_at: nil, updated_at: nil>
ruby-1.9.2-p290 :085 > fam.save!
ActiveRecord::RecordInvalid: Validation failed: Parents family can't be blank
from /Users/business/.rvm/gems/ruby-1.9.2-p290#rails311/gems/activerecord-3.1.1/lib/active_record/validations.rb:56:in `save!'
from /Users/business/.rvm/gems/ruby-1.9.2-p290#rails311/gems/activerecord-3.1.1/lib/active_record/attribute_methods/dirty.rb:33:in `save!'
from /Users/business/.rvm/gems/ruby-1.9.2-p290#rails311/gems/activerecord-3.1.1/lib/active_record/transactions.rb:246:in `block in save!'
from /Users/business/.rvm/gems/ruby-1.9.2-p290#rails311/gems/activerecord-3.1.1/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status'
from /Users/business/.rvm/gems/ruby-1.9.2-p290#rails311/gems/activerecord-3.1.1/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
from /Users/business/.rvm/gems/ruby-1.9.2-p290#rails311/gems/activerecord-3.1.1/lib/active_record/transactions.rb:208:in `transaction'
from /Users/business/.rvm/gems/ruby-1.9.2-p290#rails311/gems/activerecord-3.1.1/lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
from /Users/business/.rvm/gems/ruby-1.9.2-p290#rails311/gems/activerecord-3.1.1/lib/active_record/transactions.rb:246:in `save!'
from (irb):85
from /Users/business/.rvm/gems/ruby-1.9.2-p290#rails311/gems/railties-3.1.1/lib/rails/commands/console.rb:45:in `start'
from /Users/business/.rvm/gems/ruby-1.9.2-p290#rails311/gems/railties-3.1.1/lib/rails/commands/console.rb:8:in `start'
from /Users/business/.rvm/gems/ruby-1.9.2-p290#rails311/gems/railties-3.1.1/lib/rails/commands.rb:40:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
ruby-1.9.2-p290 :086 >
I would understand it the same way, at least upon initial reading the code that you have.
Maybe you can try this alternate solution:
http://forums.pragprog.com/forums/74/topics/732
Remove
validates_associated :family
validates_presence_of :family_id
and try this
validates_presence_of :family
Hope this helps.

to_xml Doesn't Work on Objects Returned Through Rails ActiveRecord habtm Reference

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 ?
to_xml() tries to define a type attribute for each model attribute. For example, a User model with an age (INT) attribute will have: <age type="integer">42</age>. This type information is not encoded in JSON, which is why to_json() works for you. Add this method to your Instructor model:
def to_xml(options = {})
to_xml_opts = {:skip_types => true} # no type information, not such a great idea!
to_xml_opts.merge!(options.slice(:builder, :skip_instruct))
# a builder instance is provided when to_xml is called on a collection of instructors,
# in which case you would not want to have <?xml ...?> added to each item
to_xml_opts[:root] ||= "instructor"
self.attributes.to_xml(to_xml_opts)
end
This would however make your XML devoid of any type information - not good if someone has a JAVA REST client. A better strategy would be to filter self.attributes.slice(*keys).to_xml(to_xml_opts) where keys is an array of model attributes you want in the XML.

Resources