Rails association works in the console but not in the view - ruby-on-rails

to-many association between 2 modles. It works perfectly in the console but in the view just I get object-references appears like this:
#<Author:0x0000000434bf80>
#<Author:0x000000043485b0>
This appears in my view which has this code:
<h1 class="page-title">Articles</h1>
<hr>
<div class="category-container">
<ul class="category-titles">
<% #cat.each do |c| %>
<li><%= link_to c.catName, category_path(c) %></li>
<% end %>
</ul>
</div>
<br><br><br><hr>
<% #art.each do |t| %>
<p class="articles-list-page"><%= link_to t.artTitle, article_path(t) %></p>
<p><%= t.author %></p>
<% end %>
Here is my association in Author Model
class Author < ActiveRecord::Base
has_many :articles
end
and Here is my association in Article Model
class Article < ActiveRecord::Base
belongs_to :category
belongs_to :author
end
I could not understand why it is working well in the console but not in the view

It works fine in the view.
This line:
<p><%= t.author %></p>
outputs the author model. What you probably want to do is output the author name - something like
<p><%= t.author.name %></p>

You're attempting to output an ActiveRecord relation to the view. There's probably no situation ever where you'd want to display an entire ActiveRecord object in a view. Instead, you'd want to display particular attributes of the object.
Such as:
t.author.created_at
t.author.name
t.author.whatever
However, if there was some strange reason you wanted to output the entire object to the view, you could use inspect like so:
t.author.inspect
UPDATE:
To answer the other issue you're running into, you'll need to make sure that you actually have a related Author for each of the Articles before trying to output an Author attribute to the view. You can accomplish that like so:
<% if t.author.present? %>
<p><%= t.author.authName %></p>
<% else %>
<p>No author available</p>
<% end %>
Or like so, if you want to use a terniary operator to keep things on one line:
<p><%= t.author.present? ? t.author.authName : 'No author available' %></p>
Or if you don't care about returning a default value such as "No author available" if an author isn't available, then you could just do something like this:
<p><%= t.author.try(:authName) %></p>

You should delegate that author attributes to Article model
class Article < ActiveRecord::Base
belongs_to :category
belongs_to :author
delegates :authName, allow_nil: true
end
Also in your controller use following code
class ArticleController < ApplicationController
def index
#art = Article.includes(:author).all
end
end
And in your view use like bellow
<% #art.each do |t| %>
<p class="articles-list-page"><%= link_to t.artTitle, article_path(t) %></p>
<p><%= t.authName %></p>
<% end %>

Related

How do I implement associations in searchkick

First, the example I read in the docs shows to declare the associated model as singular, :address, but if I do I get the error Association named 'address' was not found on User; If I change it to plural :addresses, then the next problem I have is the association doesn't work in views undefined method `country' for ...
Why am I declaring the association as plural and how can I make the association available in the view
User.rb:
class User < ActiveRecord::Base
searchkick word_middle: ['full_name', 'description', 'interests']
has_many :addresses
scope :search_import, -> { includes(:addresses) }
search.html.erb:
<% #users.each do |u| %>
<li>
<%= link_to "#{u.first_name} #{u.middle_name} #{u.last_name}", page_path(name: u.name) %>
<% #ua=u.addresses.where("current=?", true) %>
<% if #ua.country=="US" %>
<%= #ua.city %>, <%= #ua.state %> <%= ISO3166::Country.find_country_by_alpha2(#ua.country) %>
<% else %>
<%= #ua.city %>, <%= ISO3166::Country.find_country_by_alpha2(#ua.country) %>
<% end %>
</li>
<% end %>
</ul>
In controller, do this: #user = User.includes(:addresses).where(your_query) to make the association readily available in view.
And yes has_many associations are bound to be plural: "User has_one
:life" and "User has_many :passions"; does it make sense?
And finally your error: where returns an array because you queried: "bring me all records which fulfill this condition". find, on the other hand, will bring back 1 specific record as it expects a unique attribute or brings back first record that matches that attribute.
What you need to do:
You should either do this (if you are dead-sure that you will get 1
such record or you need only one of that type):
<% #ua=u.addresses.where("current=?", true).first %>
OR
If you need to go through all the resultant array then:
<% #ua=u.addresses.where("current=?", true) %>
<% #ua.each do |ua| %>
# Your code for each ua instead of #ua.
<% end %>
Happy Learning :)

Displaying has_many, :through association records

I am working on an application a deep association. A Story belongs to a Planning Level, the Planning Level belongs to one or many Programs.
class Program < ActiveRecord::Base
has_and_belongs_to_many :planning_levels
has_many :stories, :through => :planning_levels
end
class PlanningLevelsPrograms < ActiveRecord::Base
end
class PlanningLevel < ActiveRecord::Base
has_and_belongs_to_many :programs
has_many :stories
end
class Story < ActiveRecord::Base
belongs_to :planning_level
end
Within the Program show page I'd like to display the Program, each Planning Level and aggregate Story count for each Planning Level.
I'm not sure how to access the Story model from the Program show page.
The following works great for displaying each Planning Level belonging to the Program.
<% #program.planning_levels.each do |p| %>
<p><%= p.name %></p>
<% end %>
...but I have no idea how to make the following work for each displayed Planning Level. How do I access the Story model from with the Program? Is there something needed in the Program controller that I'm missing. Thanks in advance!
#program.planning_level.stories.count(:id)
Each Planning Level:
<% #program.planning_levels.each do |planning_level| %>
<p><%= planning_level.name %></p>
# Aggregate Story count for each planning_level
<p><%= planning_level.stories.count %></p>
<% end %>
Aggregate Story count for #program (if you want):
#program.stories.count
Hope this can help you.
In your view, you can simply use the model associations by name to do this. Try this code as a starting point for your display needs:
<% #program.planning_levels.each do |planning_level| %>
<p><%= planning_level.name %> with <%= planning_level.stories.count %> stories</p>
<% planning_level.stories.each do |story| %>
<p><%= story.name %></p>
<% end %>
<% end %>
You can output any details that you choose for the stories loop. You can add styling to get the presentation that you need.
For instance, you might consider formatting this as a nested list, like so:
<% #program.planning_levels.each do |planning_level| %>
<ul>
<li>Planning Level: <%= planning_level.name %> with <%= planning_level.stories.count %> stories
<ul>
<% planning_level.stories.each do |story| %>
<li>Story: <%= story.name %></li>
<% end %>
</ul>
</li>
</ul>
<% end %>
Adding CSS class and id attributes would give you the ability to add styling to the elements to give your UI some flair.

Using associations in Ruby on Rails

I'm learning RoR and I'm trying to understand associations. I've got two models - Company [name] and Note [company_id, notes]. As shown, the Note model has a company_id field to reference the primary key in the Company model.
Within a Notes view, I'm trying to display the Company name but I can't seem to get this to work.
I want to display
(SELECT name FROM Company WHERE Company.id=Note.company_id)
instead of note.company_id in the code below.
company.rb
class Company < ActiveRecord::Base
has_many :notes
end
note.rb:
class Note < ActiveRecord::Base
belongs_to :company
default_scope -> { order(date: :desc) }
end
notes/index.html.erb
....
<% #notes.each do |note| %>
<% if note.active %>
<p>
<%= note.date %>
</br>
<%= note.company_id %> - <%= note.contact %>
</br>
<%= note.notes %>
<!-- <td><%= note.active %></td> -->
</p>
<% end %>
<% end %>
....
To answer your specific question, try:
note.company.name
I would also recommend reading up on Rails partials, particularly how to render a collection: http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials

Rails - getting object's fields inside view when calling model's method

Im new to ruby and rails, however I cant figure out why this doesnt work.
I am doing a simple Blog with posts and its comments, everything works fine but I tried to do my own method inside Post model to get the latest comment inside that post.
class Post < ActiveRecord::Base
attr_accessible :content, :title
has_many :comments
def latestComment(id)
post = Post.find(id)
comment = post.comments.last
end
end
and the index.html.erb
<h1>Hello World!</h1>
<h2>Posts</h2>
<% #posts.each do |post| %>
<h3><%= link_to post.title, post %></h3>
<p><%= post.content %></p>
<%= latestComment = post.latestComment(post) %>
<% end %>
<h3>Add new post</h3>
<%= link_to "Add new post", new_post_path %>
This works, it returns some hexa values, so the object exists, however then I now want to get fields from that object like this
<p><%= latestComment.author %></p>
<p><%= latestComment.content %></p>
It fails and the error is
undefined method `author' for nil:NilClass
which is weird and I dont get it why cant I access comments fields..
///comment.rb
class Comment < ActiveRecord::Base
attr_accessible :author, :content, :post_id
belongs_to :post
end
Since you are looping over multiple posts, it's possible that one of them doesn't have any comments, which makes post.comments.last return nil. You can work around this by checking it before trying to render the comment:
class Post < ActiveRecord::Base
def has_comments?
comments.count > 0
end
def last_comment
comments.last
end
end
Then, on the view:
<% #posts.each do |post| %>
<h3><%= link_to post.title, post %></h3>
<p><%= post.content %></p>
<% if post.has_comments? %>
<p><%= post.last_comment.author %></p>
<p><%= post.last_comment.content %></p>
<% end %>
<% end %>

Rails: check presence of nested attribute

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!

Resources