How to display a template for empty tables? - ruby-on-rails

I have the following model
class User < ActiveRecord::Base
has_many :collabos
has_many :files
end
I want to display a conditional partial so the current_user can create a collabo or a file, when these models are empty?
Here's my first attempt, but it doesn't work well.
<% if current_user.files.empty? || current_user.collabos.empty? %>
<%= "create a file/collabo" %>
<% else %>
<%= yield %>
<% end %>
What's the best way to go for this kind of issue?
I think the picture below is better to show you the kind of behaviour I want to implement

You need and instead of or :
<% if current_user.files.empty? and current_user.collabos.empty? %>
However, it is always a nice idea to create User instance methods like :
def has_files?
files.empty? ? false : true
end
so that it becomes :
<% if current_user.has_files? and current_user.has_collabos? %>
(and you can always create a has_files_and_collabos method as well, if it's reusable code)

Related

Rails: show post when attributes is set to true

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

List database entry with ID in view

I found it difficult to title this question. It is easier if you see the situation:
by having this in my view
<% #scrapbook.scrapbook_entries.each do |d|%>
<%= d.recipe_id %>
<% end %>
I am given a list of recipe id's (3 of them) that are in the scrapbook_entries database table.
358 358 341
What I want to do is use these ID's and search the recipe table for all the information linked to them.
E.g. Display #recipe.name with ID 358.
Is there an easy way to do this in the view? Let me know if I am not making sense
If I understand you well, you can immediately put something like
= d.recipe.name
Behind the scenes, this will use your recipe id to look up the correct record, then take the name atttribute of this record
Try this:
<% #scrapbook.scrapbook_entries.each do |d|%>
<%= d.recipe_id %>
<%= d.recipe ? d.recipe.name : '' %>
<% end %>
If you have the relationship defined on the ScrapbookEntry model you can get the recipe instance and access any of its attributes.
class ScrapbookEntry < ActiveRecord::Base
belongs_to :recipe
end
<% #scrapbook.scrapbook_entries.each do |d|%>
<%= d.recipe.name %>
<% end %>
you can add a delegate in your scrabook_entry
delegate :name, :to => :recipe
than in your view
d.name

Rails finding a value in a table

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

Which of these approaches is the most "best Rails practice"?

I have a very concrete dilemma right now.
Given the following models:
class Message < ActiveRecord::Base
attr_accessible :body, :sent_at
belongs_to :subject
end
class Subject < ActiveRecord::Base
attr_accessible :title
has_many :messages
belongs_to :last_message, :class_name => 'Message', :foreign_key => 'last_message_id'
end
In a view I want to iterate over a list of subjects and display:
- Subject title
- sent_at for the subject's last message
like this:
<% #subjects.each do |subject| %>
<%= subject.title %>
<%= subject.last_message.sent_at %>
<% end %>
The thing is: subject.last_message may some times be nil. In which case, the above code will throw an exception.
So: What is the best solution to this? I can see 3 possibilities, but honestly don't know which are considered good or bad.
1) Let the view rescue it
<%= subject.last_message.sent_at rescue '' %>
2) Make a helper
def last_message_sent_at(subject)
return '' if subject.last_message.blank?
subject.last_message.sent_at
end
<%= last_message_sent_at(subject) %>
3) Make a sort of "proxy" on the Subject model
class Subject < ...
...
def last_message_sent_at
return '' if last_message.blank?
last_message.sent_at
end
end
<%= subject.last_message_sent_at %>
Which would you choose, and why? Or is there perhaps another way, which I haven't thought about?
/ Carsten
Use try :
<%= subject.last_message.try(:sent_at) %>
So, if subject.last_message is nil, you will get no output; else if it is not nil, it will call the method sent_at on subject.last_message.
It is like a convenient form for your #2 idea
Documentation
As additional thought, helper is a bad choice. You ideally always want a "receiver" (in some_class.perform(), some_class is the "receiver" i.e. it "receives" the message "perform"). I avoid Helpers unless I need to generate HTML. So, your #3 does have a receiver, but since Rails provides try, you do not need to roll your own.
The easiest thing, in this case, may be to simply check for the null value...
<% #subjects.each do |subject| %>
<%= subject.title %>
<%= subject.last_message.sent_at if subject.last_message %>
<% end %>
or
<% #subjects.each do |subject| %>
<%= subject.title %>
<%= subject.last_message && subject.last_message.sent_at %>
<% end %>
If you had any logic or action to perform, best practice would be to move it out of your views (into helpers, presenters).
Since your question is about "how to call a method on possibly nil instance?", then try is probably the best way to go in this case. Because, it's already there and you don't need any extra gems.
On the other note, you can improve your code by just putting render #subjects and moving your block content into the _subject parcial. Rails will do the looping for you.

Rails: Cutting Down Code

I know that I might have too much logic in my view, so I'm wondering how I can include it in my controller:
Controller:
def purchasers
#deal = Deal.find(params[:id])
#pl = #deal.purchases
end
View:
<% title "List Of Purchases" %>
Total Purchases: <%= #pl.count %><BR><BR>
<%
#pl.each do |p|
u = User.find(p.user_id)
%>
<%= u.email %><BR>
<%
end
%>
I'd suggest that you remove the call to User.find inside the view code.
It looks like you're looking up the user from the user_id stored in the purchase. Why not in the model use:
class Purchase < ActiveRecord::Base
belongs_to :user
...
end
And then in the view code:
<% #pl.each do |purchase| %>
<%= purchase.user.email %><BR>
<% end %>
Hope this helps.
It looks like you might not have set up your associations correctly in your Purchases and Users models. Instead of doing u = User.find(p.user_id) you should be able to write p.user.email, assuming that each Purchase belongs_to :user.
if your Purchase model belongs to User model, you don't need to find User with User.find.
if not, belong your Purchase model to User model then
<% #pl.each do |p| %>
<%= p.user.email %>
<% end %>
Its also worth noting the following can be improved to make use of Rails' skills when it comoes to caching collections:
<%= #pl.count %>
to
<%= #pl.size %>
The size method will return the number of purchases but won't load the objects into memory again as they have already been looked up in the controller.

Resources