Reputation: 45943
I have a Javascript object in a partial that looks like this:
_chart.js.erb
{
chart: {
animation: <%= @animation %>
},
plotOptions: {
...
This partial works as expected as part of a view.
I need to convert it to JSON to be used as a config for a command line utility.
What is a good way to load the partial, interpolate the ERB, convert to JSON and return the JSON?
Something like this might work, but seems like a poor solution:
respond_to do |format|
format.json {
js = File.read('app/views/trades/_chart.js.erb')
hsh = eval(ERB.new(js).result)
parsed = JSON.parse(hsh)
render json: parsed.to_json
}
Upvotes: 0
Views: 352
Reputation: 45943
As max mentioned, converting a partial JS file to JSON is probably not a good idea. Here is another approach (and what I ended up using).
class ChartConfig
class << self
def for params
chart: {
animation: params[:animation]
},
plotOptions: {
...
Now the controller looks like this:
respond_to do |format|
format.json { render json: ChartConfig.for(animation: ... }
Upvotes: 0
Reputation: 101811
To convert a javascript object defined in a ERB template to JSON you actually have to do something like:
js = render_to_string(partial: 'trades/chart', format: :js)
json_string = %x( node -e "JSON.stringify(#{js})" )
json_string.to_json
While any JSON is valid javascript the inverse is not true. Your partial is not valid JSON since the property names are not quoted. Thus you have to pass it though a javascript runtime to convert it into JSON.
This assumes that the partial renders something which actually can be passed to JSON.stringify
and you have to deal with the crazy like escaping characters and it will blow up if the partial contains anything but literals or functions that your JS runtime has.
This is not how you build sane applications. If you need use a peice of data outside the view it should not be defined in a view.
Upvotes: 2