开发者

XML Builder in Rails: 'wrong number of arguments' bug that I just can't trace

开发者 https://www.devze.com 2023-01-04 06:54 出处:网络
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

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
0

精彩评论

暂无评论...
验证码 换一张
取 消