bootstrap format rails output in columns - ruby-on-rails

I'm trying to figure out how to align my rails output into 3 columns of equal length using bootstrap. Basically i need three columns, the issue is that if I have 12 "skills" i would like them to be divided up into 4 skills in each section, etc...
But I can't figure out how to output the data in anything but a one column list. I'm thinking I need something like this?
<div class="col-md-4">
< ... output of skills >
</div>
<div class="col-md-4">
< ... output of skills >
</div>
<div class="col-md-4">
< ... output of skills >
</div>
This is my current output that makes a list, I would like to somehow make 3 columns out of the output.
<div class="col-md-12">
<table>
<!-- one-to-many association to loop through a users skills -->
<% #user.skills.each do |skill| %>
<tr>
<td>
<br />
<h4><b><%= link_to skill.name, edit_user_skill_path(user_id: #user.id, id: skill.id) %></b></h4>
</td>
</tr>
<% end %>
</table>
</div>
update
here's the solution I implemented based off of martin's suggestion.
<% #user.skills.in_groups_of(3, false).each do |group| %>
<div class='row'>
<% group.each do |skill| %>
<div class='col-md-4'>
<div><%= skill.name %></div><br />
</div>
<% end %>
</div>
<% end %>
also because the text was being displayed within a panel i found that it was running off the edge so had to use this for the CSS
.panel-body{
word-wrap: break-word;
}

You can try using in_groups_of method: https://apidock.com/rails/v4.2.7/Array/in_groups_of

Related

Loop through hash in rails

I have some functionality where I client can create custom fields, what I'm trying to do now is to loop through that data but I can't seem to get it to work.
Here are the params when we create or update a record, I've removed some as I'm only trying to loop through custom_fields_attr
Parameters: {... "custom_fields_attr"=>{"1"=>"testing12", "2"=>"", "3"=>"", "4"=>""}}, ...}
I have the following code:
<!-- start of custom fields -->
<% if Contact.has_custom_fields %>
<div class="form-block">
<h2 class="txt-title-alt">Custom Fields</h2>
<% Contact.custom_fields.in_groups_of(2).each do |field| %>
<div class="l-row-block clearfix">
<% field.each do |item| %>
<div class="l-06col l-ml-12col l-md-12col">
<div class="field field_display l-row-block clearfix">
<p class="like_p clearfix">
<strong class="l-06col">
<%= item.label %>:
</strong>
<span class="value l-06col">
<%= item.value %>
</span>
</p>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
<% end %>
<!-- end of custom fields -->
I have a custom fields table which is where we get the label from but I need to get the value from the custom_fields_attr hash
Edit
The output of #contact.custom_fields_attr is
>> #contact.custom_fields_attr
=> {"1"=>"test field123"}
Instead of doing field.each do |item| try field.each do |key, value|. This lets you access the key and value of each hash pair in your block.
Could you tell me what is the output of Contact.custom_fields?
Can you tell, how the client is creating the custom fields, because if they are params send to the controller, you can access the params in the controller, in this case you want "custom_fields_attr", you can call it by params["custom_fields_attr"] and then to loop through it params["custom_fields_attr"].each do |key, value| calling in each time key = "1" and value = "testing12" then key = "2" and value = "" and etc.

Can I build several objects in different parts of a page?

I have a Page model that has many TextBlock:
class Page < ApplicationRecord
has_many :text_blocks, as: :textable, dependent: :destroy
accepts_nested_attributes_for :text_blocks
end
In the form where a page can be edited, I have to display 3 text blocks in the upper part of the form, and 3 text blocks in the lower part of the form. Here is the code in my view...
Upper text blocks:
<%= render 'shared/admin/form-fields/text-blocks-form', f: f, number: 3, value: true %>
Lower text blocks:
<%= render 'shared/admin/form-fields/text-blocks-form', f: f, number: 2, value: false %>
And here is the text-blocks-form partial:
<div class="form-group">
<div class="row">
<div class="col-lg-12 text-blocks">
<div class="row">
<% number.times { f.object.text_blocks.where(upper_position: value).build } unless f.object.text_blocks.where(upper_position: value).any? %>
<%= f.fields_for :text_blocks do |input| %>
<div class="<%= "col-lg-#{cells(number)}" %>">
<%= render 'shared/admin/form-fields/text-blocks-fields', f: input, value: value %>
</div>
<% end %>
</div>
</div>
</div>
</div>
Upper text blocks are built as expected, there are 3 blocks but in the lower part of the form, there are 5 blocks instead of 2. It seems, that it just add 3 + 2. Is there any way to build text blocks as it was described above? Thanks ahead.
I can easily explain why you have this problem, maybe a little less easy to fix this in good way.
The reason why have this that in the first run you create three nested items (on the association), and then iterate over them using f.fields_for :text_blocks, and in the second run you add two more, and then iterating over f.fields_for :text_blocks will iterate over all five created blocks.
An easy fix would be to change your view as follows:
<div class="form-group">
<div class="row">
<div class="col-lg-12 text-blocks">
<div class="row">
<% number.times { f.object.text_blocks.where(upper_position: value).build } unless f.object.text_blocks.where(upper_position: value).any? %>
<%= f.fields_for :text_blocks do |input| %>
<%- if input.object.upper_position == value %>
<div class="<%= "col-lg-#{cells(number)}" %>">
<%= render 'shared/admin/form-fields/text-blocks-fields', f: input, value: value %>
</div>
<% end %>
<% end %>
</div>
</div>
</div>
</div>
If you always have 5 blocks (3 on top and 2 below), I would also consider adding a position or order column, allowing the textblocks to be re-rendered in the correct position after save as well.

Splitting record set in Rails for display purposes in menu

I'm trying to split my records in half for display in my menu. The menu is two columns (col-md-4) but the methods I'm using with ODD number of records, puts the larger number on the wrong side (last_half) of my menu. What am I missing?
Menu
<div class="col-md-4">
<ul>
<li class="mega-menu-title">Products</li>
<% first_half(#menu_products).each do |product| %>
<li>
<%= link_to product_path(product) do %>
<span class="text-yellow"><%= product.name %></span> <%= product.subtitle %>
<% end %>
</li>
<% end %>
</ul>
</div>
<div class="col-md-4">
<ul>
<li class="mega-menu-title"> </li>
<% last_half(#menu_products).each do |product| %>
<li>
<%= link_to product_path(product) do %>
<span class="text-yellow"><%= product.name %></span> <%= product.subtitle %>
<% end %>
</li>
<% end %>
</ul>
</div>
<div class="col-md-4">
<!--- non-related code in last column in menu --->
</div>
Application Helper
def first_half(list)
list[0...(list.length / 2)]
end
def last_half(list)
list[(list.length / 2)...list.length]
end
You can use the following:
list.first((list.length/2).ceil) # will convert 1.5 to 2
And
list.last((list.length/2).floor) # will convert 1.5 to 1
The issue you had is that [7,8,9][3/2] returns 8, and the logic 3/2 (list.size / 2) was used in both first_half and last_half.
This is what I ended up doing to get it to work. I had to change the length to a float to_f, then I could get it to test in the console correctly.
def first_half(list)
list[0...(list.length.to_f / 2).ceil]
end
def last_half(list)
list[(list.length.to_f / 2).ceil...list.length]
end
Using .ceil on both methods then allowed the math to work.

Duplicate Results From Search Params

I have a search method and two models, restaurants and menus.In the menu search method, if I search for "chicken" it shows the closest restaurants near the location that sells meals with word chicken example "chicken sandwich" with the use of association. The problem is, if a restaurant sells multiple chicken meals the restaurant is rendered several times.I want to be able to show restaurants once and when the button is clicked a modal shows the meals with "chicken" in the name using a loop if there are multiple meals with chicken. I tried adding uniq & uniq(&:restaurant_id) in the ActiveRecord and also controller & also trying "DISTINCT" using sql but nothing.
Controller
def search_for_menus
##restaurant= Menu.restaurant.all
#menus = Menu.search_for_menus(params)
end
Menus Model
belongs_to :restaurant
reverse_geocoded_by "restaurants.latitude", "restaurants.longitude"
def self.search_for_menus(params)
menus=Menu.where("dish LIKE ?", "%#{params[:dish]}%") if params[:dish].present?
menus = menus.where("menus.price <=?",params[:max ])
menus = menus.where("menus.price >=?",params[:min ])
menus= menus.joins(:restaurant).near(params[:location],2)
menus
end
end
Search Page HTML
<% if #menus.present? %>
<%#menus.each do |menu| %>
<br>
<br>
<div id ="restaurants">
<div class="box">
<div class="thumbnail box-image">
<%= link_to (image_tag (menu.restaurant.thumbnail.url(:medium))),restaurant_path(menu.restaurant),'data-no-turbolink' => true%>
<div class="caption">
<h3 class="text-center"><%=menu.restaurant.name%></h3>
<p class="text-center">View Food</p>
</div>
</div>
</div>
<div id="modal-<%= menu.id %>" class="modal fade bs-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="col-md-6">
<p><%= menu.dish %></p>
</div>
<div class="col-md-6">
<p><%= menu.price %></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>
</div>
<%end%>
</div>
<%else%>
<p>no posts</p>
<%end%>
What you need to start with, I think, is the restaurants for which there exists a matching menu item.
restaurants = Restaurant.near(params[:location],2).
where(Menu.where("menus.restaurant_id = restaurants.id").
where("dish LIKE ?", "%#{params[:dish]}%").
where("menus.price <=?",params[:max ]).
where("menus.price >=?",params[:min ]).exists)
This is guaranteed to return one row per restaurant.
You might want ILIKE for a case insensitive dish search, if your RDBMS supports it.
You can then list the appropriate menu items for the matching restaurants.
After discussing over chat, here's an update, thanks #David for the query.
Menu model:
belongs_to :restaurant
reverse_geocoded_by "restaurants.latitude", "restaurants.longitude"
def self.search_for_restaurants(params)
Restaurant.near(params[:location],2).
where(Menu.where("dish LIKE ?", "%#{params[:dish]}%").
where("menus.price <=?",params[:max ])
where("menus.price >=?",params[:min ]).exists)
end
Put this in the restaurant model (here you are going to fetch all the matching menus for the view):
def search_for_matching_menus dish
menus.where("dish LIKE ?", "%#{dish}%")
end
View (you have to adjust it to your needs, I just want you to understand the idea):
<% if #restaurants.present? %>
<%#restaurants.each do |restaurant| %>
<br></br>
<br></br>
<div id ="restaurants">
<div class="box">
<div class="thumbnail box-image">
<%= link_to (image_tag (restaurant.thumbnail.url(:medium))),restaurant_path(restaurant),'data-no-turbolink' => true%>
<div class="caption">
<h3 class="text-center"><%=restaurant.name%></h3>
<%= restaurant.search_for_matching_menus(#dish).each do |menu| %>
<%= menu.id %>
<% end %>
</div>
</div>
</div>
<%end%>
<%end%>
And finally this has to go on the controller that calls the search, to forward the dish parameter:
#dish = params[:dish]

dynamic bootstrap tabs with rails

I am trying to get rails to generate dynamic navigation tabs that refer to groups user is enrolled at. Basically, what I want to achieve is to dynamically have tabs named after groups that user is enrolled at (which is working fine) and then showing the content of each group by clicking on its tab (which is not working properly for some reason). The page loads data correctly but toggling between tabs doesn't work
Here is the code in the view
<div class="tabbable tabs-left">
<div class="row">
<div class="col-md-4">
<ul class="nav nav-pills nav-stacked">
<% current_user.group.each do |group| %>
<li><a href="#<%= group.name %>" data-toggle="tab">
<%=group.name %></a></li>
<% end %>
</ul>
</div>
<div class="col-md-8">
<div class="tab-content">
<% current_user.group.each do |group| %>
<div class="tab-pane fade <%= 'in active' if current_user.group.first == group %>" id="<%=group.name%>">
<% if current_user.group_feed(group.id).any? %>
<ol class="microposts">
<%= render current_user.group_feed(group.id) %>
<%= group.name %>
</ol>
<% end %>
</div>
<% end %>
</div>
</div>
</div>
</div>
Is there something that I am missing?
The problem is group.name producing an invalid html id attribute.
html ids should not start with a number(numbers anywhere else are ok), and have no spaces. Example:
Invalid:
1foo
aaa b
Valid:
foo1
aaa-b
group.name.parameterize will remove any odd chars(#£$ etc) and replace spaces with "-" so use that.
You also want to make this unique as things with names like: "foo" and "foo!" will parameterize to the same thing: "foo".
I'd go with:
id="<%=(group.name.gsub(/[0-9]+/, "")+group.id.to_s).parameterize%>"
This code, removes any number from the name(it only really applies at the start of the id) then adds the id on the end making it unique.

Resources