Search code examples
ruby-on-railsruby-on-rails-3.1respond-torespond-with

respond_to causes undefined method `to_sym' for [:json, :html]:Array


In Rails 3.2.8 in Ruby 1.9.3p194 when passing an array to respond_to in an included block of an ActiveSupport::Concern that is included on demand in the class definition by calling an acts_as_... method in module included in a gem results in a:

respond_to causes undefined method `to_sym' for [:json, :html]:Array

and on the next request, I get:

RuntimeError (In order to use respond_with, first you need to declare the formats your controller responds to in the class level):
  actionpack (3.2.8) lib/action_controller/metal/mime_responds.rb:234:in `respond_with'

In the module code, it is just doing the equivalent of:

formats = [:json, :html]
respond_to formats

Where formats is configured elsewhere so it can be applied to all controllers that specify acts_as_....

I know it works when I do this in a class definition:

respond_to :json, :html

So, how can I call respond_to with a variable that is an array of formats?


Solution

  • The related parts of the respond_to method in Rails 3.2.8 are:

    def respond_to(*mimes)
      # ...
      mimes.each do |mime|
        mime = mime.to_sym
        # ...
      end
      # ...
    end
    

    Because the splat operator is used in respond_to, it is wrapping the incoming array in an array, so mimes is [[:json, :html]], and it is trying to call to_sym on the array.

    If calling respond_to with a variable containing an array, you need to use the splat (*) operator, e.g.:

    formats = [:json, :html]
    respond_to *formats
    

    That will call respond_to as if you were sending in two arguments:

    respond_to :json, :html
    

    or:

    respond_to(:json, :html)