2012-02-19 6 views
6

Tengo un problema en mi aplicación Rails 3.2 donde un atributo virtual enviado de manera relajada a través de JSON no está en el lugar correcto en hash de params. Bueno, no es donde espero. Queda por verse si mis expectativas son correctas. :)Atributo virtual no movido al hash del modelo dentro de los parámetros

que tienen un modelo utilizando el patrón atributo virtual estándar, así:

class Track < ActiveRecord::Base 
    def rating 
    # get logic removed for brevity 
    end 

    def rating=(value) 
    # set logic 
    end 

    def as_json(options={}) # so my method is in the JSON when I use respond_with/to_json 
    super(options.merge(methods: [:rating])) 
    end 
end 

El JSON envió a mi controlador se parece a esto:

{"id":1,"name":"Icarus - Main Theme 2","rating":2} 

Para ser claros, el nombre y id no son virtuales, la calificación es.

termino con esto en el hash params, después de rieles hace su magia:

{"id"=>"1", "name"=>"Icarus - Main Theme 2", "rating"=>2, "track"=>{"id"=>"1", "name"=>"Icarus - Main Theme 2"}} 

Como se puede ver, la identificación y el nombre que sea a la anidada: hash de pista, pero calificación no lo hace. ¿Es este comportamiento esperado? Se rompe la práctica (algo) estándar de utilizar el hash anidado en el controlador porque el hash anidado no contiene todos los parámetros que necesito.

Track.update(params[:id], params[:track]) # :track is missing rating 

Gracias por su ayuda!

+0

Puede pegar el formulario que está haciendo la presentación, parece que no tiene el alcance adecuado para rastrear – MatthewFord

Respuesta

7

Recientemente me encontré con este gotcha también. El problema es que el envoltorio de parámetros está buscando en su modelo Track.attribute_names para determinar cómo mapear los datos en a: track => {params} hash. Si usted no tiene asociado un modelo, el valor por defecto será para envolver los parametros basado en el nombre del controlador, e incluyen todos los valores:

class SinglesController < ApplicationController 
    def create 
    #params[:single] will contain all of your attributes as it doesn't 
    # have an activerecord model to look at. 
    @track_single = Track.new(params[:single]) 
    end 
end 

Puede llamar wrap_parameters en su controlador para contar controlador de acción lo atributos para incluir cuando su embalar sus parametros, así:

class TracksController < ApplicationController 
    wrap_parameters :track, :include => :rating 
    #other controller stuff below 
end 

Ver más aquí: http://api.rubyonrails.org/classes/ActionController/ParamsWrapper.html

+3

Tengo un problema similar, cuando uso wrap_parameters, si tengo muchos otros atributos no virtuales, tuve que escribir todos ellos a la matriz de inclusión. de lo contrario, no se incluirán en el hash de solicitud, ¿cómo hacerlo de una manera sencilla? ya que solo tengo un atributo virtual que quiero incluir en el hash de solicitud Gracias – user1883793

0

Tal vez si se asigna el atributo virtual rating dentro del resumen anidada como esto:

def as_json(options={}) 
    super(options.merge(:track => {:methods => @rating})) 
end 

se comportaría en la forma esperada.

0

acaba de ejecutar a través de este problema y encontrado una solución bastante decente. Agregue lo siguiente a su ApplicationController

wrap_parameters exclude: [:controller, :action, :format] + ActionController::ParamsWrapper::EXCLUDE_PARAMETERS 

De esta manera, todo está anidado bajo su recurso (a excepción de los carriles cosas añade al hash params) y no tendrá nunca para anexar a una llamada específica del controlador de wrap_parameters nuevo . : D

Cuestiones relacionadas