haml conditional if/else indentation - ruby-on-rails

I have a situation where I want to add a class to a div tag only when the count is greater than 0
Example:
- #color.shades.each_with_index do |shade, index|
- if index == 0
#shades
- else
#shades.horizontalLine.second
%h3 something
%dl
%dt some
%dd some1
In this example I want everything starting from %h3 to come under either #shades or #shades.horizontalLine.second depending on however those if and else statements evaluate.
work around is:
- #color.shades.each_with_index do |shade, index|
- if index == 0
#shades
%h3 something
%dl
%dt some
%dd some1
- else
#shades.horizontalLine.second
%h3 something
%dl
%dt some
%dd some1
but here I have to repeat code
I'm stumped at how to do this in rails without repeating the code starting from %h3 for both the divs.

You can set the class to a variable holding the class names based on the index to DRY it up:
- #color.shades.each_with_index do |shade, index|
- shade_classes = index == 0 ? '' : 'horizontalLine second'
#shades{ :class => shade_classes }
%h3 something
%dl
%dt some
%dd some1

Related

How to break inside an haml loop?

It could be a stupid question, but that is why I prefer to ask here.
I have this code below in HAML:
- #calendar[:array_number_day].each.with_index do |num_d, index|
%tr
- (0..6).each do |i|
- if (#calendar[:array_name_day][index] == i)
%td
%span #{num_d}
- else
%td
How can I break the each loop in this case ? I tried #{break} and break after %span #{num_d} but without success.
Thank's in advance for the help,
- break should work:
- #calendar[:array_number_day].each.with_index do |num_d, index|
%tr
- (0..6).each do |i|
- if (#calendar[:array_name_day][index] == i)
%td
%span #{num_d}
- break
- else
%td
Make sure you have - and use the proper indentation (it should be one indentation level deeper than the if statement.

View helper to split list in two column

I have a little problem.
I'm rendering a definition list in my haml view. Here is the code.
.col
- #product.data.each do |features_group_id, features_group|
.data-group
%h3= features_group["name"]
%dl
- features_group['features'].each do |id, hash|
- if #product.product_category.show_feature_ids.include?(id)
%span.data-wrap
%dt
= hash['name']
%dd
= hash['value']
I must split this list in two column.
I must take product.data.count/2 and show the two blocks in two column
.col
- #product.data_batch1.each do |features_group_id, features_group|
.data-group
%h3= features_group["name"]
%dl
- features_group['features'].each do |id, hash|
- if #product.product_category.show_feature_ids.include?(id)
%span.data-wrap
%dt
= hash['name']
%dd
= hash['value']
.col
- #product.data_batch2.each do |features_group_id, features_group|
.data-group
%h3= features_group["name"]
%dl
- features_group['features'].each do |id, hash|
- if #product.product_category.show_feature_ids.include?(id)
%span.data-wrap
%dt
= hash['name']
%dd
= hash['value']
Any easy solution to do this?
You can use in_groups_of, given that #product.data is or acts as an Array.
From your code:
- #product.data.in_groups_of(2, false).each do |group|
.col
- group.each do |features_group_id, features_group|
.data-group
%h3= features_group["name"]
%dl
- features_group['features'].each do |id, hash|
- if #product.product_category.show_feature_ids.include?(id)
%span.data-wrap
%dt
= hash['name']
%dd
= hash['value']
There is even a Railscast on this! :-)

Order alphabetically and group by first letter

I currently have the following code:
- #alpha = Glossary.find(:all, :order =>"title ASC").group_by{|u| u.title[0]}
- #glossary = Glossary.find(:all, :order =>"title ASC")
- #alpha.each do|a|
%h1= a[0]
- #glossary.each do |g|
%p display stuff
This displays all of the glossary terms under each letter rather than only the ones that begin with the letter.. I've tried a few things but I'm not sure how to select the right thing.
You should be able to do everything with your #alpha instance variable, since you're using group_by:
- #alpha = Glossary.find(:all, :order =>"title ASC").group_by{|u| u.title[0]}
- #alpha.each do |alpha, glossary_array|
%h1= alpha
- glossary_array.each do |item|
%p= item
You're close. I think you just want to do
- #alpha = Glossary.order("title ASC").group_by{|u| u.title[0]}
- #alpha.each do |letter, items|
%h1= letter
- items.each do |item|
%p= item

Rails + Bootstrap 3: Have two columns in a row, but have them collapse one column after another

This is an odd problem I'm having. I have a list of names, split up into two arrays at the middle. So names A-M are in name1 and names N-Z are in name2. Now I'm going through each array and putting them in a row with two columns so the names look like this:
Aaron Neil
Arthur Nick
etc. But when I collapse the page down, it looks like:
Aaron
Neil
Arthur
Nick
and I want it to look like:
Aaron
Arthur
Neil
Nick
Here's the haml:
- a = true
- index = 0
- while(a)
- first = name1[index]
- second = name2[index]
- if first != nil || second != nil
.row
.col-md-6
- if first
= first
.col-md-6
- if second
= second
- index += 1
- else
- a = false
I understand why this is happening, but I'm not exactly sure how else to approach this. Does anyone have any insight?
You are creating a new row and column for each set of names.
instead you should run your loop inside the columns like this:
- name1 = %w[Aaron Arthur]
- name2 = %w[Neil Nick]
.row
.col-md-6
-name1.each do |x|
%p= x
.col-md-6
-name2.each do |x|
%p= x

Rails loop refactor

I have created a loop, to calculate a total rating of a record. To do this I am first looping through all the child records (ratings), extracting the rating from each row, adding it to the total and then outputting the total.
<% total = 0 %>
<% for ratings in #post.ratings %>
<% total = (total + ratings.rating) %>
<% end %>
<%= total %>
My question is, simply, Is this the rails way?
It achieves the desired result, although needs 5 lines to do so. I am worried I am bring old habits from other languages into my rails project, and I am hoping someone could clarify if there is an easier way.
The following, preferably in the controller, will do it succinctly:
#rating = #post.ratings.sum { &:rating }
If that seems cryptic, you might prefer
#rating = #post.ratings.inject(0) { |sum, p| sum + p.rating }
Note, however, that this will fail if any of the ratings are null, so you might want:
#rating = #post.ratings.inject(0) { |sum, p| sum + (p.rating || 0) }
You should generally keep logic out of your views. I would put that code in a helper or a controller, and the call a method to calculate the total
Put the following in your controller, then you just need to use #rating in your view:
total = 0
#rating = #post.ratings.each { |r| total += r.rating }
Or you could move it into the Post model and do something like:
def self.total_rating
total = 0
ratings.each { |r| total += r.rating }
total
end
and then simply call #post.total_rating

Resources