views:

1238

answers:

3

I have a rails template (.rhtml file) generating a Javascript object. It looks something like the following:

var volumes = {
  <% for volume in @volumes %>
    <%= volume.id %> : <%= volume.data %> 
    <%= ',' unless volume === @volumes.last %>
  <% end %>
};

Note the unless statement modifier to suppress printing the comma after the last element (to satisfy Internet Explorer, which incredibly doesn't support trailing commas in JSON properties declarations).

This appears to work, but as a matter of style, do people think it is reasonable to rely on <%= value unless condition %> in the template generating an appropriate render call?

+6  A: 

I don't see why not, but generally if you find yourself conditionalizing a comma on the last member, you probably want to use join instead:

<%= @volumes.map {|v| "#{v.id} : #{v.data}"}.join "," %>
Jim Puls
A: 

Or even:

<%= @volumes.map { |v| "#{v.id} : #{v.data}"}.to_sentence -%>

To get "a: something, b: something else, c: anything, and d: another thing."

James A. Rosen
Not exactly legal in JavaScript, but hey, whatever turns you on.
Jim Puls
Damn you Jim. You come over to my house and eat my homemade ribs, then you point out in public that I didn't even read the question and notice the "var volumes = ..." What's next, stealing my puppy?
James A. Rosen
Mmm, homemade ribs. Thanks, dude, they were delicious.
Jim Puls
+3  A: 

If you would like to contruct JSON (and BTW you are constructing JavaScript Object not Array) then I suggest to use to_json method:

var volumes = <%= @volumes.inject({}){|h,v| h.merge(v.id=>v.data)}.to_json %>;

or

var volumes = <%= Hash[*@volumes.map{|v| [v.id, v.data]}.flatten].to_json %>;

Even better would be to move Ruby Hash construction to model as it is too complex for view.

class Volume
  def self.to_hash(volumes)
    Hash[*volumes.map{|v| [v.id, v.data]}.flatten]
  end
end

and then in view you can put much simpler code:

var volumes = <%= Volume.to_hash(@volumes).to_json %>;
Raimonds Simanovskis
Thanks, and you're right, it's JSON object, not Array. Fixed in the question.
ykaganovich