Two Similar Partials, One Giving Error, Other Is Fine - ruby-on-rails

I have two partials, that are almost exactly the same, except one is a full view, and the other is a compact. They are both under 'projects' view, but one works correctly, and the other gives errors:
projects/_project.html.erb
<div class="pure-u-1-3">
<%= link_to project do %>
<div class="project">
<h4 class="red marginless"><%= truncate( project.title, length: 22, separator: ' ') %></h4>
<p class="left marginless"><strong>By:</strong> <%= project.user.username %><br>
<strong>Genres:</strong> <%= truncate( project.genre2, length: 25, separator: ' ') %><br><br>
<strong>Description:</strong><br>
<%= truncate( project.description, length: 60, separator: ' ') %><br>
<strong>Needs:</strong><br>
<%= truncate( project.looking_for, length: 60, separator: ' ') %></p>
</div>
<% end %>
<% if #projects.size == 0 %>
<em> no projects found with that criteria </em>
<% end %>
</div>
projects/_short.html.erb
<div class="pure-u-1-3">
<%= link_to project do %>
<div class="project">
<h4 class="red marginless"><%= truncate( project.title, length: 22, separator: ' ') %></h4>
<p class="left marginless"><strong>By:</strong> <%= project.user.username %></p>
</div>
<% end %>
</div>
Now, this is the part of the view using these partials:
dashboards/index.html.erb
<% if #projects.length > 0 %>
<div class="pure-u-1" id="projects"><h3 class="red"><%= current_user.username %>'s Owned Projects</h3>
<%= render :partial => 'projects/short', :collection => #projects %>
</div>
<% end %>
When I have 'projects/project' it works perfectly, no issues.
When I put 'projects/short' it gives me this error:
undefined local variable or method `project'
This error is given everywhere the word project is used on _short, unless I use #project, but then it gives me this error:
undefined method `title' for nil:NilClass (same for user)
I do not understand how the partials can be in the exact same spot, and used the exact same way, in the exact same spot, but one works and the other does not. Is there code I may have done in the past, that I am missing that makes this work?

You need to supply the as: :project option to the render partial call as:
<% if #projects.length > 0 %>
<div class="pure-u-1" id="projects"><h3 class="red"><%= current_user.username %>'s Owned Projects</h3>
<%= render :partial => 'projects/short', :collection => #projects, as: :project %>
</div>
<% end %>
This will make project local variable available within the partial projects/short.
The reason you are getting the error is because (from the documentation on rendering collections within Using render):
When a partial is called with a pluralized collection, then the
individual instances of the partial have access to the member of the
collection being rendered via a variable named after the partial.

Okay, so before I actually saw the above answer, I was still sorting through documentation, and from my best understanding, I actually just changed everything that said project to compact now like:
<h4 class="red marginless"><%= truncate( compact.title, length: 22, separator: ' ') %></h4>
<p class="left marginless"><strong>By:</strong> <%= compact.user.username %></p>
Is this the 'wrong' way to do it? It seems to be working perfectly now...

Related

Strange output from rails each do

Rails each do method is acting strangely and I do not know why.
controller
def index
#fabric_guides = FabricGuide.with_attached_image.all.order(:name)
end
index.html.erb
<div class="guide-items">
<%= #fabric_guides.each do |fabric| %>
<div class="guide-container">
<%= link_to fabric_guide_path(slug: fabric.slug) do %>
<%= image_tag fabric.image if fabric.image.attached? %>
<% end %>
<div class="guide-info">
<p class="g-name">
<%= link_to fabric.name,
fabric_guide_path(slug: fabric.slug) %>
</p>
</div>
</div>
<% end %>
</div>
I have two FabricGuide records so I expect two "guide-container" but I get three. Or more precisely I get two guide containers and a third block of text containing all the content from the last FabricGuide record.
I have almost an identical setup for articles and have never encountered this problem. I'd happily share more information if needed. Thank you!
Please remove = equal sign from your each loop of view code
like below :-
<% #fabric_guides.each do |fabric| %>
...
...
<% end %>
you have used this <%= #fabric_guides.each do |fabric| %> in your view that's why it shows all record in DOM.
The expression for erb tags is <% %>
now if we want to print that tag too then we apply <%= %>

Shows "#" instead of text

I am executing this code:
def find_all_from_id
Note.find_by_sql([%{SELECT NOTE_N FROM NOTES WHERE ORDSP_ID = #{#order.order_number}}])
end
And in ERB file, I have an output:
<div class="form-field notes-div" >
<%= service_form.label :notes, "Pakalpojuma papildinformācija:", :class => "label_for_cod", :style=>"width: 170px;" %>
<div style="float:left; width:400px;"><%#= notes %> <%= find_all_from_id %></div>
</div>
It puts the # symbol instead of text the that comes from the database (http://prntscr.com/kop3mz). Why? And how can I fix that?
Take a look at the documentation for find_by_sql: https://api.rubyonrails.org/classes/ActiveRecord/Querying.html
This method will return an array of instances. If you want to display information about those instances you need to iterate through the array and manually display the information you want to show. Erb will not display the array of instances, leading to your issue.
E.g.
<% find_all_from_id.each do |note| %>
<%= note.name %>
<%= note.id %>
<% end %>

I want to display a random object

I want to display a random object in cards.
<div class="row">
<% #slots.sample(3).each do |slot| %>
<div class="col-md-4 col-sm-6">
<div class="card-image">
<%= link_to slot_path(slot) do %>
<% if slot.photo? %>
<%= cl_image_tag slot.photo, class: "img-rounded img-responsive", height: 262, width: 195 %>
<% else %>
<%= image_tag "image_placeholder.jpg", class: "fileinput-new thumbnail img-no-padding", height: 250, width: 400 %>
<% end %>
<% end %>
<div class="details">
<div class="author">
<%= link_to slot_user(slot) do %>
<%= cl_image_tag slot.user.photo, class: "img-circle img-no-padding img-responsive" %>
<span class="name"><%= slot.name %></span>
<span class="meta"><%= slot.user.first_name %> <%= slot.user.last_name %></span>
<% end %>
</div>
</div>
</div>
</div>
<% end %>
</div>
My code returns error messages like:
"undefined method `sample' for nil:NilClass",
"undefined method `photo' for nil:NilClass",
"undefined method `user' for nil:NilClass"
I don't understand. Can you help me?
You can randomize your #slots collection in the conntroller, eg:
#slots = Slot.where(id: Slot.pluck(:id).sample(3))
Then use directly in the view
<% #slots.each do |slot| %>
Getting a random object in Ruby on Rails (ActiveRecord) is not well documented but it is fairly easy.
There is the obvious: take two random objects from any array:
#users = User.all
#users.sample(2)
This will get all objects from the db, put them in an array (#users) from which two random objects are picked. If you happen to need all objects in an array this is fine. If not, you better go for something better:
User.order('RANDOM()').limit(2)
This will only read two entries from the db, using a random order. It is therefore much easier on the db than the first command.
The command syntax works for PostgreSQL - use 'RAND()' for MySQL.
There is one thing to watch out for and that is a default_scope. If you have set a default_scope for the obj class use reorder instead:
User.reorder('RANDOM()').limit(2)

Can one use conditions and loops on a single line in Ruby?

How would one go about turning the following code into the latter?
<div id="faqs">
<% if #faqs.length > 0 %>
<% #faqs.each do |faq| %>
<div class="faq">
<strong>Q:</strong> <%= faq.question %>
<br />
<strong>A:</strong> <%= faq.answer %>
</div>
<% end %>
<% else %>
<p>No FAQs to display.</p>
<% end %>
</div>
<div id="faqs">
<% #faqs.empty? ? content_tag(:p, "No FAQs to display.") : #faqs.each do |faq| %>
<div class="faq">
<strong>Q:</strong> <%= faq.question %>
<br />
<strong>A:</strong> <%= faq.answer %>
</div>
<% end %>
</div>
I'm curious as to whether I can get the latter code to work. The only element of it that is failing at the moment is that the content_tag() is not displaying - this is due to the fact that I'm not using printable ruby tags (<%= # %>) but using them will dump out the FAQ objects underneath the content.
I considered the use of puts() to print the content_tag() while inside the ruby tags but that didn't work.
I've tried to search for this issue but haven't yielded anything useful.
Is this achievable and if so, does it have any benefits other than being prettier?
One way to make the later code to work if you can put the body of the loop in a helper function and return the out put of content_tag from that. The line in view file might be somewhat like this.
<%= #faqs.empty? ? content_tag(:p, "No FAQs to display.") : printList(#faqs) %>
and your printList function will return the output of nested content_tags. You can make a generic list printing function which can be used for any list.
Something so obvious but still shared.
This should work (for clarity, I moved FAQ tag generation in separate helper method):
<div id="faqs">
<%= raw (#faqs.empty? ? content_tag(:p, "No FAQs to display.") : #faqs.map { |faq| faq_div(faq) }.join) %>
</div>
or, perhaps more clean:
<div id="faqs">
<%= content_tag(:p, "No FAQs to display.") if #faqs.empty? %>
<%= raw #faqs.map { |faq| faq_div(faq) }.join %>
</div>
meanwhile, in helpers:
def faq_div(faq)
'<div class="faq"><strong>Q:</strong> %s<br /><strong>A:</strong> %s</div>' % [faq.question, faq.answer]
end
This should work:
<% if #faqs.each do |faq| %>
<div class="faq">
<strong>Q:</strong> <%= faq.question %>
<br />
<strong>A:</strong> <%= faq.answer %>
</div>
<% end.empty? %>
<p>No FAQs to display.</p>
<% end %>

Help applying two different styles to Ruby on Rails pluralize method

How do I apply two different styles to the "vote" text and the number output from this RoR code:
<%= pluralize video.vote_sum, 'Vote' %>
Since you want to style the pluralized word, I would just suggest doing the following:
<%= video.vote_sum %>
<div class="style-word">
<% word = "Vote" %>
<% if video.vote_sum > 1 %>
<%= word.pluralize %>
<% else %>
<%= word %>
<% end %>
</div>
(Sorry about all the <% %>, I'm so used to HAML now, I don't do erb anymore).
Try this :
<div class="<%= pluralize video.vote_sum, 'number' %>">
<%= video.vote_sum %>
</div>
<div class="<%= pluralize video.vote_sum, 'vote' %>">
<%= pluralize video.vote_sum, 'Vote' %>
</div>
And in your CSS:
.vote{# some style code here!}
.votes{# some style code here!}
.number{# some style code here!}
.numbers{# some style code here!}
<%= pluralize video.vote_sum, '<span class="some_other_class">Vote</span>', '<span class="some_other_class">Votes</span>' %>
I just ran into this exact situation and chose to extend the pluralize method in application_helper.rb
def pluralize(count, singular, plural = nil)
count, counted = super.split(' ', 2)
[content_tag(:span, count, class: 'count'),content_tag(:span, counted, class: 'counted')].join(' ').html_safe
end
pluralize(2, "Thing") will now output something like <span class="count">1</span> <span class="counted">Things</span>

Resources