Rails: Cutting Down Code - ruby-on-rails

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.

Related

ActiveRecord_Associations_CollectionProxy:0x0000000e490b98 in RoR

I'm creating a application using ruby on rails, but currently i'm suffering a problem like db relation, below my code:
Company
has_many :posts, :foreign_key => :company_id
Post
belongs_to :companies, :foreign_key => :company_id
controller
#post = current_user.companies.all
view
<% #post.each do |p| %>
<%= p.posts.post_title %>
<% end %>
Showing error above code.
If I debug like use <%= debug p.posts %> then showing all posts, which is under my companies but when I use <%= debug p.posts.post_title %> then showing ActiveRecord_Associations_CollectionProxy:0x0000000e490b98
Thanks
I think the problem here is that you are trying to call the method :post_title on p.posts, which is an ActiveRecord::Associations::CollectionProxy object.
In your example, p is a Company object, which has a method posts, which returns to you a CollectionProxy object that acts a lot like a list of posts. That list will not have a method post_title, but each element of that list will have a method post_title
So, instead of
<% #post.each do |p| %>
<%= p.posts.post_title %>
<% end %>
You will want something like:
<% #post.each do |company| %>
<% company.posts.each do |post| %>
<%= post.post_title %>
<% end %>
<% end %>
Two additional things to note:
1) The variable #post is inaccurately named. Inaccurate variable names will lead to confusion when trying to understand what is happening. current_user.companies.all returns a list of companies, and therefore, it should read:
#companies = current_user.companies.all
not
#post = current_user.companies.all
2) The actual error that is being shown to you likely says something like
Undefined Method 'post_title' for ActiveRecord_Associations_CollectionProxy:0x0000000e490b98
Not just
ActiveRecord_Associations_CollectionProxy:0x0000000e490b98
When debugging and asking for help, it's very important to note the entire message of the exception being raised.
Because companiy has_many :posts........ posts are objects you need a loop to show all posts e.g
p.posts.each do |post|

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: App displays table/model name instead of data from table

I'm very new to rails and putting together my first app. Please bear with me!
I'm making an app that lets the user rate the video games they are playing. On the site I've made a page where the user can see a list of all the games that he/she has rated in the past.
I'm running into some issues and I think it's pretty simple but it's driving me crazy.
In the controller I have:
def index
#rate = Rate.where(:rater_id => current_user.id)
#ratename = Game.where(:id => #rate.first.rateable_id)
end
And in my view I have:
<% #rates.order("created_at desc").each do |rates| %>
You are playing <%= #ratename.name %></div>
<% end %>
Where I'm confused is that in the browser this is displayed: "You are playing Game"
How do I get it to display the name of the game not just "Game"?
UPATE:
Model for rate:
class Rate < ActiveRecord::Base
attr_accessible :rateable_id, :rater_id
belongs_to :user
belongs_to :game
end
#ratename = Game.where(:id => #rate.first.rateable_id)
means that you find Game with all attributes, not only name.
The right way:
in controller:
#rates = current_user.rates.order("created_at desc") #will work if you made correct associations (user has many rates)
in view:
<% #rates each do |rate| %>
You are playing <%= rate.game.name %></div>
<% end %>
rate.game.name will work if you made correct associations: game has many rates, rate belongs to game.
Try referring to the associations directly.
Controller:
def index
#rates = current_user.rates.order("created_at desc")
end
View:
<% #rates.each do |rate| %>
You are playing <%= rate.game.name %>
<% end %>
my suggestion just do this
in index
def index
#rates = current_user.rates.includes(:game).order("created_at desc")
end
in view
<% #rates.each do |rate| %>
You are playing <%= rate.game.name %></div>
<% end %>
this will solve your problem plus it will improve your server efficiency

How to display a template for empty tables?

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)

How can I display a list of three different Models sortable by the same :attribute in rails?

I have a Campaign model which has_many Calls, Emails, and Letters.
For now, these are each a separate Model with different controllers and actions (although I would like to start to think of ways to collapse them once the models and actions stabilize).
They do share two attributes at least: :days and :title
I would like a way to represent all the Calls, Emails, and Letters that belong_to a specific Campaign as a sortable collection (sortable by :days), in a way that outputs the model name and the path_to() for each.
For example (I know the below is not correct, but it represents the kind of output/format I've been trying to do:
#campaign_events.each do |campaign_event|
<%= campaign_event.model_name %>
<%= link_to campaign_event.title, #{model_name}_path(campaign_event) %>
end
Thanks so much. BTW, if this matters, I would then want to make the :days attribute editable_in_place.
Here is what I've got working, but want some additional insights
module CampaignsHelper
def campaign_events
return (#campaign.calls + #campaign.emails + #campaign.letters).sort{|a,b| a.days <=> b.days}
end
end
In the VIEW:
<% #campaign_events = campaign_events %>
<% #campaign_events.each do |campaign_event| %>
<% model_name = campaign_event.class.name.tableize.singularize %>
<p>
<%= link_to campaign_event.title, send("#{model_name}_path", campaign_event) %>
<%= campaign_event.days %>
</p>
<% end %>
Like this?
# controller
#campaign = Campaign.find(params[:id])
#campaign_events = (#campaign.calls + #campaign.emails + #campaign.letters).sort{|a,b| a.days <=> b.days}
# view
#campaign_events.each do |campaign_event|
<%= campaign_event.model_name %>
<%= link_to campaign_event.title, #{model_name}_path(campaign_event) %>
end
In controller you find all campaign events and sort it by days field

Resources