6

I have this render in a method controller:

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

but translatedCity method in the model should accept 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 the parameter in the controller. Is there any way to pass this parameter to the method in the model?

1
  • translatedCity would need to accept a parameter like so translatedCity(language) in order for you to have access to the value in params[:language] only the controller has access to the params hash. read this: stackoverflow.com/questions/10237388/… Commented May 22, 2015 at 16:16

4 Answers 4

4

Unfortunately the process of passing methods that require params to_json is not nicely built into rails. a typical pattern is to modify the as_json method on the model to accept custom keys, and then calling 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 pass everything in accoringdly

render :json => @boats, 
  :include => {
    :port => {
      :only => [:id, :name], 
      :include => {
        :city => {
          :only => [:id, :name], 
          :translatedCity => params[:language]
        }
      }
    }
  }
Sign up to request clarification or add additional context in comments.

Comments

4

All answers are good!

I just did something like:

In controller:

boat.port.language = params[:language]

In model:

attr_accessor :language
  @language  

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

What do you think?

1 Comment

Seems reasonable. I feel funny adding temporary request data to a model so that later I can call an instance method, but to each their own :)
2

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

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

Then BoatPresenter would add the extra data you want in its 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 have BoatPresenter add your default includes, etc. if you want a standard set without the controller having to worry about it. And if you don't want to do the array mapping yourself, Draper also offers collection presenters (eg BoatsPresenter).


If you're averse to adding a class, you could also override as_json directly on Boat to handle a language option:

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

Comments

0

You can set 'language' in a session variable and set it before executing to_json in your controller, and destroy session in your method before return as follwoing

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

1 Comment

is that cool to save this kind of data in session? I mean we can need more data to pass in the same kind of parameters, what do you think?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.