How to stop count from duplicating partials in #show? - ruby-on-rails

For some reason I am getting duplicates of show.html.erb. The duplicates happen to coincide with what the .count is, even if I remove .count from the show file.
users/show.html.erb
<% if #user.habits.any? %>
<h2>Habit Challenges (<%= #user.habits.count %>)</h2>
<%= render #habits %>
<% end %>
<% if #user.valuations.any? %>
<h2>Values (<%= #user.valuations.count %>)</h2>
<%= render #valuations %>
<% end %>
<% if #user.goals.any? %>
<h2>Current Goals (<%= #user.goals.unaccomplished.count %>)</h2>
<%= render #unaccomplished_goals %>
<% end %>
<% if #user.goals.any? %>
<h2>Accomplished Goals (<%= #user.goals.accomplished.count %>)</h2>
<%= render #accomplished_goals %>
<% end %>
<% if #user.quantifieds.any? %>
<h2>Stats: Monthly Average (<%= #user.quantifieds.count %>)</h2>
<%= render #averaged_quantifieds %>
<% end %>
<% if #user.quantifieds.any? %>
<h2>Stats: Instances (<%= #user.quantifieds.count %>)</h2>
<%= render #instance_quantifieds %>
<% end %>
users_controller.rb
def show
#user = User.find(params[:id])
#habits = #user.habits.all
#valuations = #user.valuations.all
#accomplished_goals = #user.goals.accomplished.all
#unaccomplished_goals = #user.goals.unaccomplished.all
#averaged_quantifieds = #user.quantifieds.averaged.all
#instance_quantifieds = #user.quantifieds.instance.all
end
As you can see by the picture if I create 3 habits, 3 tables of habits will show. If I create 4, 5, so on the same thing happens. The same goes for the rest, like with values (#valuations) 12 repetitions are being created.
habits/_habit.html.erb
<!-- Default bootstrap panel contents -->
<div id="valuations" class="panel panel-default">
<div class="panel-heading"><h4><b>HABITS</b></h4></div>
<!-- Table -->
<table>
<thead>
<tr>
<th>Level</th>
<th>Left</th>
<th>Strike</th>
<th>Trigger</th>
<th>Action</th>
<th>Target</th>
<th>Reward</th>
<th>Days</th>
</tr>
</thead>
<tbody>
<% #habits.each do |challenged| %>
<tr>
<td><%= challenged.current_level %></td>
<td>
<%= link_to edit_habit_path(challenged) do %>
<%= [params[:missed]].flatten.length %>
<% end %></td>
<td><%= challenged.trigger %></td>
<td class="category">
<b><%= raw challenged.tag_list.map { |t| link_to t.titleize, tag_path(t) }.join(', ') %></b>
</td>
<td><%= challenged.target %></td>
<td class= "committed">
<%= challenged.committed.map { |d| d.titleize[0,3] }.join ', ' %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
Do you have any ideas? I'm baffled.

You can try this:
<h2>Habit Challenges (<%= #habits.count %>)</h2>
<%= render #habits %>
<h2>Values (<%= #valuations.count %>)</h2>
<%= render #valuations %>
<h2>Current Goals (<%= #unaccomplished_goals.count %>)</h2>
<%= render #unaccomplished_goals %>
<h2>Accomplished Goals (<%= #accomplished_goals.count %>)</h2>
<%= render #accomplished_goals %>
<h2>Stats: Monthly Average (<%= #averaged_quantifieds.count %>)</h2>
<%= render #averaged_quantifieds %>
<h2>Stats: Instances (<%= #instance_quantifieds.count %>)</h2>
<%= render #instance_quantifieds %>
Change your show action:
def show
#user = User.find(params[:id])
#habits = #user.habits
#valuations = #user.valuations
#accomplished_goals = #user.goals.accomplished
#unaccomplished_goals = #user.goals.unaccomplished
#averaged_quantifieds = #user.quantifieds.averaged
#instance_quantifieds = #user.quantifieds.instance
end
Change your partial, stop iterating over #habits again:
<tbody>
<tr>
<td><%= habit.current_level %></td>
<td><%= link_to edit_habit_path(habit) do %>
<%= [params[:missed]].flatten.length %><% end %>
</td>
<td><%= habit.trigger %></td>
<td class="category"><b><%= raw habit.tag_list.map { |t| link_to t.titleize, tag_path(t) }.join(', ') %></b></td>
<td><%= habit.target %></td>
<td class= "committed"><%= habit.committed.map { |d| d.titleize[0,3] }.join ', ' %></td>
</tr>
</tbody>
Update:
Another way around, which will only repeat tbody (as per your request).
<h2>Habit Challenges (<%= #habits.count %>)</h2>
<%= render partial: 'habit', locals: {habits: #habits} %>
Then change your habit partial:
<% habits.each do |habit| %>
<tbody>
<tr>
...
...
</tr>
</tbody>
<% end %>

That's the normal behavour if you render a collection of objects. A partial for each object in the collection is rendered.
Look at section 3.4.5 of the guides.rubyonrails.org on layouts and rendering...
http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials
The habit partial should probably be edited to show only what you want to show per element in the collection. If it is currently showing only the information for the first element, then you may not be passing the object correctly to the partial. See section 3.4.6 in the above document.

Are they part of the same controller? If so, call the partial without the variable...
<% if #user.habits.any? %>
<h2>Habit Challenges (<%= #user.habits.count %>)</h2>
<%= render 'habits' %>
<% end %>
If not, call the partial with a local variable:
<% if #user.habits.any? %>
<h2>Habit Challenges (<%= #user.habits.count %>)</h2>
<%= render 'habits', :locals => {:habits => #habits} %>
<% end %>
If that's the case, you have to change the partial to stop using # based variable for #habits.

Related

How to place two elements in a row while using .each loop in rails

I want to show two columns of the code in table data tag"" per row while using '.each' method. But the issue is that the following code displays one column in a row.
<table>
<% #lease.apartment.roommates.each do |roommate| %>
<tr>
<td colspan="5">
<% unless roommate == #lease.second_occupant || roommate == #lease.user %>
<% if roommate.current_room.present? %>
<p>
<%= roommate.full_name %> -
<% if roommate.current_room.apartment == #lease.apartment%>
<%= roommate.current_room&.label %>
<% end %>
<br>Email:<%= roommate.email %><br>Phone:<%= roommate.phone %><br>
<% if #lease.end_at.present? %>
Lease End date (if applicable):<%= #lease.end_at %>
<% end %>
</p>
<% end %>
<% end %>
</td>
</tr>
<% end %>
</table>
You can use the each_slice method for dividing the array into slices of 2 elements each:
<table>
<% #roommates.each_slice(2) do |roommate_slice| %>
<tr>
<td colspan="5">
<%= roommate_slice[0].full_name %>
<%= roommate_slice[1].full_name %>
</td>
</tr>
<% end %>
</table>

Ruby on Rails - Get first n number of elements from array with condition

In my Rails view template, the #comments is an array of hashes. I just need to show the first three comments that meet this condition <% if post["id"] === comment["postId"] %>. Right now it's showing all of them.
<tbody>
<% #posts.each do |post| %>
<tr>
<% #users.each do |user| %>
<% if post["userId"] === user["id"] %>
<td> <%= user["name"] %></td>
<% end %>
<% end %>
<td><%= post["title"] %></td>
<td><%= post["body"] %></td>
<% comments_total = 0 %>
<% #comments.each do |comment| %>
<% if post["id"] === comment["postId"] %>
<td><%= comment["body"] %></td>
<% comments_total += 1 %>
<% end %>
<% end %>
<td><%= comments_total %></td>
<% end %>
</tr>
</tbody>
When you only want to show the first 3 comments that match a certain condition then I would do this:
<% matching_comments = #comments.select { |comment| comment["postId"] == post["id"] } %>
<% matching_comments.first(3).each do |comment| %>
<td><%= comment["body"] %></td>
<% end %>
<td><%= matching_comments.size %></td>
You might load the #comments with the condition in the controller to make the view easier to read.

rails ransack remote true with pagination

I've a controller for WeekDay. Then I tried to add RanSack in my project. It works good except when I tried to enable remote true, it shows only search form. AJAX call is being made, but nothing shows up.
Controller code
def index
#q = WeekDay.ransack(params[:q])
#week_days = #q.result().page(params[:page]).per(10)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #week_days }
end
end
index.html.erb
<div id="week_days"><%= render 'week_days' %></div>
_week_days.html.erb
<%= search_form_for #q,remote: true do |f| %>
<%= f.label :datum_gteq %>
<%= f.date_field :datum_gteq%>
<%= f.label :datum_lteq %>
<%= f.date_field :datum_lteq %>
<%= f.submit %>
<% end %>
<table>
<thead>
<tr>
<th><%=sort_link #q, :datum %></th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #week_days.each do |week_day| %>
<tr>
<td><%= l week_day.datum %></td>
<td><%= link_to 'Show', week_day %></td>
<td><%= link_to 'Edit', edit_week_day_path(week_day) %></td>
</tr>
<% end %>
</tbody>
</table>
<%= paginate #week_days %>
<br>
<%= link_to 'New Week Day', new_week_day_path %>
some idea from me is you split the _week_days into partial and then render part of data using ajax, I added new div with name display-area as target for ajax to render and you should create javascripts to render it without reload the page with escape javascripts (j)
_week_days.html.erb
<%= render "search" %>
<%= render "my_data" %>
_search.html.erb
<%= search_form_for #q,remote: true do |f| %>
<%= f.label :datum_gteq %>
<%= f.date_field :datum_gteq%>
<%= f.label :datum_lteq %>
<%= f.date_field :datum_lteq %>
<%= f.submit %>
<% end %>
_my_data.html.erb
<div class="display-area">
<table>
<thead>
<tr>
<th><%=sort_link #q, :datum %></th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #week_days.each do |week_day| %>
<tr>
<td><%= l week_day.datum %></td>
<td><%= link_to 'Show', week_day %></td>
<td><%= link_to 'Edit', edit_week_day_path(week_day) %></td>
</tr>
<% end %>
</tbody>
</table>
<%= paginate #week_days %>
<br>
<%= link_to 'New Week Day', new_week_day_path %>
</div>
write _weekdays.js.erb inside app/assets/javascripts
$('.display-area').html("<%= j render(partial: 'my_data') %>")

Form_tag routing error after unsuccessful submit

I have an index page with a partial form to submit new records to Package model. I keep this form in the index page, so the user doesn't need to leave the page when repeating this action, several times.
In the same page I have a form_tag fir multiple updates for the same controller, namely packages_controller.
Everything works fine, except the following: when hit the update button, going to the form BUT instead of submitting I go back (with the browser) and try to select other records to be updated then I have a routing error:
Routing Error
No route matches [PUT] "/projects/47/orderlines/18/packages"
My index page looks like this:
<% if current_user %>
<%= render "packages/form" %>
<% end %>
<% if #packages.count >= 1 %>
<table class="table table-striped">
<thead>
<tr>
<th> <input type="checkbox" id="selectAll" value="selectAll"></th>
<th>Packed </th>
<th>#No.</th>
<th>Type</th>
<th>Gross weight</th>
<th>Length</th>
<th>Width</th>
<th>Height</th>
<th></th>
<th>Container</th>
</tr>
</thead>
<%= form_tag edit_multiple_project_orderline_packages_path, method: :get do %>
<tbody>
<% for package in #packages %>
<% if package.packed== true %>
<% #label_type="success" %>
<% else %>
<% #label_type="default" %>
<% end %>
<tr>
<td><%= check_box_tag "package_ids[]", package.id %></td>
<td><span class="label label-<%= #label_type %>"><% if package.packed==true %>Packed<% else %>Unpacked<% end %></span></td>
<td><%= package.package_no %></td>
<td><%= package.package_type %></td>
<td><%= package.gross_weight %></td>
<td><%= package.length %></td>
<td><%= package.width %></td>
<td><%= package.height %></td>
<% if #orderline.packages.count >= 1 %>
<td><%= link_to 'Delete', [package.orderline.project, package.orderline, package],
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
<td><%= #containers.find(package.container_id).container_id if package.packed %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<%= submit_tag "Add to container", class: "btn btn-primary" %>
<% end %>
<br />
<%= will_paginate %>
<br>
And the multiple_edit form
<div class="col-sm-4">
<%= form_tag update_multiple_project_orderline_packages_path, method: :put do %>
<ul>
<% #packages.each do |package| %>
<li>
<%= hidden_field_tag "package_ids[]", package.id %>
<%= package.package_no %>
<%= package.container_id %>
<% package.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</li>
<% end %>
</ul>
<%= fields_for :package do |f| %>
<div class="field">
<%= f.label :package_no %><br />
<%= f.text_field :package_no, :class => "form-control" %>
</div>
<br />
<div class="field">
<%= f.label :container_id %><br />
<%= select_tag 'package[container_id]', options_from_collection_for_select(#project.containers, 'id', 'container_id', default_blank: true), prompt: "- Select container -", :class => "form-control" %>
</div>
<br />
<div class="field">
<%= f.label :packed %><br />
<%= f.select :packed, [["Packed", true], ["Unpacked", false]],{ prompt: "- Packing -"},{ :class => "form-control" } %>
</div>
<% end %>
<div class="actions">
<br />
<%= submit_tag "Update", :class => "btn btn-primary" %>
</div>
<% end %>
</div>
And the packages controller edit_multiple actions:
def edit_multiple
#project = Project.find(params[:project_id])
#packages = Package.find(params[:package_ids])
end
def update_multiple
#packages = Package.find(params[:package_ids])
#packages.reject! do |package|
package.update_attributes(package_params.reject { |k,v| v.blank? })
end
if #packages.empty?
redirect_to project_orderline_packages_url
else
#package = Package.new(package_params)
render "edit_multiple"
end
end
packages_controller create action:
def create
project = Project.find(params[:project_id])
orderline = project.orderlines.find(params[:orderline_id])
#package = orderline.packages.new(package_params)
#package.save
if #package.save
flash[:success] = "Package(s) was successfully added."
redirect_to :back
else
render 'new'
end
And my routes:
resources :projects do
resources :containers
resources :orderlines do
resources :packages do
collection do
put :packed
get :edit_multiple
put :update_multiple
end
end
end
end
I just added my routes here:
edit_multiple_project_orderline_packages_path GET /projects/:project_id/orderlines/:orderline_id/packages/edit_multiple(.:format)
packages#edit_multiple
update_multiple_project_orderline_packages_path PUT /projects/:project_id/orderlines/:orderline_id/packages/update_multiple(.:format)
packages#update_multiple
project_orderline_packages_path GET /projects/:project_id/orderlines/:orderline_id/packages(.:format)
packages#index
POST /projects/:project_id/orderlines/:orderline_id/packages(.:format)
packages#create
new_project_orderline_package_path GET /projects/:project_id/orderlines/:orderline_id/packages/new(.:format)
packages#new
edit_project_orderline_package_path GET /projects/:project_id/orderlines/:orderline_id/packages/:id/edit(.:format)
packages#edit
project_orderline_package_path GET /projects/:project_id/orderlines/:orderline_id/packages/:id(.:format)
packages#show
PATCH /projects/:project_id/orderlines/:orderline_id/packages/:id(.:format)
packages#update
PUT /projects/:project_id/orderlines/:orderline_id/packages/:id(.:format)
packages#update
DELETE /projects/:project_id/orderlines/:orderline_id/packages/:id(.:format)
your form_tag code is update_multiple_project_orderline_packages_path
I think it should be update_multiple_project_orderline_package_path(project_id, orderline_id, package_id)
I am not 100% sure with my statement above, because you gave scrambled Rails Routes, hard to read
and your form action seems goes to packages#edit_multiple controller
so paste your edit_multiple method, not create method
are you implementing your scenario above with javascript, or just plain HTML?

Rails syntax error : unexpected keyword_ensure, expecting end-of-input

I am a newbie in rails and i tried creating a forum application based on a tutorial. This is my forum page but i keep getting the error:
syntax error, unexpected keyword_ensure, expecting end-of-input
Extracted source (around line #33):
30
31 <p><% if admin? %><%= link_to "New Forum", new_forum_path %><% end %></p>
here is the forum index page which is throwing the error:
<% title "Forums" %>
<table>
<tr>
<th width="70%">Forum</th>
<th width="30%">Last Post</th>
</tr>
<% for forum in #forums %>
<tr>
<td><h4><%= link_to h(forum.name), forum_path(forum.id) %></h4>
<small><%= forum.topics.count %> topics</small><br />
<%=h forum.description %></td>
<td class="right">
<% if forum.most_recent_post %>
<%= distance_of_time_in_words_to_now forum.most_recent_post.last_post_at %>
ago by
<%= link_to forum.most_recent_post.user.username, "/users/#{forum.most_recent_post.last_poster_id}" %>
<% else %>no posts<% end %>
</td>
<% if admin? %>
<td><%= link_to "Edit", edit_forum_path(forum) %>
<% end %></td>
<!-- <% end %> -->
<% if admin? %>
<td><%= link_to "Destroy", forum, :confirm => 'Are you sure?', :method => :delete %></td>
<% end %>
</tr>
<% end %>
<p><% if admin? %><%= link_to "New Forum", new_forum_path %><% end %></p>
<!-- <% end %> --> what is this doing? a html commented ERB tag will still evaluate. Remove it. if you want to comment ruby code use # instead, like <% #end %>
Properly formatted code goes a long way towards diagnosing problems like this (mismatch and the like). Try out the following:
<% title "Forums" %>
<table>
<tr>
<th width="70%">Forum</th>
<th width="30%">Last Post</th>
</tr>
<% for forum in #forums %>
<tr>
<td>
<h4><%= link_to h(forum.name), forum_path(forum.id) %></h4>
<small><%= forum.topics.count %> topics</small>
<br />
<%=h forum.description %>
</td>
<td class="right">
<% if forum.most_recent_post %>
<%= distance_of_time_in_words_to_now forum.most_recent_post.last_post_at %>
ago by
<%= link_to forum.most_recent_post.user.username, "/users/#{forum.most_recent_post.last_poster_id}" %>
<% else %>
no posts
<% end %>
</td>
<% if admin? %>
<td><%= link_to "Edit", edit_forum_path(forum) %></td>
<td><%= link_to "Destroy", forum, :confirm => 'Are you sure?', :method => :delete %></td>
<% end %>
</tr>
<% end %>
</table>
<% if admin? %>
<p><%= link_to "New Forum", new_forum_path %></p>
<% end %>
all I could see wrong is that you set end before it should here
<% if admin? %>
<td><%= link_to "Edit", edit_forum_path(forum) %>
<% end %></td>
so try to move it like this
<% if admin? %>
<td><%= link_to "Edit", edit_forum_path(forum) %>
</td><% end %>
I think you have the order of opening and closing blocks jumbled up.
if, for are all opening blocks that have to be closed at the appropriate times.
The commented-out end tag that Benjamin mentioned is actually important but misplaced and has to go between your </tr> and </table> tags to close the for forum in #forums.
I prepared a modified version with some realignments, so I could make sense of it more easily. Haven't actually tested it, though.
<% title "Forums" %>
<table>
<tr>
<th width="70%">Forum</th>
<th width="30%">Last Post</th>
</tr>
<% for forum in #forums %>
<tr>
<td>
<h4><%= link_to h(forum.name), forum_path(forum.id) %></h4>
<small><%= forum.topics.count %> topics</small><br />
<%=h forum.description %></td>
<td class="right">
<% if forum.most_recent_post %>
<%= distance_of_time_in_words_to_now forum.most_recent_post.last_post_at %>
ago by
<%= link_to forum.most_recent_post.user.username, "/users/#{forum.most_recent_post.last_poster_id}" %>
<% else %>
no posts
<% end %>
</td>
<% if admin? %>
<td>
<%= link_to "Edit", edit_forum_path(forum) %>
</td>
<% end %>
<% if admin? %>
<td><%= link_to "Destroy", forum, :confirm => 'Are you sure?', :method => :delete %></td>
<% end %>
</tr>
<% end %>
</table>
<p>
<% if admin? %>
<%= link_to "New Forum", new_forum_path %>
<% end %>
</p>

Resources