I'm going through examples from 'Agile Web Dev with Rails' book, but mixing it with extra techniques i found useful - like haml.
Got one tricky issue, how to write down this erb partial:
<% if line_item == #current_item %>
<tr id="current_item">
<% else %>
<tr>
<% end %>
<td><%= line_item.quantity %>×</td>
<td><%= line_item.product.title %></td>
<td class="item_price"><%= number_to_currency(line_item.total_price) %></td>
</tr>
In haml?
Tried sth like this:
-if line_item==#current_item
%tr#current_item
-else
%tr
%td!=line_item.quantity.to_s+"×"
%td=line_item.product.title
%td.item_price=number_to_currency(line_item.total_price)
But it prints out an empty TR without TD within...
Rather than having two separate %tr entries (in which case you would need to list your 3 td's under each tr, I think), you could just set the id in a conditional:
%tr{:id => (line_item == #current_item) ? "current_item" : false}
%td!=line_item.quantity.to_s+"×"
%td=line_item.product.title
%td.item_price=number_to_currency(line_item.total_price)
Related
I have a functioning self-join relationship where a guideline has many children and belongs to a parent. I need to let the user supply an ID via an html form, and then find its children, or its parent (in a separate form of course) When I run in rails console as
#guidelines = Guideline.find(4)
#guidelines.children
I get the proper children, and when i do
#guideline.parent
I get the proper parent.
For some reason when I define a form as
<%= form_tag(guidelines_path, :method => "get", id: "search-form") do %>
<td><%= label_tag(:seeChildren, "See Immediate Children")%></td>
<td><%= text_field_tag :seeChildren, params[:seeChildren], placeholder: "Enter ID" %></td>
<td><%= submit_tag "Search", :name => nil %></td>
<% end %>
(app/views/index.html.erb)
And in the controller i say
if params[:seeChildren]
#guideline = Guideline.find(params[:seeChildren])
#guideline.children
(app/controllers/guidelines_controller.rb)
I get the following error in my rails served in Terminal:
Started GET "/guidelines?utf8=%E2%9C%93&seeChildren=4" for 127.0.0.1 at 2014-10-18 14:25:58 -0500
Processing by GuidelinesController#index as HTML
Parameters: {"utf8"=>"✓", "seeChildren"=>"4"}
Guideline Load (0.3ms) SELECT "guidelines".* FROM "guidelines" WHERE "guidelines"."id" = ? LIMIT 1 [["id", 4]]
Rendered guidelines/index.html.erb within layouts/application (4.1ms)
Completed 500 Internal Server Error in 85ms
ActionView::Template::Error (undefined method `each' for nil:NilClass):
62: <th>Guideline Text</th>
63: </tr>
64:
65: <% #guidelines.each do |guideline| %>
66: <tr>
67: <td><%= guideline.id %></td>
68: <td><%= guideline.guide_desc %></td>
app/views/guidelines/index.html.erb:65:in `_app_views_guidelines_index_html_erb__3376611479089996349_70360485758280'
Rendered /Users/john.dodson/.rvm/gems/ruby-2.1.3#global/gems/actionpack-4.1.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.7ms)
Rendered /Users/john.dodson/.rvm/gems/ruby-2.1.3#global/gems/actionpack-4.1.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.3ms)
Rendered /Users/john.dodson/.rvm/gems/ruby-2.1.3#global/gems/actionpack-4.1.6/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout (21.6ms)
Any ideas? I appreciate the help. Ive posted a couple questions and was unsuccessful usually because I wasn't supplying enough information, so please let me know if you need to see another file.
It looks like you may have forgotten to define #guidlines in your controller, which would explain why you are getting the undefined method 'each' for nil:NilClass error message when attempting to call .each on #guidelines in <% #guidelines.each do |guideline| %>
Yes, Same as JBMILGROm said, you forgot to mention #guidelines in controller.
In addition to using the wrong singular/plural on guidelines, I found out that I needed to cast a single object into an array. So find a guideline, then call children and cast the results into an array. so in the controller I say:
if params[:seeChildren]
#guideline = Guideline.find(params[:seeChildren])
#guidelines = Array.wrap(#guideline.children())
and magic, my query works. Posting this here so other people having a similar problem can find the truth.
When I'm using an if-statement in an erb- template file, the if statement is evaluated delayed, which is mixing up the html:
<small>
<% if #applause_count == 1 %>
The author has been cheered up once!
<% elsif #applause_count > 1%>
The author has been cheered up <%= #applause_count %> times! <br/>Be the next!
<% end if %>
</small>
produces:
<small>
</small>
The author has been cheered up 100 times! <br/>Be the next!
Can someone explain me this strange behaviour?
As noted, the problem is with the <% end if %>
Use <% end %>
This produces the desired html:
<small>
The author has been cheered up 2 times! <br/>Be the next!
</small>
I would like to hide the issue number on the issue list.
I use "Redmine 2.3.1" and the file to achieve that is this file: ./app/views/issues/_list.html.erb
It contains this line:
<%= raw query.inline_columns.map {|column| "<td class=\"#{column.css_classes}\">#{column_content(column, issue)}</td>"}.join%>
And the array query.inline_columns contains the id for example. I thought modifying this array would help me with my problem, but the changes aren't saved.
This is what I tried:
<%= #query.inline_columns.inspect %>
=> [#<QueryColumn:0x00000003607928 #name=:id ... and so on>]
<% #query.inline_columns.delete_at(0) %>
=>
<%= #query.inline_columns.inspect %>
=> [#<QueryColumn:0x00000003607928 #name=:id ... and so on>]
Why was the delete_at useless? And how would I modify this array or hide the number?
A few things to note:
#query.inline_columns might not an array. It may quack like an Array, but it's not.
#query.inline_columns.delete_at(0) should have returned something. Did it return and you ommited?
And last, but not least, the most probable guess I can make:
#query.inline_columns fetches something, converts it to an array and dups it before returning. The only way you can do something like that would be:
some_columns = #query.inline_columns
some_columns.delete_at(0)
some_columns
This is my solution now:
<% if #project.id == 1 %>
<% #qcols = query.inline_columns.reject{ |col| col.name.to_s == 'id' } %>
<% else %>
<% #qcols = query.inline_columns.each %>
<% end %>
So I took advantage of the reject method. And then I work with the #qcols.
Posted on behalf of OP.
I am new to Sinatra.
I work currently on a project that is supposed to use a array,
for example: ary = ['a','b','c']
to covert it into an HTML table (possible using an .erb file).
The table should have a single column with as many rows, as there are strings (dynamic).
for example:
a
b
c
(any other item of the array)
I don't really have a clue how to do that and I tried code from similar projects, that didn't work. I hope its even possible to do.
In the controller do
get '/something' do
#ary = ['a','b','c']
erb :'something'
end
In the view named something you can do
<table>
<% #ary.each do |elem| %>
<tr>
<td>
<%= elem %>
</td>
</tr>
<% end %>
</table>
Say I have a block like this:
<% #help_sections.each do |section| %>
<li><%= section.name %></li>
<% end %>
But on the last record returned, I want to do something else, e.g. applying a class to the li that's there:
<li class="last"><%= section.name %></li>
How do I do that in the most DRY way?
Thanks.
Edit1:
I imagine I would simply use an if statement and the last ruby method, but not sure how to do that within the block? I know that if I just wanted the last element in that array, I could just do #help_sections.last, but that doesn't make sense within the confines of a Ruby block.
The most DRY way is to use CSS instead. Instead of e.g. this:
li.last { color: red; }
..and then cluttering up your markup with an extra CSS class, just use the :last-child pseudoselector, i.e.:
li:last-child { color: red; }
Then you don't have to change anything in your view. This is supported in all modern browsers including IE9.
Try each_with_index:
<% #help_sections.each do |section, index| %>
<li <%= "class='last'" if index == (#help_sections.length-1) %>><%= section.name %></li>
<% end %>
DRY is a good idea in general, but don't kill yourself to keep from repeating a li.
<% #help_sections[0...-1].each do |section| %>
<li><%= section.name %></li>
<% end %>
<li class="last"><%= #help_sections.last.name %></li>
You could either do something like
<% #help_sections.count.times do |i| %>
<%= #help_sections[i].name %>
<%= do_something if #help_sections.count == i - 1 %>
<% end %>
This old answer might help (Tell the end of a .each loop in ruby). Basically, you can use:
<% #help_sections.each_with_index do |section, index| %>
<% if index == #help_sections.size - 1 %>
<li class="last">
<% else %>
<li>
<% end %>
<%= section.name %></li>
<% end %>
If you use each_with_index instead of plain each, the block will also be passed the index of the current element within the collection. You can then compare that to #help_sections.length.
E.g.
<% #help_sections.each_with_index do |section, i| %>
<li<% concat " class='last'" if i == #help_sections.length - 1 %>><%= section.name %></li>
<% end %>
In general cases not covered by smart CSS selectors, you can define a convenient helper method, which would provide each iterated element with its context within the collection. Like this one:
def each_with_context enum
length = enum.count
enum.each_with_index do |elem, i|
context = {
:first => i == 0,
:last => i == length - 1,
:even => i.even?,
:odd => i.odd?,
:middle => i == length / 2
}
yield elem, context
end
end
And then use it within HAML view like this:
-each_with_context(#help_sections) do |section, context|
%li{:class => context[:last] ? 'last' : nil}
=section.name