Rails renders json including methods with parameters

I have this render in a method controller:

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

      

but the translatedCity

method in the model must take a language parameter.

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

      

I have a parameter in my controller. Is there a way to pass this parameter to a method in the model?

+3


source to share


4 answers


All answers are good!

I just did something like:

In the controller:

boat.port.language = params[:language]

      



In the model:

attr_accessor :language
  @language  

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

      

What do you think?

+1


source


Unfortunately, the process of passing methods that require params to_json

is not well built into rails. the typical pattern is to change a method as_json

on the model to accept custom keys and then call to_json

(or 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

      



now in your controller you all pass in accoringdly

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

      

+1


source


as_json

doesn't support methods that require arguments, but it's a good place to use a Presenter (or Decorator or View Model, depending on who you're talking to) that builds the JSON you want. Draper is a gem that helps with this if you want one and your controller will look something like

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

      

Then it BoatPresenter

will add extra data to its own as_json

:

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

      

You can also BoatPresenter

add your default include

s and so on if you want the standard set not requiring the controller to worry about that. And if you don't want to do the array mapping yourself, Draper also offers collectors (for example BoatsPresenter

).


If you don't want to add a class, you can also override the option as_json

directly Boat

to handle language

:

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

      

+1


source


You can set "language" in session variable and set it before executing to_json in your controller and destroy the session in your method before returning like following

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}}}}

      

0


source







All Articles