Rails渲染json,包括带参数

时间:2015-05-22 15:56:05

标签: ruby-on-rails ruby-on-rails-4

我在方法控制器中有这个渲染:

render :json => @boats, :include => {:port => {:only => [:id, :name], :include => {:city => {:only => [:id, :name], :methods => :translatedCity}}}}

但模型中的translatedCity方法应该接受语言参数。

  def translatedCity     
    language = params[:language]
    puts "translatedCity.language=" + language  
    city = TranslationService.translateCity(self.city_id, language)        
    return city.element_translation
  end

我在控制器中有参数。有没有办法将此参数传递给模型中的方法?

4 个答案:

答案 0 :(得分:4)

不幸的是,传递需要params to_json的方法的过程并没有很好地构建到rails中。一个典型的模式是修改模型上的as_json方法以接受自定义键,然后调用to_json(或render :json

# city.rb model
def translatedCity(language)
  puts "translatedCity.language=" + language  
  city = TranslationService.translateCity(self.city_id, language)        
  return city.element_translation
end

def as_json(options = {})
  json_to_return = super
  if options.has_key? :translatedCity
    city_translation = self.translatedCity(options[:translatedCity][:language])
    json_to_return[:translatedCity] = city_translation
  end

  return json_to_return
end

现在在您的控制器中,您可以按照惯例传递所有内容

render :json => @boats, 
  :include => {
    :port => {
      :only => [:id, :name], 
      :include => {
        :city => {
          :only => [:id, :name], 
          :translatedCity => params[:language]
        }
      }
    }
  }

答案 1 :(得分:4)

所有答案都很好!

我做了类似的事情:

在控制器中:

boat.port.language = params[:language]

模特:

attr_accessor :language
  @language  

  def translatedCity            
    city = TranslationService.translateCity(self.city_id, language)        
    return city.element_translation
  end

您怎么看?

答案 2 :(得分:1)

as_json不支持需要参数的方法,但这是一个使用Presenter(或装饰器或视图模型,取决于你与谁交谈)构建所需JSON的好地方。 Draper是一个宝石,如果你想要一个,它可以帮助你,你的控制器看起来像

data = @boats.map do |boat|
  BoatPresenter.new(boat).as_json(language: params[:language])
end
render json: data

然后BoatPresenter会在as_json中添加您想要的额外数据:

def as_json(options = {})
  @boat.as_json(options).tap do |json|
    json[:translated_city] = @boat.translated_city(options[:language])
  end
end

如果您想要一个没有控制器担心的标准设置,您也可以BoatPresenter添加默认include等。如果您不想自己进行数组映射,Draper还会提供集合演示者(例如BoatsPresenter)。

如果您反对添加课程,也可以直接在as_json覆盖Boat来处理language选项:

def as_json(options = {})
  super(options).tap do |json|
    json[:translated_city] = translated_city(options[:language])
  end
end

答案 3 :(得分:0)

您可以设置'语言'在会话变量中并在控制器中执行to_json之前设置它,并在返回之前销毁方法中的会话,如下所示

def translatedCity(language=nil)
    language ||= session[:language]
    puts "translatedCity.language=" + language  
    city = TranslationService.translateCity(self.city_id, language)        
    session[:language] = nil #destroy session, or use session.delete(:language)         
    return city.element_translation
end


session[:language] = language
render :json => @boats, :include => {:port => {:only => [:id, :name], :include => {:city => {:only => [:id, :name], :methods => :translatedCity}}}}