Rails if object can't be found move on in view - ruby-on-rails

I have the following statement in an erb template:
<% if #serial.hacks.find(#serial.id) %>
<h1><%= #serial.hacks.find(#serial.id).hack_name %><h1>
<% end %>
I'm trying to display the hack_name if it exists, however, prevent an error if it doesn't exist. The Serial and Hack models share a has many through relationship.
When I load a page that doesn't have an association between Serial and Hack I get the following error which I'm trying to prevent:
Couldn't find Hack with id=2 [WHERE "hacktions"."serial_id" = 2]

<% if hack = #serial.hacks.find_by_id(#serial.id) %>
<h1><%= hack.hack_name %><h1>
<% end %>
But you should use presenters.
BTW, it's really weird to have a serial having hacks with it's id. What do you really want?
Edit I guess you're looking for:
<% #serial.hacks.each do |hack| %>
<h1><%= hack.hack_name %><h1>
<% end %>

Related

Rails - how to write an index view?

I'm having trouble figuring out how to display an index.
In my organisation requests view folder, I have a file called index.html.erb.
In that file, I'm trying to list each organisation request. I've tried each of the following formulations:
<% OrganisationRequest.each do |OrgReq| %>
<% organisation_request.each do |OrgReq| %>
<% #organisation_request.each do |OrgReq| %>
<% #organisation_requests.each do |OrgReq| %>
In each case, I get an error that says:
formal argument cannot be a constant
I thought a constant meant something beginning with a capital letter. 3 of the above attempts don't begin with a capital letter.
It's also confusing to me since in my user index, I have <% User.each %> and I don't get an error message.
Can anyone see what's gone wrong? How do I ask for a list of objects?
If you have your data and view right, you should be able to fix with:
<% #organisation_requests.each do |org_req| %>
...
<% end %>
If we stick Rails conventions, we'd say that, you have a OrganisationRequests controller, has such content.
class OrganisationRequestsController < ApplicationController
...
def index
#your_local_variable = OrganisationRequest.find(...)
end
...
end
That is to say, you need to use, #your_local_variable inside view file.
<% #your_local_variable.each do |o| %>
....
<% end %>
If the variable inside index action is #organisation_requests, use that.

In loop, find if two records belong to same post

I have a loop of questions where each question belongs to a post and the post title is displayed above the question. If 2 ( or 3 or 4 etc) questions in a row belong to the same post I only want to display the post name once. My idea was to use an index to check if the prior questions post == the current questions post. The problem is I'm not sure how that would work.
Here is what I tried:
<% #questions.each_with_index do |question, i| %>
<% unless (i-1).comment.post == question.comment.post %>
<%= question.comment.post.title %>
<% end %>
<% end %>
This gives me an undefined method comment error since I can't call '(i-1).comment' but can I do something like that or is there a better way to do this?
One way to do this would be to use group_by to group the questions by post:
<% #questions.group_by {|q| q.comment.post}.each do |post, questions| %>
<%= post.title %>
<% for question in questions %>
<%= question.title %>
<% end %>
<% end %>
If you need to maintain the order of the questions, you could use each_cons.
<%= #questions.first.comment.post.title %>
<% #questions.each_cons(2) do |previous_question, question| %>
<% unless previous_question.comment.post == question.comment.post %>
<%= question.comment.post.title %>
<% end %>
<% end %>
Couple of minor notes:
This is a troubling Law of Demeter violation (having to traverse from the question to the comment to the post and eventually the title).
This sort of complicated data manipulation is much better in a Ruby object than in a template. Ideally, templates are dead simple.

Combining two associations in my "each do" loop method

I'm a little new to back-end programming...I'm currently running the following code in my rails 4 app to show a basic list of all the admins on a project (if there are any)...
<% if project.projectadmins.any? %>
<div class="row-fluid">
<% project.projectadmins.each do |user| %>
<div class="collaborator">
<%= link_to user do %>
<%= image_tag user.image_url(:thumb).to_s, :class => "profile-pic-thumb" %>
<% end %>
</div>
<% end %>
</div>
<% end %>
However, I also have projectcollaborators for each project, so I'd like to know what the most effective way would be to combine those and provide a list of both projectadmins AND projectcollaborators (with project admins being listed first if there are any...other than that ordering is not important).
I assume the if statement at the beginning would change to...
<% if project.projectadmins.any? || project.projectcollaborators.any? %>
but I'm not 100% sure and am lost on the rest...any help is much appreciated.
You could create a scope, for example project_admins_and_collaborators, which gets all the needed records and then use it in your loop.
You can also do this in following way
project_admins_and_collaborators = project.projectadmins
project_admins_and_collaborators << project.projectcollaborators
project_admins_and_collaborators.flatten.uniq do |user|
#your code
end

Stuck trying to list associated model

I think I am deeply misunderstanding how to write instances.
Miniatures have_many Manufacturers through the Productions table.
On the miniatures show page I am trying to list all the manufacturers for the current miniature and have them link the Manufacturer show page. Like so:
<% #miniature.manufacturers.each do |manufacturer| %>
<%= link_to #miniature.manufacturer.name, manufacturer_path %>
<% end %>
Needless to say it does not work. It gives "undefined method `manufacturer'".
I have tried A LOT of different combinations to no avail. The following version puts all the manufacturers, rolled into one link, once for each manufacturer a miniature has, and links to /manufacturers. A big mess.
<% #miniature.manufacturers.each do |manufacturer| %>
<%= link_to #miniature.manufacturers.map(&:name).join(', '), manufacturer_path %>
<% end %>
I have been working on other things and hoping I would get the hang of this but I'm pretty sure it's something pretty fundamental about how I set up the instance.
If it's more likely something I need to add to the controller then I can add my controller code here. Any help much appreciated.
Does this work:
<% #miniature.manufacturers.each do |manufacturer| %>
<%= link_to manufacturer.name, manufacturer_path(manufacturer) %>
<% end %>

What is the best way using multiple lines of <% %> Tag or <% %> Tag with multiple lines?

Sorry if the title is not enough to understand what i am asking about.
I am rails developer and i used multiple lines of <% %> in my views but now i realized that it's not best practice so i came here and like to you all excellent guys what is the correct way in ROR?
For example if i required to something like following
<% user =User.all %>
<% name= [] %>
<% count = 0 %>
<% for user in users %>
<% name << user.name %>
<% count+=1%>
<% end %>
Can i do it as follows ?
<% user =User.all
name= []
count = 0
for user in users
name << user.name
count+=1
end
%>
I know better way of collecting element from array But above is just example.
But my question is, is it possible and if yes which is the correct way?
I think the correct way is something totally different: move logic out of views.
This blog post explains what I mean.
in start and end must has '<%' or '%>'
Like:
<% users = User.all
name= []
count = 0
for user in users
count+=1
end %>
Using just a single pair of tags per code block is certainly preferable if only because it makes the output smaller.
The code should really rather look like
<% names = User.all.map(&:name) %>
Note that "count" can be obtained via names.size.
If you need to mix <% and <%= you need to switch:
<% for user in User.all %>
<%= user.name %></br>
<% end %>

Resources