how to render Ruby array as JavaScript array in ERB template [duplicate] - ruby-on-rails

This question already has an answer here:
Use ruby array for a javascript array in erb. Escaping quotes
(1 answer)
Closed 7 years ago.
I need to render a Ruby array in a very specific format for an erb template. This is because I am using JQcloud to build word clouds using JQuery, and is apparently picky about array formatting.
Here is the way that JQcloud requires a JS array to be formatted:
var word_array = [
{text: "Lorem", weight: 15},
{text: "Ipsum", weight: 9},
{text: "Dolor", weight: 6},
{text: "Sit", weight: 7},
{text: "Amet", weight: 5}
// ...as many words as you want
];
So what I have created in my controller are two arrays, one array of words to build my cloud, and another array of weights for each word.
ruby_word_array = ["Lorem","Ipsum","Dolor","Sit","Amet"]
ruby_weight_array = [15,10,13,8,4]
I need to convert my two Ruby arrays in such a way that they render properly with erb. So far I have come up with:
var wordArray = <%= raw #word_array.map{|a, i| {text: #word_array[0], weight: 15} } %> # I just hard coded the weight for simplicity
This gives me something that's close, but not close enough, and it ends up formatted like so:
var wordArray = [{:text=>"Lorem", :weight=>15}, {:text=>"Ipsum", :weight=>15}]
I really just need to know how to modify my last example to render in the Python style hash syntax {key: "value"},{key_2: "value_2"}
This is honestly a tricky one and I am stumped. The library I am using for this is called JQcloud, and it has a Ruby gem which I have incorporated into this Rails app. Here is a link.

Why don't your just use to_json?
# in ruby
#array = [{:text=>"Lorem", :weight=>15}, {:text=>"Ipsum", :weight=>15}]
Then, in the view:
var wordArray = <%= #array.to_json.html_safe %>;
Which will render:
var wordArray = [{"text":"Lorem","weight":15},{"text":"Ipsum","weight":15}];

You should create a helper function in app/helpers that does the behaviour you want. It's better to leave complex logic out of the view. Then in the view
var wordArray = <%= myHelper #word_array %>
And in the helper
def myHelper(word_array):
string = "["
word_array.each do |word|
string << "{text: \"#{word[:text]}\", weight: #{word[:weight]}},"
string = string.chomp(",") #in case JS hates the last comma
string << "]"
return string
Really, though, you can put anything you want in myHelper. You could pass both arrays and put them together in the helper. You could add newlines to the strings. Anything is possible

In such 2 Arrays situation, zip is useful.
ruby_word_array.zip(ruby_weight_array).map{|word, weight| "{text: #{word}, weight: #{weight}}"}.join(',')
If you need [],
'[' + ruby_word_array.zip(ruby_weight_array).map{|word, weight| "{text: #{word}, weight: #{weight}}"}.join(',') + ']'

Related

Trying to make a two column unordered, bulleted list with Prawn PDF in ruby/rails?

I am having trouble with how to create a two-column bulleted list using prawn PDF and prawn/table. I wanted to know if there is a way to do it that's not too custom/uses existing classes to take care of overflow to a new page, etc so I don't miss things or reinvent the wheel.
I want the list to look something like this:
*Name 1 * Name 3
*Name 2 * Name 4
... ...
Currently what I have is:
bullet_list = [
[ '*' , 'Name 1' ],
[ '*' , 'Name 2' ],
[ '*' , 'Name 3' ],
[ '*' , 'Name 4' ]
]
pdf.table(bullet_list, {:cell_style => { :borders => [], :align => :justify, :padding => [0,10,0,0]}})
This obviously makes a bullet list straight down, but it seemed to be a decent start, but will I need to split the list, create the list down with the first half, go back up the PDF some amount, go right, and repeat the process?
Another thing I was thinking of was using inline HTML styling as seen here
https://prawnpdf.org/manual.pdf (Pg. 53) but I think it only accepts very basic styling like bold/italics.
Any tips would be greatly appreciated!
Alright so I ended up using the table method, I'm not sure why I didn't think of this earlier but we can just split the list of names in half and append them in such a way that the second half of names is appended to the same row as the first half of names. Here is essentially what I did:
require 'active_support/core_ext/array/grouping'
require 'prawn'
require 'prawn/table'
names = ['John', 'Jim', 'Joe', 'James']
pdf = Prawn::Document.new
split_names = names.in_groups(2, false)
split_names.first.each do |name|
bullet_list << ["\u2022", name]
end
split_names.second.each_with_index do |name, index|
bullet_list[index].push("\u2022", name)
end
pdf.table(bullet_list, { cell_style: { borders: [], align: :justify, padding: [0, 10, 0, 0] } })
This is a solution that works but let me know if you have any tips or changes that should be made.

How to replace Space with Line Break in Ruby on Rails?

I am trying to replace Space in a string with Line Break in Ruby on Rails,
name = 'john smith'
i have tried the following so far:
name.gsub!(" ", "\n")
name.gsub!(" ", "<br>")
name.sub(" ", "\n")
name.sub(" ", "<br>")
but none of the above worked.
You have to be careful when marking a string as html_safe, especially if it may contain user input:
name = 'john smith<script>alert("gotcha")</script>'
name.gsub(' ', '<br>').html_safe
#=> "john<br>smith<script>alert(\"gotcha\")</script>"
Rails would output that string as-is, i.e. including the <script> tag.
In order to take advantage of Rails' HTML escaping, you should only mark the trusted parts as being html_safe. For a manually concatenated string:
''.html_safe + 'john' + '<br>'.html_safe + 'smith<script>alert("gotcha")</script>'
#=> "john<br>smith<script>alert("gotcha")</script>"
As you can see, only the <br> tag was left intact, the remaining parts were properly escaped.
There are several helpers for building safe strings as well as for building HTML tags. In your case, I'd use safe_join and tag:
name = 'john smith<script>alert("gotcha")</script>'
safe_join(name.split(' '), tag(:br))
#=> "john<br />smith<script>alert("gotcha")</script>"
While printing it in html you will need to use raw, otherwise rails will escape the tags
= raw name.gsub(" ", "<br>")
Try another one:
<%= name.gsub(" ", "<br>").html_safe %>
html_safe :
Marks a string as trusted safe. It will be inserted into HTML with no additional escaping performed.
"<a>Hello</a>".html_safe
#=> "<a>Hello</a>"
nil.html_safe
#=> NoMethodError: undefined method `html_safe' for nil:NilClass
raw :
raw is just a wrapper around html_safe. Use raw if there are chances that the string will be nil.
raw("<a>Hello</a>")
#=> "<a>Hello</a>"
raw(nil)
#=> ""

How to convert ActiveRecord query result into json to feed D3 in a RoR project?

I develop an application with Ruby on Rails 5.0
I am building an array of hashes to feed D3, that should look like this:
var errors = [
{index:-1, count:10},
{index:-2, count:40},
{index:-3, count:20},
{index:-4, count:60},
{index:-5, count:80},
{index:-6, count:30}];
Formatting my ActiveRecord query, I get this result at the rails console:
var errors = <%= d3_chart_series_for(this_object).map { |measure| {index: measure.idx, count: measure.score}}.to_json %>;
var errors = "[{\"index\":-1,\"count\":\"96.74\"},{\"index\":-2,\"count\":\"93.5\"},{\"index\":-3,\"count\":\"91.3\"},{\"index\":-4,\"count\":\"97.05\"},{\"index\":-5,\"count\":\"96.07\"},{\"index\":-6,\"count\":\"96.75\"},{\"index\":-7,\"count\":\"92.03\"},{\"index\":-8,\"count\":\"96.11\"}]"
Nearly good ! How can I remove all these \" to make it readable ?
Is there a simple Ruby method to apply ?
Thanks
because this is in an erb template, you need to mark the json as html_safe
var errors = <%= d3_chart_series_for(this_object).map { |measure| {index: measure.idx, count: measure.score}}.to_json.html_safe %>

Rails interpolate action_name

I have the following code structure:
<% types = [
{
one: 'one 1',
two: 'two 2',
three: 'three 3'
}
] %>
<% result = types[:#{action_name}]%>
<% puts result %>
The one, two and three are actions I have, which I want to interpolate in the result variable, so the result of an action would get the according object in the types array. How can I do this, what I did seems to return an error.
:#{action_name} it returns an error
Your code is wrong syntactically.
Fix is : :"#{action_name}" . And you don't need a Array of hash, only hash is enough.
<% types =
{
one: 'one 1',
two: 'two 2',
three: 'three 3'
}
%>
There is a couple of things wrong with your solution.
1) types = [{ one: "one1", ... }] is not a hash, it is an array with a hash in it. It looks like you want a hash, so it should be written as types = { one: "one1", ... }
2) You want to access an element from the hash by effectively doing types[:one]. To interpolate a variable into a symbol you need to do use the quotes, i.e. :"#{var}". So the assignment line should be result = types[:"#{action_name}"]
3) It seems you are doing this in a template, which is a strange place to variable assignment of any sort. I suggest you move all this code into a controller (for a start, at least).
If you have array of hash then you can access first array element:
types.first[:"#{action_name}"]
Or you can use loop for accessing hash.
If you need only hash then you should follow #Arup Rakshit answer.

how to add a data-source attribute for x-editable in rails

How, in rails, do you supply a dynamic hash to the source data attribute that x-editable accepts?
<a href="#" data-xeditable="true" data-type="select" data-pk="<%= g.id %>" data-model="graded_item" data-name="teacher_grade_id" data-url="<%= graded_item_url(g) %>" data-source="<%= g.gradescale.grade_scale_items.map{ |x| "{x.id, x.grade}" } %>" data-title="Edit Grade">
<%= g.teacher_grade.try(:grade) %> - <%= g.teacher_grade.try(:name) %>
</a>
The docs want a hash like { value: id, text: name } but I can't seem to get a hash that doesn't result in a red inactive select menu (x-editable doesn't like the source).
Anyone have an example of a dynamic data-source for x-editable in rails?
Per docs
If array - it should be in format: [{value: 1, text: "text1"}, {value: 2, text: "text2"}, ...]
For compatibility, object format is also supported: {"1": "text1", "2": "text2" ...} but it does not guarantee elements order.
update
This created an instance variable that is an array of hashes in the exact format the docs says is needed for an array data-source. But, this also results in an error empty select in the editable popup.
#grade_scale_items = []
#course.gradescale.grade_scale_items.each do |x|
#grade_scale_items << {value: x.id, text: "#{x.grade} - #{x.name}"}
end
Pretty simple fix...after digging a bit. The docs aren't real helpful with this, and the rails examples only uses text fields (no select menus). Convert the array of hashes to json...like so.
#grade_scale_items = []
#course.gradescale.grade_scale_items.each do |x|
#grade_scale_items << {value: x.id, text: "#{x.grade} - #{x.name}"}
end
view: data-source="<%= #grade_scale_items.to_json %>"
This puts it in a format that x-editable is happy with as a data-source

Resources