Order alphabetically and group by first letter - ruby-on-rails

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

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.

Simpler index views

In a Rails index view you iterate the collection and per item in the collection data is presented. In most cases I end up with a complex view, because there is a need to do additional calculations for a specific item in the collection. Here is a typical example:
- if #projects.blank?
= render "shared/placeholder", colspan: "10"
- else
- #hours_total = 0
- #turnover_total = 0
- #projectusers_total = 0
- #projects.each do |project|
- decorate project do |decorates|
- project_calc = ProjectCalculator.new(project)
- hours = project_calc.get_project_data("hours")
- turnover = project_calc.get_project_data("turnover")
- #hours_total += hours
- #turnover_total += turnover
- #projectusers_total += project.projectusers.size
%tr
%td= link_to decorates.data_field(project.name), admin_project_path(project)
%td= decorates.data_field(project.customer.name) unless project.customer.blank?
%td= decorates.data_field(project.company.name_short)
%td= decorates.status
%td= decorates.data_field(project.projectusers.size)
%td= decorates.decimal(hours)
%td= decorates.amount(turnover)
%td= decorates.fixed_price
%td= decorates.show_progress("hours", "compact", hours)
%td= decorates.show_progress("turnover", "compact", turnover)
An improvement I already implemented is to use a decorator for view specific stuff and another one is to use service objects for the actual calculations.
But what bothers me here are all the calculations. What is a solution to make this simpler and ideally not having this in the view?
What about using a Presenter?
This link helped me a lot: http://robertomurray.co.uk/blog/2014/decorators-presenters-delegators-rails/
Here is another Short overview
In your case you could implement it like this
# app/presenter/project_presenter.rb
class ProjectPresenter
attr_accessor :project, :project_calculator
def initialize project
#project = project
#project_calculator = ProjectCalculator.new
end
def hours
project_calculator.get_project_data("hours")
end
def show_progress *args
# calculate progress
end
end
In your controller you can initialize the presenter for every project
#projects = Project.all.collect { |project| ProjectPresenter.new(project) }
So, your view can access the presenter with
- #projects.each do |project|
%tr
%td= project.show_progress('hours')
Hope it will help
ciao boris

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! :-)

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

haml conditional if/else indentation

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

Resources