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?
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]
}
}
}
}
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?
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 include
s, 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With