I am facing a weird bug and unfortunately I don't know how to investigate about it.
I am rendering certain pins on my homepage when the integer => pinoftheday is set to true. I am manually setting some pins to true.
For some pins its working well and they are appearing on the homepage, some others just don't. Btw, I am checking in my console and they are correctly set to true.
Here is a bit of code:
<% #pins.each do |pin| %>
<% if pin.pinoftheday %>
(...) some informations about the pin
<% end %>
<% end %>
Any ideas how I could check why some pins are not rendering? I am not writting any tests for now... I know this is stupid but I just did not learnt testing for rails.
Thank you.
EDIT: Yes, in my code it's a pin model. I wanted to used post to make it clearer. Figured it was not :) - Edited it to the correct model: pin.
Try the below code.
<% #postss.each do |post| %>
<% if post.pinoftheday %>
(...) some informations about the pin
<% end %>
<% end %>
Your problem is that you've defined a local variable in your block, and are referencing another:
<% #postss.each do |post| %>
<% if post.pinoftheday %>
...
<% end %>
<% end %>
--
You'd be better using a scope:
#app/models/post.rb
class Post < ActiveRecord::Base
scope :pin_of_the_day, -> { where pinoftheday: true }
end
You'll also do well to make your pinoftheday column boolean. If you're referencing 1 = true; 0 = false, Rails handles that with a tinyint in your db, calling true/false as boolean logic. Instead of referencing the integer as a number, you can call true etc.
The above will allow you to call:
#app/controllers/your_controller.rb
class YourController < ApplicationController
def index
#postss = Post.pin_of_the_day
end
end
This will remove the inefficient conditional logic (<% if ...):
<% #postss.each do |post| %>
...
<% end %>
If I understood your code then will below:
<% #postss.each do |pin| %>
<% if pin.pinoftheday.nil? %>
(...) some informations about the pin
<% else %>
(...) some informations about the pin
<% end %>
<% end %>
Hope will help you
Related
I have a loop that looks like this
<% #user.collections.each do |collection| %>
<h1 class="impact"> <%= collection.name %><br></h1>
<%= collection.stories.count %>
<% end %>
It works perfectly to show the Collections that belongs to a User, and then show how many Stories are in each Collection.
However, I want to use a helper that does this.
in the view
<% #user.collections.each do |collection| %>
<h1 class="impact"> <%= collection.name %><br></h1>
<%= number_of_stories_in_collection %>
<% end %>
in the helper
module CollectionsHelper
def number_of_stories_in_collection
collection.stories.count
end
def render_stories_count
if number_of_stories_in_collection.zero?
'No stories in this collection yet'
else
"#{number_of_stories_in_collection} #{'story'.pluralize(number_of_stories_in_collection)}"
end
end
end
I get an error that says
undefined method `stories' for #<Collection::ActiveRecord_Relation:0x007f510f504af8>
Any help is appreciated, thanks!
The 'collection' variable isn't an instance variable, so the helper can't see it.
Change your view to this:
<% #user.collections.each do |collection| %>
<h1 class="impact"> <%= collection.name %><br></h1>
<%= number_of_stories_in(collection) %>
<% end %>
And your helper method to:
def number_of_stories_in(collection)
collection.stories.count
end
This way you are passing the variable to the helper correctly.
extending #Richard's answer and little bit of optimisation to avoid n+1 queries..
<% #user.collections.includes(:stories).each do |collection| %>
<h1 class="impact"> <%= collection.name %><br></h1>
<%= render_stories_count(collection) %>
<% end %>
helper:
module CollectionsHelper
def number_of_stories_in(collection)
collection.stories.length
end
def render_stories_count(collection)
if (count = number_of_stories_in(collection)).zero?
'No stories in this collection yet'
else
"#{count} #{'story'.pluralize(count)}"
end
end
end
I'm new to rails and I'm trying to build a view that will list the parents and related children
Ex:
Passport has many Visas
I want to list information about the passport and the visas that the passport has.
So I have
<% #passport_list.each do |passport| %>
# passportFields
<% passport.visas.each do |visa| %>
<%= t.text_field :visa_type %>
<% end %>
<% end %>
I'm getting the error
undefined method `visa_type' for #Passport:0x000000091b8b28
It looks like rails is trying to find the property visa_type for passport, instead of in visa. How does the scope work within each? Can I force it to access visa_type from visa?
I think you're looking for the fields_for form helper. This will allow you to create fields for the relevant visa attributes. Replace your code sample with the following, and you should be all set.
<% #passport_list.each do |passport| %>
# passportFields
<% t.fields_for :visas do |visa_fields| %>
<%= visa_fields.text_field :visa_type %>
<% end %>
<% end %>
You can also iterate over the list as follows:
<% #passport_list.each do |passport| %>
# passportFields
<% passport.visas.each do |visa| %>
<% t.fields_for :visas do |visa_fields| %>
<%= visa_fields.text_field :visa_type %>
<% end %>
<% end %>
<% end %>
For more information on fields_for, check out the link I added above, and to customize further for your use case, check out the "One-to-many" section.
IMO you should always handle the null case of an object.
Something like this if you use rails (present? is a Rails function)...
<% if #passport_list.present? %>
<% #passport_list.each do |passport| %>
passportFields
<% passport.visas.each do |visa| %>
<%= t.text_field :visa_type %>
<%end%>
<%end%>
<% else %>
<p>Nothing to see here</p>
<% end %>
However if your #passport_list is backed by an ActiveRecord Query, you can handle this in the model/helper/controller by returning the .none query on the model. Note that this differs from an empty array because it is an ActiveRecord Scope, so you can chain AR queries onto it
# scope on AR model
def self.awesomeville
where(country_of_origin: "awesomeville")
end
# method queried in controller
#passport_list = Passport.all
if #passport_list.present?
#passport_list
else
Passport.none
end
# additional filtering in view is now possible without fear of NoMethodError
#passport_list.awesomeville
Whereas a ruby Array would raise an error as it would respond to the Array methods.
Is it possible to call the include? function on a whole table, like this?
<% #user.games.each do |g|
##latestround = g.rounds.order('created_at DESC').first
%>
<% if ##latestround.submittedpictures.isFinalPicture.include?(true) %>
<p>FinalPicture has been played!</p>
<% end %>
<% end %>
The problem i'm getting is that It only works when I put a block on submittedpictures and then loop through each record of this table. However I want to look through the whole table in one go and see if the column 'isFinalPicture' includes a value with 'false'.
Any ideas?
The following snippet works but its not the way i want it (I would get more lines if the round happens to have more 'true' FinalPictures)
<% ##latestround.submittedpictures.each do |s| %>
<% if s.isFinalPicture == true %>
<p>Final Picture has been played!</p>
<% end %>
<% end %>
You could make a scope for it like
class SubmitedPricture << ActiveRecord::Base
scope :final_pictures, where('isFinalPricture = ?', true)
end
then you could see if there is any with only one query
latestround.submittedpictures.final_pictures.any?
Also you should follow the conventions of Rails in naming your Models and everything else. Like submittedpictures should be submitted_pictures
If I have the following nested model relationships (all has_many):
Countries < Cities < Streets < Homes
In a show view, how can I check if a particular Country has any homes?
Edit:
Adding the suggested method of chaining with the map method (first try to map to streets). So far it's not restricting the records
<% #countries.each do |country| %>
<% if country.cities.map(&:streets).any? %>
....
<% end %>
<% end %>
You can call or #country.cities.map(&:streets).flatten.map(&:homes).present? or #country.cities.map(&:streets).map(&:homes).any?
<% if #country.cities.map(&:streets).flatten.map(&:homes).flatten.any? %>
Tro-lol-lo yo-lo-puki
<% end %>
Also you can wrap this long line into your model method:
class Country < ActiveRecord::Base
def any_homes?
cities.map(&:streets).flatten.map(&:homes).flatten.any?
end
end
Usage
<% if #country.any_homes? %>
Tro-lol-lo yo-lo-puki
<% end %>
And of course it looks like a good data structure for refactoring! It wants to be refactored!
If I have...
class Bunny < ActiveRecord::Base
has_many :carrots
end
...how can I check in the View if #bunny has any carrots? I want to do something like this:
<% if #bunny.carrots? %>
<strong>Yay! Carrots!</strong>
<% for carrot in #bunny.carrots %>
You got a <%=h carrot.color %> carrot!<br />
<% end %>
<% end %>
I know #bunny.carrots? doesn't work -- what would?
<% if #bunny.carrots.any? %>
<strong>Yay! Carrots!</strong>
<% for carrot in #bunny.carrots %>
You got a <%=h carrot.color %> carrot!<br />
<% end %>
<% end %>
unless #bunny.carrots.empty?
would work as well
either:
if #bunny.carrots.length>0
or
unless #bunny.carrots.nil? || #bunny.carrots.length>0
or
if #bunny.carrots.any?
by the way, you will find more operations on collections if you use irb or script/console with require 'irb/completion'
#bunny.carrots is an array, so you can treat it as such by calling array methods on it, e.g. unless #bunny.carrots.empty?