How to correctly call models in controller - ruby-on-rails

My Chefs Model is linked to my Meals Model through chef_id. I am displaying information about the chef, and would also like to show information about his meals. I have not been able to figure out the correct way to call it in the controller. Any ideas?
chef controller:
def index
#chefs=Chef.paginate(page: params[:page])
#meals = ????? Cant figure out how to call this
end
Index.html.erb
<div class = 'chef'>
<div class = 'row'>
<% #chefs.each do |chef| %>
<%= render chef %>
<% end %>
</div>
</div>
<%= will_paginate %>
_chef partial
<div class = 'span4'>
<div class = 'chef-box'>
<h2><center><%= link_to chef.name, chef %></center></h2>
<h2><center>"<%= chef.description %>"</center></h2>
<h2><center><%= THIS IS WHERE I WANT TO DISPLAY INFORMATION ON MEALS %></center></h2>
</div>
</div>

If you just want to access the #meals, than you can get it just by for an instance of #chef:
#meals = #chef.meals
given that you have defined the association in the Chef class like following:
class Chef < ActiveRecord::Base
has_many :meals
#rest of the code
end
Have a look at Active Record Associations here.
So, Here I am just giving an example of how to use it in views, you may have to correct it:
in _chef partial
<div class = 'span4'>
<div class = 'chef-box'>
<h2><center><%= link_to chef.name, chef %></center></h2>
<h2><center>"<%= chef.description %>"</center></h2>
<% chef.meals.each do |meal| %>
<h2><center><%= meal.information %></center></h2>
<% end %>
</div>
</div>
You will need to call correct attribute of meal in above sample code.

As previously mentioned – first and foremost make sure the relation is set up in your chef model:
class Chef < ActiveRecord::Base
has_many :meals
end
Then you can call any Chef.meals, whether that's in your controller as:
def index
#chef = Chef.paginate(page: params[:page])
#meals = #chef.meals
end
Or just in your view:
<div class = 'span4'>
<div class = 'chef-box'>
<h2><center><%= link_to chef.name, chef %></center></h2>
<h2><center>"<%= chef.description %>"</center></h2>
<h2>Has <%= pluralize(chef.meals.size, 'meal') %></h2>
<% chef.meals.each do |meal| %>
<% meal.name %>
<% end %>
</div>
</div>
Of note – since Chef is a model name, you should be able to render your _chef.html.erb more cleanly with simply:
<div class = 'chef'>
<div class = 'row'>
<%= render #chef %>
</div>
</div>
<%= will_paginate %>
Note that #chef is singular to match your controller, you could also pass it a collection <%= render #chefs %> if that's what's set up in your controller, and it will do render each chef separately.

Related

How to pass more than one parameters to render in rails?

Below is my review.html.erb:
<% provide(:title, 'All reviews') %>
<h1>All reviews</h1>
<ol class="reviews">
<%= render #reviews %>
</ol>
<%= will_paginate #reviews %>
And my _review.html.erb looks like:
<li>
<p>Student: <%= Student.find(review.student_id).name%></p>
<p>Score: <%= review.score%></p>
<p>Review: <%= review.review%></p>
<p>Created at: <%= review.created_at%></p>
</li>
How can I pass #students as well to render for example?
I tried <%= render #reviews, #students %> in review.html.erb and Student: <%= student.name%> in _review.html.erb. It didn't work.
You don't actually need to pass multiple parameters. You just need to setup the assocations between reviews and students:
class Student < ApplicationRecord
has_many :reviews
end
class Review < ApplicationRecord
belongs_to :student
# optional but avoids a law of demeter violation
delegate :name, to: :student, prefix: true
end
<li>
<p>Student: <%= review.student_name %></p>
<p>Score: <%= review.score %></p>
<p>Review: <%= review.review %></p>
<p>Created at: <%= review.created_at %></p>
</li>
To avoid a N+1 query issue you should use includes or eager_load to load the student with the reviews:
#reviews = Review.includes(:student)
.all
If you do actually want to pass additional arguments when rendering a collection (which isn't needed here) you do it with local assigns:
<%= render #reviews, locals: { foo: 'bar' } %>
This will be available in the partial as foo or local_assigns(:foo).
Reivew table and students are related
In _review.html.erb , you don't need use Student.find(review.student_id)
<li>
<p>Student: <%= review.student&.name%></p> // changed
....
</li>

How to use same partial with variables from different controllers?

In my application, users submit reviews under brands. Here's the association:
class Brand < ActiveRecord::Base
has_many :reviews
class Review < ActiveRecord::Base
belongs_to :brand
Right now I have a partial defined to show reviews as such:
_showreview.html.erb
<% review.each do |review| %>
<div class="col-sm-4">
<div class="thumbnail">
<%= image_tag review.first_photo %>
<div class="caption">
<h4><%= link_to review.title, review %></h4>
<h6><strong><%= link_to ("WRITTEN BY " + review.user.username.upcase), review.user %></strong></h6>
<%= review.description.truncate_words(60, omission: '...') %>
<br>
<br>
<%= link_to review.brand.label, review.brand, :class => 'btn btn-sm btn-lake' %>
</div>
</div>
</div>
And I render it like this by passing an instance variable in:
<%= render "showreview", review: #top_reviews %>
It works as expected.
Now I wish to reuse the partial for brands/show.html.erb
What I want to do now is retrieve all the reviews that belong to a brand and display it.
show_controller.rb looks like this
def show
#brand = Brand.find(params[:id])
#reviews =Review.find(params[:id])
end
I tried to use this but it doesn't work. What is the correct way to do this?
<%= render "/reviews/showreview", review: '#brand.reviews' %>
<%= render "/reviews/showreview", review: #brand.reviews %>
But please, rename review to reviews. It's more convenient name of this variable.
Your method will be like this
def show
#brand = Brand.find(params[:id])
end
and in your view
<%= render "reviews/showreview", review: #brand.reviews %>
firstly, you should use a plurality for the variable review instead.
reviews.each do |review|
it makes your code readability.
then try placing review: '#branch.review' by reviews: #branch.reviews
and make sure that you did pass the variable #branch from your controller

Can't Get Photos to Work in Rails

I am having all kinds of trouble doing a simple task, displaying a photo as part of a result set for each one. I'm pretty new to Rails in general, coming from another language where I can do this in seconds.
The #photo query finds 0 records even though multiple records for photos are in the DB matching the property ID.
I'm not too sure what I'm doing wrong here.
Here are my relevant files:
app/controllers/properties_controller.rb:
class PropertiesController < ApplicationController
......
def all
# gets all of the properties and uses will_paginate
#properties = Property.paginate(page: params[:page])
# should get the first positioned photo matching the results in the #properties query
#photos = Photo.where(:property_id => #properties.map(&:id)).order("position").first
end
# ......
end
app/models/property.rb:
class Property < ActiveRecord::Base
belongs_to :listing_type
belongs_to :property_type
belongs_to :status
has_many :photos
# ......
end
app/models/photo.rb:
class Photo < ActiveRecord::Base
mount_uploader :photoname, PhotoUploader
belongs_to :property
acts_as_list scope: :property_id
validates :photoname, presence: true
validates :property_id, presence: true
end
details.html.erb:
<% #properties.reverse_each do |property| %>
<div class="item col-md-4">
<div class="image">
<%= link_to property_path(property) do %>
<span class="btn btn-default"><i class="fa fa-file-o"></i> Details</span>
<% end %>
<%= image_tag(property) %>
</div>
# ......
<% end %>
Since you have a has_many realtion in the Property, you have to just access to the relation of the property to read all teh photoes:
photo = #property.photos.order("position").first
Well if you need to grab all the photoes of properties, use include to properties grab:
#properties = Property.includes(:photos).paginate(page: params[:page]).reverse
the include is needed to avoid N + 1 problem, then try replacing it with a first photo:
#photos = #properties.map { |pr| pr.photos.order("position").first }
Mpve reverse to controller, and to use #photos along with #properties use index:
<% #properties.each.with_index do |property, i| %>
#...
<%= image_tag(#photos[i]) %>
<- end >
NOTE that the code selecting an image pr.photos... be better moved to a decorator (see gem draper).
After a TON of help from #МалъСкрылевъ, which also had me learning a few new ways of "thinking" this in general, his answer led me to rethink what I was doing and go back to simply starting over and reconstructing what ended up being VERY basic. All I needed to do was make the photo query for the first photo in my loop over the properties. DUH! Here's what I did in case it helps some other poor new Rails developer!
properties_controller.rb
class PropertiesController < ApplicationController
......
def all
# gets all of the properties and uses will_paginate
#properties = Property.paginate(page: params[:page])
......
end
details.html.erb
<% #properties.each do |property| %>
<div class="item col-md-4">
<% #photo = Photo.where(property_id: property.id).order("position").first %>
<div class="image">
<%= link_to property_path(property) do %>
<span class="btn btn-default"><i class="fa fa-file-o"></i> Details</span>
<% end %>
<%= image_tag(#photo.photoname.medium) %>
</div>
......

Unable to autoload constant Featured_image, expected C:/Sites/pickyourchoice/app/models/featured_image.rb to define it

i have a model Featured_images in my rails application and in my view page i need to show all the data stored with this model table .
In my controller i have a method named index
def index
#featured_images = Featured_image.all
end
in my view
<% #featured_images.each do |h| %>
<div class="item">
<%=image_tag h.pg_images.url(:medium), :class=>'img-responsive' %>
</div>
<% end %>
You need to use
#featured_images = FeaturedImage.all
instead of
#featured_images = Featured_image.all
and your model should be like
class FeaturedImage < ActiveRecord::Base
end

how to render this partial in rails

i am trying to render this partial of the association belongs_to and has_many i.e
my model is as thus
activity Model
class Activity < ActiveRecord::Base
has_many :talks
end
talk model
class Talk < ActiveRecord::Base
belongs :activity
end
in my talk controller i have
#activities = Activity.where(user_id: [current_user.friend_ids, current_user])
#talks = Talk.find(:all, :order => "created_at DESC")
and in view i have
<% activity.talks.each do |c| %>
<div class="media">
<a class="pull-left" href="#">
<%= image_tag(c.user.image.url(:tiny),:style=> "width: 100%;")%>
</a>
<div class="media-body">
<strong><%= c.user.username %></strong> <%= c.details %><br>
<small><span class="muted"><%="#{time_ago_in_words(c.created_at)} ago "%></span></small>
</div>
</div>
<% end %>
this displays all the talk for each activity
how do i create a partial of <% activity.talks.each do |c| %>
Create a partial in
app/views/talks/_talk.html.erb
and call
<%= render activity.talks %>
This will render one _talk.html.erb partial for each talk in the activity.talks collection, which will have access to a talk variable.
Furthermore, you can optimize the code by preventing N + 1 queries. In your controller,
#activities = Activity.includes(:talks).where(user_id: [current_user.friend_ids, current_user])
Notice the includes(:talks). Read more about eager loading in the docs linked above.

Resources