Ruby .each but need to add in a unique class for each of them - ruby

i have the following piece of code that loops through and shows the results however i want to be able to set a class for each of the <td> and unsure how to do this as i dont know ruby and doing the frontend on a ruby project.
<% priority[1].each do|val|%>
<td><%=val[1] %></td>
<% end %>
It just shows 4 of them so if i can set defined classes great but if not something like class1, class2, class3, class4 would be fine i guess.
Many Thanks

You could do this:
<% priority[1].each_with_index do |val,i| %>
<td class="class<%= i %>"><%= val[1] %></td>
<% end %>
Which will give every element a unique class of 'class1','class2' etc for all i.
Marginally more complicated, but this example allows you assign your own class names:
<% arr = ['Hi','Hello','Howdy','Yo'] #class names %>
<% priority[1].each_with_index do |val,i| %>
<td class="<%= arr[i] %>"><%= val[1] %></td>
<% end %>

Related

simple_form - can't generate combined select input

I have complex form with a lot of controls, and I'm currently using simple_form gem due to its flexibility. But when I wanted to do something more complex I faced to several problems that currently looking obscure for me. I would like to introduce combined collection input, that will render both optgroups and single non-groupped selects. Generated html that I want to achieve should look something like this:
<select name="select" multiple="multiple">
<option value="1">Milk</option>
<optgroup label="Soda">
<option value="2">Cola</option>
<option value="3">Fanta</option>
</optgroup>
</select>
I've tried to create custom input class, but stucked on implementation details of input method, I simply couldn't find out how to generate proper output.
UPDATE
Currently quick and dirty implementation for custom input looks something like this, but I don't think that it is a good idea to drop all goodnesses with options that simple_form gives me.
class CombinedMultiselectInput < SimpleForm::Inputs::CollectionSelectInput
include ActionView::Helpers::FormTagHelper
include ActionView::Helpers::FormOptionsHelper
def input
out = ActiveSupport::SafeBuffer.new
option_tags = ungrouped_options.safe_concat(grouped_options)
out << select_tag(options[:name], option_tags, class: ['select', 'form-control'])
out
end
private
def ungrouped_options
# this can be retrieved from general collection like collection[:ungrouped]
collection = [["Foo", 2], ["Bar", 3]]
options_for_select(collection)
end
def grouped_options
# and this using collection[:grouped]
collection = [["Group", [["Foobar", 4]]]]
grouped_options_for_select(collection)
end
end
Using your current design you can combine the options_for_select and option_groups_from_collection_for_select methods like so.
def ungrouped_options
[["Foo", 2], ["Bar", 3]]
end
def grouped_options
[["Group", [["Foobar", 4]]]]
end
def your_hash
{"ungrouped" => ungrouped_options, "grouped" => grouped_options}
end
Then in your view something like this should work:
<%= content_tag(:select,nil,{multiple: true,name: "select"}) do
<%= your_hash.each do |k,v| %>
<% if k == "ungrouped" %>
<%= options_for_select(v) %>
<% else %>
#this works because:
# last will be the collection of children for a member
# first will be the group name
# last on the child will be the value method
# first on the child will be the text displayed
<%= option_groups_from_collection_for_select(v, :last, :first, :last, :first) %>
<% end %>
<% end %>
<% end %>
This will create the following:
<select name=\"select\" multiple=\"true\">
<option value=\"2\">Foo</option>
<option value=\"3\">Bar</option>
<optgroup label=\"Group\">
<option value=\"4\">Foobar</option>
</optgroup>
</select>
Obviously this was simplified to show how this could be done but hopefully this points you in the right direction.
You should also be able to wrap this for simple_form although I have not tested it.
<%= f.input :some_attribute do %>
<%= f.select :some_attribute do %>
<%= your_hash.each do |k,v| %>
<% if k == "ungrouped" %>
<%= options_for_select(v) %>
<% else %>
<%= option_groups_from_collection_for_select(v, :last, :first, :last, :first) %>
<% end %>
<% end %>
<% end %>
<% end %>

erb idiom to handle undefined variable

I'm trying to write some puppet .erb, I'd like to handle this "environment" variable if it's:
undefined
a string with newlines
an array.
I've got as far as this:
<% Array(environment).join("\n").split(%r{\n}).each do |f| %>
one line: <%= f %>
<% end %>
But haven't gotten around the undefined case yet. I've tried this
<% if (defined?(environment)).nil? %?
<% Array(environment).join("\n").split(%r{\n}).each do |f| %>
one line: <%= f %>
<% end %>
<% end %>
but am still getting "(erb):11: undefined local variable or method `environment' for main:Object (NameError)" when trying to test it like this:
ruby -rerb -e "environmentUNDEFINEME= [ 'cronvar=cronval', 'var2=val2' ];
puts ERB.new(File.read('templates/job.erb')).result"
Sorry this is so basic, but somebody's got to ask the easy questions. Any help?
I would do this:
<% if defined?(environment) %>
<% Array(environment).each do |f| %>
one line: <%= f %>
<% end %>
<% end %>
I didn't understand why you joining on new lines and then splitting on them again, so I removed it from the example.

Determine index of element in Array.each

I'm trying to render a bulk of content in rows of three. However, I'm not sure how would I determine the current position of the element using Ruby. This is what I have:
<% Animals.each do | animal | %>
<%= animal.species %>
<% end %>
I want to be able to add a <BR> or if I was rendering a table a </TR><TR> each time we'd hit the third animal in the set. Of course, if the number of elements nE isn't divisible by three, then the table would be malformed. I figured by doing a bit of checking after the iteration that I could close it.
But is there a way to get the index of an element that's being iterated over in an Array.each method? I have the strong hunch that I could just do the following:
<table>
<% Animals.each do | animal | %>
<% if Animals.find_index(animal) / 3 == 0 %>
<tr>
<% end %>
<td><%= animal.species %></td>
<% if Animals.find_index(animal) / 3 == 2 %>
</tr>
<% end %>
</table>
My only thing is that Animal is a subclass of ActiveRecord::Base, so I'm not sure (haven't looked to see) if this would scale well, let alone if each call to find_index would be a super intensive method. Any suggestions are welcome.
You need
<% animals = Animals.all %>
<table>
<% animals.in_groups_of(3) do |animal_row| %>
<tr>
<% animal_row.compact.each do |animal| %>
<td><%= render animal %></td>
<% end %>
</tr>
<% end %>
</table>
Should roughly do the job.
More importantly, I think keeping the Enumerable module's documentation handy has been great for me as a Ruby developer. It is my "favourite" module, and nearly ALWAYS helps me solve tricky problems easily.

Ruby each, different action depending on index, with a pattern?

Ok so my title may be confusing. What I want to do is to loop through a collection of models, and for the first two, render a template, for the next four render a different template and next two render the same template as for the first ones, and so on.
Like this:
<% ads.each do |ad| %>
<% # if it's 1-2, 7-8, 13-14 and so on render as big' %>
<%= render 'front/home/big_ad', ad: ad %>
<% # if it's 3-6, 9-12, 15-18 and so on render as small' %>
<%= render 'front/home/small_ad', ad: ad %>
<% end %>
<% end %>
What would be the cleanest way to accomplish this?
If your groups would be even long, then you could use in_groups_of command, and alternate between them, but with these specifications, the easiest way is this:
<% ads.each_with_index do |ad, index| %>
<% if (index % 6 < 2) %>
<%= render 'front/home/big_ad', ad: ad %>
<% else %>
<%= render 'front/home/small_ad', ad: ad %>
<% end %>
<% end %>

Sorting and manipulating a hash in Ruby

In my rails 3.1 project I have a Book model that has a ID, NAME, and BOOK_ORDER. I am using the ranked-model gem, which for its sorting process creates large numbers in the sorting(:book_order) column. Im looking for some help to create a method to sort all of the Books by the :book_order column, then simplify the :book_order numbers.
So, I have this:
controller
#books = Books.all
view
<% #books.each do |book| %>
<%= book.book_order %>
<% end %>
# book1.book_order => 1231654
# book2.book_order => 9255654
# book3.book_order => 1654
But want this:
view
<% #books.each do |book| %>
<%= book.clean_book_order %>
<% end %>
# book1.clean_book_order => 2
# book2.clean_book_order => 3
# book3.clean_book_order => 1
Additionally, i don’t want to change the database entry, just use its current values to make simpler ones.
Thanks!
UPDATE:
Thanks to nash’s response I was able to find a solution:
In my Book Model I added the clean_book_order method:
class Book < ActiveRecord::Base
include RankedModel
ranks :book_order
def clean_book_order
self.class.where("book_order < ?", book_order).count + 1
end
end
<% #books.each do |book| %>
<%= book.book_order_position %>
<% end %>
EDIT:
Oh, I see. https://github.com/harvesthq/ranked-model/issues/10

Resources