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

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 %>

Related

Error with instance variable in Index view

So in my tutors_controller.rb this is my index action
def index
#tutor = Tutor.all
#tutor = #tutor.fees_search(params[:fees_search]) if params[:fees_search].present?
end
and in my index.html.erb this is the view
<div class='container'>
<%= form_tag(tutors_path, method: :get) do %>
<%= label_tag 'fees_search', 'Max Fees' %>
<%= select_tag 'fees_search', options_for_select((10..50).step(10)) %>
<%= submit_tag 'Filter' %>
<% end %>
<% #tutor.each do |tutor| %>
<% unless tutor.admin? %>
<div class='row' id='tutor-listing'>
<div class='col-xs-4'>
<%= image_tag(tutor.profile.avatar.url, :class => "img-rounded" ) if tutor.profile.avatar? %>
</div>
<div class='col-xs-8'>
<h3><%= link_to tutor.full_name, tutor_path(tutor) %></h3>
<% unless tutor.subjects.nil? %>
<% tutor.subjects.each do |subs| %>
<span class='badge'id='tutor-listing-badge'>
<%= link_to subs.name, subject_path(subs) %>
</span>
<% end %>
<% end %>
<% unless current_tutor %>
<%= button_to "Shortlist Tutor", add_to_cart_path(tutor.id), :method => :post %>
<% end %>
</div>
</div>
<% end %>
<% end %>
</div>
So i understand that when the index view first renders, #tutor would simply be Tutor.all so it renders each individual tutor perfectly.
After trying to filter it though, i start receiving errors. The exact error is NoMethodError in Tutors#indexand the highlighted line is <% unless tutor.admin? %>
profile.rb model
class Profile < ActiveRecord::Base
belongs_to :tutor
scope :fees_to, -> (fees_to) { where("fees_to <= ?", "#{fees_to}") }
end
tutor.rb model
class Tutor < ActiveRecord::Base
has_one :profile, dependent: :destroy
def self.fees_search(n)
#profile = Profile.fees_to(n)
if #profile.empty?
return Tutor.none
else
#profile.each do |y|
y.tutor
end
end
end
end
I get that now my #tutor instance variable has obviously changed. But how do i go about resolving this problem? Should i be rendering a partial instead? Obviously my index action in my controller could be "better" also but i'm quite confused now as to what i should be doing.
Would appreciate any advice! Thank you!
#profile.each do |y|
y.tutor
end
Seems to be a problem. All the other outcomes are a Tutor.something scope, whereas this will return the last tutor only. Change each to map to get an array of Tutors instead.

Create a Ruby feed of two un-related tables

I'm creating an app that has two sets of content that's unrelated.
The first is Questions and Answers (Q&As) where a user can ask a question and the community can answer.
The second is an RSS like feed where an article is posted and links to a 3rd party site.
I'd like to create a 'Feed' so when the user logs in, they see the latest of the Q&As and the latest news all mixed together. I've got it working now where they aren't mixed together.
So two questions, how do i combine the two data sets? And what is the code to make it viewed given it's different content in each table.
Here is my code:
app>models>feed.rb
class Feed < ActiveRecord::Base
validates :name, :url, :description, :source, presence: true
end
app>models>question.rb
class Feed < ActiveRecord::Base
belongs_to :user
has_many :answers, dependent: :destroy, foreign_key: "id"
end
app>controllers>feeds_controller.rb
def index
#feeds = Feed.where("created_at >= ?", Date.today)
#questions = Question.where("created_at >= ?", Date.today)
end
app>views>feeds>index.html.erb
<% #feeds.each do |feed| %>
<h3><%= feed.name %></h3>
<p><%= feed.source %></p>
<p> <%= feed.created_at.strftime("%b %d, %Y") %> </p>
<%= link_to image_tag(feed.image.url(:medium)), feed.url %><br>
<%= truncate(feed.description, length: 50) %><br>
<% end %>
<% #questions.each do |question| %>
<tr>
<td><h1><%= link_to question.question , question_path(question) %></h1></td>
<td><p>Posted by: <%= question.user.name %></p></td>
<td> <p><%= question.created_at.strftime("%b %d, %Y") %> </p></td>
<td><p>Number of answers: <%= question.answers.count %> </p></td>
</tr>
<% end %>
I don't think join works given they have different data. Any suggestions on how to combine feed and questions into one stream with the most recent at the top? (like a facebook feed).
thanks for your help!
I'd suggest this... which is doing array sorting, but I think you don't have a choice with two unrelated object types.
#combined = (#feeds.to_a + #questions.to_a).sort{|a,b| b.created_at <=> a.created_at}
Then in the view...
<% #combined.each do |combined| %>
<%= render combined %>
<% end %>
The beauty of the render is that it will render a partial appropriate to the type of object. If combined s a Feed object the partial used will be feeds/_feed but if it's a Question object it will use the partial questions/_question
I was able to get this working with a few small changes. Rather than rendering the partial I did the following
<% #combined.each do |combined| %>
<% if combined.is_a?(Feed) %>
<h3><%= combined.name %></h3>
<p><%= combined.source %></p
...
<% else %>
<% end %>
Thank you for your help!

Rails association works in the console but not in the view

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 %>

Get object of relation n:m in Ruby on Rails

I have two models:
Perfiles
Modulos
And the relationship between them is: Many to Many, there is a table to map relation: modulos_perfiles
I need get all "modulos" that belongs to "perfil".. I have this:
<% #perfiles.each do |perfil| %>
<% #m = perfil.modulo.last %>
<%= #m.ruta %><br/>
<% end %>
but I get this error:
undefined method "ruta" for nil:NilClass
Where "ruta" is a column of "modulo" table.
I made this:
<% #perfiles.each do |perfil| %>
<% #m = perfil.modulo.last %>
<%= debug #m %><br/>
<% end %>
And I can see all attributes of #m object so:
ruby/object:Modulo
attributes:
id: 7
descripcion: Busquedas
ruta: /busquedas
created_at: 2012-11-25 02:23:51.984916000 Z
updated_at: 2012-11-25 02:23:51.984916000 Z
But I don't understand why I cannot get this attributes with:
<%= #m.ruta %>
Any idea?, thanks!
UPDATE
My model classes are:
class Perfil < ActiveRecord::Base
has_many :usuario
has_and_belongs_to_many :modulo
end
class Modulo < ActiveRecord::Base
has_and_belongs_to_many :perfiles
end
class ModulosPerfiles < ActiveRecord::Base
end
**
ANSWER
**
I don't have enough reputation to publish answer.
I've resolved:
I made this:
<% #perfiles.each do |perfil| %>
<% perfil.modulo.each do |modulo| %>
<%= modulo.ruta %><br/>
<% end %>
<% end %>
And so I can get any attribute of object "modulo".
Thanks.
<% #perfiles.each do |perfil| %>
<% perfil.modulo.each do |modulo| %>
<%= modulo.ruta %><br/>
<% end %>
<% end %>

Error in nested loop

I'm trying to make a report with predefined questions.
I have made questions from the scaffold and filled it.
Now is to assign answer fields per each questions.
[DATA TYPE]
class Report < ActiveRecord::Base
has_many :ansbwer_singles
end
class AnswerSingle < ActiveRecord::Base
belongs_to :report
end
reports/_form.html.erb
<div class="question">
<% QuestionSingle.all.each_with_index do |question, index| %>
<p><%= index+1 %>. <%= question.content %></p>
<p>
<%= f.fields_for :answer_singles do |answer| %>
<%= answer.text_area :content %>
<% end %>
</p>
<% end %>
it shows well but once submit it makes error
1. Question 1
[text area]
2. Question 2
[text area]
[error when submit]
AnswerSingle(#18194030) expected, got Array(#1133380)
I think the reason is using :answer_singles for fields for.
Is there any better code to implement this?

Resources