Using Rails and HAML to output objects in pairs - ruby-on-rails

Iterating over 'posts' I want to create a row div which will contain two post divs:
<div id="row">
<div id="post"> ... </div>
<div id="post"> ... </div>
</div>
<div id="row">
<div id="post"> ... </div>
<div id="post"> ... </div>
</div>
If I try this:
- #posts.each_with_index do |post,index|
- if index %2 == 0
.row
.post
- else
.post
...then I get:
<div class="row">
<div class="post"></div>
</div>
<div class="post"></div>
<div class="row">
<div class="post"></div>
</div>
<div class="post"></div>
I can see why this happens but I can't figure out how to do it correctly. Any ideas?
UPDATE:
When accessing object attributes as per apneadiving's suggesion, I receive errors when the last slice contains only a single post. For example, the following...
- #posts.each_slice(2) do |post1, post2|
.row
.post= post1.title
.post= post2.title
returns the error "undefined method `title' for nil:NilClass" when there are an odd number of posts. To get around this I have used this:
- #posts.each_slice(2) do |post1, post2|
.row
.post= post1.title
.post= post2.title unless post2.nil?

I'd take my posts 2 by 2, I can't see how to do otherwise with haml:
- #posts.each_slice(2) do |post1, post2|
.row
.post= post1
.post= post2

For tasks like this i prefer to use erb templates, that adds more flexibility, use it and you will see that your problem will solve so easy. Structuring of haml imposes some restrictions on the tasks implementation.
<% #posts.each_with_index do |post, index| %>
<% if index %2 == 0 %>
<div class="row">
<% end %>
<div class="post></div>
<% if index %2 != 0 %>
</div>
<% end %>
<% end %>

Related

Rails Helper create unintended Array ouput

I have created a rails helper method, So far so good the only problem is it created an unexpected array ouput.
I did try the key value pair using the each method but the array still there.
I'm trying to figure it out how to remove the unexpected array
My application_helper.rb
def bid_items(origin, destination)
item = Item.where(item_deliver_from: origin).where(item_deliver_to: destination).where(shopper_id: current_user)
end
My search_results.html.rb
<%= bid_items(trip.origin, trip.destination).each do |item| %>
<div class="card border-0">
<%= image_tag item.cover_image_url(:cover_image_medium), class: "card-img-top" %>
<div class="card-body">
<h5 class="card-title"><%= item.name %></h5>
</div>
</div>
<% end %>
Though I got the intended results still, there's an unexpected array
check the image
I just want to remove this area
See Red X
Remove = sign from <%= bid_items(trip.origin, trip.destination).each do |item| %>
So, make it <% bid_items(trip.origin, trip.destination).each do |item| %>

Rails - conditional display of html block

On my views I use 1 form that includes a block that renders comments. I do not want to run it when creating a new record. So, I tried conditions like so...
<% unless #annotation_id.nil? %>
<hr>
<div class="row">
<div class="col-md-8">
<h4>Comments</h4>
<%= render #annotation.comments %>
</div>
<div class="col-md-4">
<%= render 'comments/form' %>
</div>
</div>
<% end %>
This however results in never displaying the block - also when the annotation record exists. What am I doing wrong?
You don't show that you have actually set #annotation_id to something.
A simpler way might be to use the .new_record? method instead, like:
<% unless #annotation.new_record? %>
...
<% end %>
use if #annotation.persisted? or unless #annotation.new_record?

HTML Snippets that repeat in the Rails views

I am using a bootstrapping framework, that has the following snippet, which I use a lot:
<div class="panel panel-default">
<div class="panel-heading">...</div>
<div class="panel-body">
...
</div>
</div>
(The snippet will be actually bigger, but I want to start small)
So I thought I would build a partial and use it, something like this:
Partial
<div class="panel panel-default">
<div class="panel-heading"><%= title %></div>
<div class="panel-body">
<%= yield %>
</div>
</div>
Use example
<%= render partial: "panel", locals: { title: "Hello" } do %>
Testing
<% end %>
But this apparently is not working. I get the following error:
'nil' is not an ActiveModel-compatible object. It must implement :to_partial_path.
Am I doing something wrong here? Did I understood partials wrong?
In order for yield to work I think you need to use render :layout instead of/in addition to :partial:
<%= render layout: "panel", locals: { title: "Hello" } do %>
Testing
<% end %>
Have a read of the PartialRenderer examples for more information

Call a method associated with partial rails

In my controller I have this method that retuns to me the list of specific books controller/books_controller
def postings
#books = Book.postings(current_user.id).order("created_at ASC")
render :partial =>'postings'
end
I have a partial in views/books/_postings.html.erb
<div class="container">
<h4>My Partial Postings</h4>
<% #books.each do |book| %>
<div class="row">
<div class="col-sm-2"><img src="<%= book.image_path %>" alt="..." class="img-responsive"/></div>
<div class="col-sm-10">
<h4 class="nomargin"><%= book.title %></h4>
<p><%= book.description %></p>
<p>Quantity: <%= book.quantity %></p>
<p>Available for: <%= book.sale_type %></p>
</div>
</div>
<hr>
<% end %>
</div>
In my routes :
resources :books do
collection do
get 'postings'
end
end
on running rake routes :
postings_books GET /books/postings(.:format) books#postings
When I use localhost:3000/books/postings I get the desired partial showing list of books .But when I want to call this partial from some other view eg from localhost:3000/dashboard/index:
<div class="tab-pane" id="postings">
<%= render 'books/postings', :collection => #books %>
</div>
I get the following error:
Showing /home/swati/867/WorkSpace2/assignment_3/app/views/books/_postings.html.erb where line #4 raised:
undefined method `each' for nil:NilClass
Extracted source (around line #4):
<div class="container">
<h4>My Partial Postings</h4>
<% #books.each do |book| %>
<div class="row">
<div class="col-sm-2"><img src="<%= book.image_path %>" alt="..." class="img-responsive"/></div>
<div class="col-sm-10">
I understand that render is just rendering the partial without calling my method postings in books_controller and my partial has no access to #books , which is nil. How can aprroach this ?
When you access dashboard/index you are actually calling index method of dashboards_controller. If you would like to render the books/postings partial there, you need to add the list of books (#books) in that controller too.
More info here: http://guides.rubyonrails.org/action_controller_overview.html

Rails add text to class in a content_tag_for :li

I have a content tag that is creating jquery sortable output.
Some items I don't want sortable, so I've added the following to the jquery:
cancel: ".ui-state-disabled"
So, now I need to put "ui-state-disabled" into the li class.
Currently the code creating the li is this:
<% wostatus.workorders.each do |workorder| %>
<%= content_tag_for(:li, workorder) do %>
<div class="<%= workorder.type.maximo_no %> <%= workorder.priority %> ">
<a href="<%= workorder_path(workorder) %>">
<strong><%= workorder.wonum %></strong>
<%= workorder.description %>
</a>
</div>
<% end %>
<% end %>
The results in HTML are:
<li class="workorder" id="workorder_36">
<div class=" ">
<a href="/workorders/36">
<strong>13-39870</strong>
Added some text again
</a>
</div>
</li>
In the browser, if I edit the li class to include "ui-state-disabled" it works the way I want.
Now, how can I insert the "ui-state-disabled" into the li status if the workorder.wostatus.id = 232 ??
Thanks for your help!!
Make a helper:
def disabled_workorder_li(workorder)
{:class => "ui-state-disabled"} if workorder.id == 232
end
Then in the view:
<%= content_tag_for(:li, workorder, disabled_workorder_li(workorder) %>
Here's what it would look like if you skipped the helper and tried to do it all in the view:
<%= content_tag_for(:li, workorder,
(workorder.id == 232) ? {:class => "ui_state_disabled"} : nil %>
That looks terrible. Putting it into a helper will also make it easier to test.

Resources