nested content_tag designing table
I'm stuck...
I'm trying to create a table helper in my application helper like this:
def simple_grid(theGrid, theData)
content_tag :div, :class => "text_area_show" do
content_tag :table, :width => "95%" do
concat content_tag :tr, "" do
theGrid['fields'].each do |field|
开发者_JAVA百科concat content_tag(:th, field)
end
end
theData.collect do |record|
concat content_tag :tr do
theGrid['fields'].collect do |field|
concat content_tag(:td, record[field], :align => "center")
end
theGrid['right_links'].collect do |right_link,path|
case right_link
when 'show'
concat content_tag(:td, link_to(right_link, "#{path}#{record.id}"), :align => "center")
when 'edit'
concat content_tag(:td, link_to(right_link, "#{path}#{record.id}/edit"), :align => "center")
end
end
end
end
end
end
end
with this in my controller:
@users = User.all
@grid = {'fields' => ['firstname','lastname','email'],
'right_links' => {'show' => '/admin/users/', 'edit' => '/admin/users/'}
}
And this in my view:
<%= simple_grid(@grid, @users) %>
This generates the following html:
<div class="text_area_show"><table width="95%"><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr><tr></tr></table></div>
I miss all my td tags.
Any help to tell my what's wrong would be highly appreciated!
Nicolas.
This is what I did first but, as a newbie to Rails, I'm trying to think the Rails way...
The best solution I found until now is:
def simple_grid(theGrid, theData)
content_tag :div, :class => "text_area_show" do
concat(content_tag(:table, :width => "95%") do
concat(content_tag(:tr) do
theGrid['fields'].collect do |field|
concat(content_tag(:th, field))
end
end)
theData.collect do |record|
concat(content_tag(:tr) do
theGrid['fields'].collect do |field|
concat(content_tag(:td, record[field], :align => "center"))
end
theGrid['right_links'].collect do |right_link,path|
case right_link
when 'show'
concat(content_tag(:td, link_to(right_link, "#{path}#{record.id}"), :align => "center"))
when 'edit'
concat(content_tag(:td, link_to(right_link, "#{path}#{record.id}/edit"), :align => "center"))
end
end
end)
end
end)
end
end
It is pretty ugly but it works. Any suggestion to do better work is welcome!
content_tag
is only suitable for simple helpers. For complex helpers it's far better to use a partial :
def simple_grid( grid, data )
render partial: '/shared/simple_grid', locals: { grid: grid, data: data }
end
so you can take advantage of your favourite template engine. Notice that i usually store such partials in a 'shared' folder in 'app/views', but it's up to you. The helper in this case is not even mandatory, but it can be useful at times when you need to process data before rendering.
Another approach would be the decorator pattern (using the Draper gem), but it's another topic.
Had a nightmare of a time trying to resolve your issue because of the multiple content_for tags. Read in the API docs that you need to always use .collect instead of .each and that for multiple content_for tags within a block you need to use concat... but try as I might, I can't get it work either..
Last resort you could always fall back to:
@output = "<div class='text_area_show'>
<table width='95%'>
<tr>"
theGrid['fields'].each { |field| @output += "<th>#{field}</th>"}
@output += "</tr>"
theData.collect do |record|
@output += "<tr>"
theGrid['fields'].each { |field| @output += "<td align='center'>#{record[field]}</td>"}
theGrid['right_links'].collect do |right_link,path|
case right_link
when 'show'
@output += "<td align='center'>#{link_to(right_link, "#{path}#{record.id}")}</td>"
when 'edit'
@output += "<td align='center'>#{link_to(right_link, "#{path}#{record.id}/edit")}</td>"
end
end
@output += "</tr>"
end
@output += "</table></div>"
@output
精彩评论