【问题标题】:Rails render json including methods with parametersRails 渲染 json,包括带参数的方法
【发布时间】:2015-08-04 17:41:09
【问题描述】:

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

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

我在控制器中有参数。有没有办法把这个参数传给模型中的方法?

【问题讨论】:

  • translatedCity 需要接受像 translateCity(language) 这样的参数,以便您可以访问 params[:language] 中的值,只有控制器可以访问 params 哈希。阅读:stackoverflow.com/questions/10237388/…

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


【解决方案1】:

不幸的是,传递需要参数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]
        }
      }
    }
  }

【讨论】:

    【解决方案2】:

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

    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 添加您的默认includes 等,如果您想要一个标准集而无需控制器担心它。如果你不想自己做数组映射,Draper 还提供集合展示器(例如BoatsPresenter)。


    如果您不愿意添加类,您也可以直接在 Boat 上覆盖 as_json 以处理 language 选项:

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

    【讨论】:

      【解决方案3】:

      所有答案都很好!

      我刚刚做了类似的事情:

      在控制器中:

      boat.port.language = params[:language]
      

      在模型中:

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

      你怎么看?

      【讨论】:

      • 看起来很合理。我觉得将临时请求数据添加到模型中很有趣,以便稍后我可以调用实例方法,但每个方法都有自己的 :)
      【解决方案4】:

      您可以在会话变量中设置“语言”并在控制器中执行 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}}}}
      

      【讨论】:

      • 在会话中保存这种数据很酷吗?我的意思是我们可能需要更多的数据来传递同一种参数,你怎么看?
      猜你喜欢
      • 2011-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-10
      • 1970-01-01
      相关资源
      最近更新 更多