New to rails, and I've just spent hours trying to hunt down a bug. Any help very appreciated.
I'm trying to make a rails page so that if a user enters /info/who_bought/1 the page outputs HTML, and if they enter /info/who_bought/1.xml, the page returns an XML file. (In short, I'm doing chapter 11 from the 'Agile Web Development with Rails' book)
The HTML-formatted output works fine, but if I enter the xml I consistently get a 'wrong number of arguments (1 for 0)' error page. Downloaded the actual ebook and did a direct copy/paste of all code; still facing the same problem. Google doesn't bring up any mention of code bugs.
Code & full stack trace below. If anyone has any ideas I'd be very appreciative. In short - what could possible cause xml.builder to return a '1 for 0 arguments' bug?
Many thanks, Baggage
# app/controllers/info_controller.rb
class InfoController < ApplicationController
def who_bought
@product = Product.find(params[:id])
@orders = @product.orders
respond_to do |format|
format.html
format.xml {render :layout => false }
end
end
protected
def authorize
end
end
# app/views/info/who_bought.xml.builder
xml.order_list(:for_product => @product.title) do
for o in @orders
xml.order do
xml.name(o.name)
xml.email(o.email)
end
end
end
# app/models/product.rb
class Product < ActiveRecord::Base
has_many :orders, :through => :line_items
has_many :line_items
validates_presence_of :title, :description, :image_url
validates_numericality_of :price
validates_uniqueness_of :title
validates_length_of :title,
:minimum => 10
validates_format_of :image_url,
:with => %r{\.(gif|jpg|png)$}i,
:message => 'must be a URL for GIF, JPG ' +
'or PNG image.'
validate :price_must_be_at_least_a_cent
def price_must_be_at_least_a_cent
errors.add(:price, 'should be at least 0.01') if price.nil? || price < 0.01
end
def self.find_products_for_sale
find(:all, :order => "title")
end
end
# config/routes.rb
ActionController::Routing::Routes.draw do |map|
map.resources :users
map.resources :line_items
map.resources :orders
map.resources :products
map.connect ':controller/:action'
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
# Full trace
/usr/lib/ruby/1.8/builder/xmlbase.rb:134:in `to_xs'
/usr/lib/ruby/1.8/builder/xmlbase.rb:134:in `_escape'
/usr/lib/ruby/1.8/builder/xmlbase.rb:87:in `text!'
/usr/lib/ruby/1.8/builder/xmlbase.rb:144:in `_newline'
/usr/lib/ruby/1.8/builder/xmlbase.rb:60:in `method_missing'
app/views/info/who_bought.xml.builder:2
vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:359:in `method_missing'
vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:212:in `method_missing'
vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:212:in `each'
vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:212:in `send'
vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:212:in `method_missing'
vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:359:in `method_missing'
app/views/info/who_bought.xml.builder:1
vendor/rails/actionpack/lib/action_view/renderable.rb:39:in `send'
vendor/rails/actionpack/lib/action_view/renderable.rb:39:in `render'
vendor/rails/actionpack/lib/action_view/template.rb:73:in `render_template'
vendor/rails/actionpack/lib/action_view/base.rb:256:in `render'
vendor/rails/actionpack/lib/action_controller/base.rb:1177:in `render_for_file'
vendor/rails/actionpack/lib/action_controller/base.rb:940:in `render_without_benchmark'
vendor/rails/actionpack/lib/action_controller/benchmarking.rb:51:in `render'
vendor/rails/activesupport/lib/active_support/core_ext/benchmark.rb:8:in `realtime'
vendor/rails/actionpack/lib/action_controller/benchmarking.rb:51:in `render'
app/controllers/info_controller.rb:6
vendor/rails/actionpack/lib/action_controller/mime_responds.rb:135:in `call'
vendor/rails/actionpack/lib/action_controller/mime_responds.rb:135
vendor/rails/actionpack/lib/action_controller/mime_responds.rb:164:in `call'
vendor/rails/actionpack/lib/action_controller/mime_responds.rb:164:in `respond'
vendor/rails/actionpack/lib/action_controller/mime_responds.rb:158:in `each'
vendor/rails/actionpack/lib/action_controller/mime_responds.rb:158:in `respond'
vendor/rails/actionpack/lib/action_controller/mime_responds.rb:107:in `respond_to'
app/controllers/info_controller.rb:5:in `who_bought'
vendor/rails/actionpack/lib/action_controller/base.rb:1256:in `send'
vendor/rails/actionpack/lib/action_controller/base.rb:1256:in `perform_action_without_filters'
vendor/rails/actionpack/lib/action_controller/filters.rb:617:in `call_filters'
vendor/rails/actionpack/lib/action_controller/filters.rb:610:in `perform_action_without_benchmark'
vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
/usr/lib/ruby/1.8/benchmark.rb:293:in `measure'
vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
vendor/rails/actionpack/lib/action_controller/rescue.rb:136:in `perform_action_without_caching'
vendor/rails/actionpack/lib/action_controller/caching/sql_cache.rb:13:in `perform_action'
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:34:in `cache'
vendor/rails/activerecord/lib/active_record/query_cache.rb:8:in `cache'
vendor/rails/actionpack/lib/action_controller/caching/sql_cache.rb:12:in `perform_action'
vendor/rails/actionpack/lib/action_controller/base.rb:524:in `send'
vendor/rails/actionpack/lib/action_controller/base.rb:524:in `process_without_filters'
vendor/rails/actionpack/lib/action_controller/filters.rb:606:in `process_without_session_management_support'
vendor/rails/actionpack/lib/action_controller/session_management.rb:134:in `process'
vendor/rails/actionpack/lib/action_controller/base.rb:392:in `process'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:184:in `handle_request'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:112:in `dispatch_unlocked'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:125:in `dispatch'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:124:in `synchronize'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:124:in `dispatch'
vendor/rails/actionpack/lib/action_controller/dispatcher.rb:134:in `dispatch_cgi'
vendor/rails/actionpack/lib/action_contro开发者_StackOverflow社区ller/dispatcher.rb:41:in `dispatch'
/usr/lib/ruby/1.8/mongrel/rails.rb:76:in `process'
/usr/lib/ruby/1.8/mongrel/rails.rb:74:in `synchronize'
/usr/lib/ruby/1.8/mongrel/rails.rb:74:in `process'
/usr/lib/ruby/1.8/mongrel.rb:159:in `process_client'
/usr/lib/ruby/1.8/mongrel.rb:158:in `each'
/usr/lib/ruby/1.8/mongrel.rb:158:in `process_client'
/usr/lib/ruby/1.8/mongrel.rb:285:in `run'
/usr/lib/ruby/1.8/mongrel.rb:285:in `initialize'
/usr/lib/ruby/1.8/mongrel.rb:285:in `new'
/usr/lib/ruby/1.8/mongrel.rb:285:in `run'
/usr/lib/ruby/1.8/mongrel.rb:268:in `initialize'
/usr/lib/ruby/1.8/mongrel.rb:268:in `new'
/usr/lib/ruby/1.8/mongrel.rb:268:in `run'
/usr/lib/ruby/1.8/mongrel/configurator.rb:282:in `run'
/usr/lib/ruby/1.8/mongrel/configurator.rb:281:in `each'
/usr/lib/ruby/1.8/mongrel/configurator.rb:281:in `run'
/usr/bin/mongrel_rails:129:in `run'
/usr/lib/ruby/1.8/mongrel/command.rb:212:in `run'
/usr/bin/mongrel_rails:282
This is a conflict between Rails 3.1, Builder 3.0, and either the fast_xs gem or hpricot (which bundles fast_xs). The reason why some people can't reproduce it is that they don't have fast_xs or hpricot in their Gemfile.
Unfortunately, since it's a three-way conflict, everybody thinks it's the other library's fault:
- Builder bug report
- Rails pull request
- fast_xs bug report
In the meantime, pile another monkey patch on the heap and add config/initializers/unbreak_string_to_xs.rb
with the following:
class String
def fast_xs_absorb_args(*args); fast_xs; end
alias_method :to_xs, :fast_xs_absorb_args
end
(From this answer to a duplicate.)
Try (re)installing the 'builder' gem, that fixed the '1 for 0 arguments' bug for me :)
sudo gem install builder
Don't forget to restart your server afterwards
I would kind of like to blame the "for o in @orders" part. Perhaps trying with a traditional way would help to eliminate this suspicion:
@orders.each do |o|
...
end
精彩评论