0

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
  }
5
  • This sounds like a collosal X & Y question. If you need to create a hash like structure and use it outside the view then don't put in in a js.erb template to begin with. Commented Sep 1, 2021 at 17:31
  • 1
    Instead just use a serializer or a method method that takes the data as input and returns a hash that can converted to JSON. Once you go to JSON you don't convert it back unless you're building a Ruby Goldberg machine (pun intetend). Commented Sep 1, 2021 at 17:38
  • I don't think you understood the use case. I have the Javascript object that already is used in a partial. I want to use the same partial as JSON for a command line tool. Commented Sep 1, 2021 at 17:52
  • 1
    +1 to @max suggestion. If you have need for it outside of a view then it shouldn't be defined in the view. If it's a static hash I'd put it in a YAML file (or similar) and send it to the view / anywhere else you need it. Commented Sep 1, 2021 at 17:54
  • Yes I understood. Your partial should just be doing something like let data = <%= raw @serialized_data.to_json %>; instead. Commented Sep 1, 2021 at 17:58

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

I see...I will see about defining the hash in Ruby, then converting it to JS and JSON.
0

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

Comments

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.