Виртуальный атрибут не перемещен в хеш модели внутри параметров - PullRequest
6 голосов
/ 20 февраля 2012

В моем приложении на Rails 3.2 возникла проблема, когда виртуальный атрибут, отправленный в спокойном состоянии через JSON, не находится в нужном месте в хэше params. Ну, это не то, где я ожидаю. Еще неизвестно, верны ли мои ожидания. :)

У меня есть модель, использующая стандартный шаблон виртуальных атрибутов, например:

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

JSON, отправленный на мой контроллер, выглядит следующим образом:

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

Чтобы быть понятным, имя и идентификатор не являются виртуальными, рейтинг.

Я получаю это в хэше params, после того, как rails делает свою магию:

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

Как видите, имя и имя попадают во вложенный хэш, но рейтинг - нет. Это ожидаемое поведение? Это нарушает (несколько) стандартную практику использования вложенного хэша в контроллере, потому что вложенный хэш не содержит всех необходимых мне параметров.

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

Спасибо за вашу помощь!

Ответы [ 3 ]

7 голосов
/ 04 октября 2012

Я недавно столкнулся и с этой ошибкой.Проблема заключается в том, что оболочка params просматривает вашу модель Track.attribute_names, чтобы определить, как отобразить данные в хеш: track => {params}.Если модель не связана, по умолчанию будет заключаться в перенос параметров на основе имени контроллера и включение всех значений:

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

Вы можете вызвать wrap_parameters в вашем контроллере, чтобы сообщить действиеКонтроллер, какие атрибуты включить при обёртывании ваших параметров, например:

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

Подробнее здесь: http://api.rubyonrails.org/classes/ActionController/ParamsWrapper.html

0 голосов
/ 10 мая 2016

Просто наткнулся на эту проблему и нашел довольно приличное решение.Добавьте следующее в ApplicationController

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

Таким образом, все вложено в ваш ресурс (за исключением того, что Rails добавляет к хэшу params), и вам никогда не придется добавлять к вызову конкретного контроллераснова wrap_parameters.: D

0 голосов
/ 25 июля 2012

Может быть, если вы назначите виртуальный атрибут rating внутри вложенного хэша следующим образом:

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

Это будет вести себя так, как вы ожидали.

...