I have this code which associates one table to another. Using Set it collects all data and only shows it once if there are other similar values.
genre_names = Set.new
<% #pm_relationships = PmRelationship.where(:people_id => #person.id) %>
<% #pm_relationships.each do |pm_relationship| %>
<% #movie=Movie.find(pm_relationship.movie_id) %>
<% #mg_relationships = MgRelationship.where(:movie_id => #movie.id) %>
<% #mg_relationships.each do |mg_relationship| %>
<% #genre=Genre.find(mg_relationship.genre_id) %>
<% genre_names.add(#genre.name) %>
<% end %>
<% end%>
# actual view code
<ul class="basic-info-genres">
<%= "<li>#{genre_names.to_a.join('</li><li>')}</li>".html_safe %>
</ul>
My problem here is how a link_to would work in the print code provided
<%= "<a><li><button><span>#{genre_names.to_a.join('</span></button></li></a><a><li><button><span>')}</span></button></li></a>".html_safe %>
How to make the above print to have this link to /genres/<%=#genre.id%>?
I've tried
<%= "<a href='/genres/#{#genre.id}'><li><button><span>#{genre_names.to_a.join('</span></button></li></a><a><li><button><span>')}</span></button></li></a>".html_safe %>
but this only links to the first genre shown
Any ideas?
Thanks
Add to genres the whole #genres, not only the #genre-name, then you can use the each-loop in the view code.
For the Controller (you should have your programmic logic there):
#genres = Set.new
#pm_relationships = PmRelationship.where(:people_id => #person.id)
#pm_relationships.each do |pm_relationship|
movie=Movie.find(pm_relationship.movie_id)
#mg_relationships = MgRelationship.where(:movie_id => movie.id)
#mg_relationships.each do |mg_relationship| %>
genre=Genre.find(mg_relationship.genre_id) %>
#genres.add(genre) %>
end
end
For the view:
<ul class="basic-info-genres">
<% #genres.each do |genre| %>
<li><%= link_to genre.genre_name, "#{root_url}genres/#{genre.id}" %></li>
<% end %>
</ul>
If I understand correctly, you want to link all genres that are associated with a movie.
To do this, in your controller, load the genres for a user's movies. With the correct association setup, this is as easy as #person.genres. So let's do that.
class Person < ActiveRecord::Base
has_many :pm_relationships
has_many :movies, through: :pm_relationships
has_many :genres, through: :movies
end
class PmRelationship < ActiveRecord::Base
belongs_to :person
belongs_to :movie
end
class Movie < ActiveRecord::Base
has_many :mg_relationships
has_many :genres, through: :mg_relationships
end
With that setup, in your controller, just setup an instance variable to list all genres for #person
#genres = #person.genres
Then in your view, use the block form of link_to so it's easier to code your html
<ul class="basic-info-genres">
<% #genres.each do |genre| %>
<%= link_to genre do %>
<li>
<button>
<span><%= genre.name %></span>
</button>
</li>
<% end %>
<% end %>
</ul>
Basically, you can't have any direct child element instead of li within ul. You will need to have <a> within li, however, we can apply css to <a> so that it looks like whole 'li' have the clickable link.
From your actual code, update the snippet.
<ul class="basic-info-genres">
<% genre_names.each do |genre_name| %>
<li>
<%= link_to genre_name, genre_path(#genre), :class => 'clickable-li' %>
</li>
<% end %>
</ul>
You need to set your <a> to display: block;
# css file
.clickable-li {
display: block;
}
Related
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>
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.
So i'm making an Items class and people write reviews where the reviews contain rating and the in the item model , I had written a defined method called 'average_rating' which calculates the average rating for the items by collecting all the ratings in the reviews corresponding to this item.
now i want to sort the items by using this function yet I get that it's an undefined function.
Item Model:
class Item < ActiveRecord::Base
has_many :reviews, dependent: :destroy
belongs_to :category
def average_rating
if self.reviews.size > 0
sprintf('%.2f', self.reviews.average(:rating))
else
'undefined'
end
end
def self.search(query)
where("name like ?", "%#{query}%")
end
def self.top(query)
text= Category.where(name: query).first
where("category_id like ?", "%#{text.id}%")
end
end
Item view:
<% #items=#items.sort_by{|x,y| x.average_rating <=> y.average_rating } %>
<% #items.each do |item| %>
<div class="item">
<h4>
<%= link_to item.name, item %>
</h4>
<ul>
<li><%= item.description %></li>
<li> <%= item.average_rating %> </li>
</ul>
</div>
<% end %>
Error:
undefined method `average_rating' for nil:NilClass
You get this type of error when the object your calling your method on is nil.
I guess there is a nil in your #items list - you can get a copy of an array with all nil removed by calling #items.compact
You are getting that error because some of your item is nil. You can do something like this to remove the blank/nil values first, and then sort them:
local_items = #items.compact.sort_by{|x,y| x.average_rating <=> y.average_rating }
or,
local_items = #items.reject { |c| c.blank? }.sort_by{|x,y| x.average_rating <=> y.average_rating }
Update
Try to rename the local variable to local_items in your view and then loop through that:
local_items = #items.compact.sort_by{|x,y| x.average_rating <=> y.average_rating }
Then:
<% local_items.each do |item| %>
<div class="item">
<h4>
<%= link_to item.name, item %>
</h4>
<ul>
<li><%= item.description %></li>
<li> <%= item.average_rating %> </li>
</ul>
</div>
<% end %>
here is my models.
User
unit_id
Unit
block_id
Block
postalcode_id
Postalcode
neighbourhood_id
Neighbourhood
name
the relations is for all is top belongs to bottom
this is my current index.html.erb file, i wish to output the number of user in each neighbourhood.
<% provide(:title, 'Neighbourhoods') %>
<ul class="thumbnails">
<% #neighbourhoods.each do |neighbourhood| %>
<li class="span3">
<div class="thumbnail">
<div style="position:relative;">
<%= link_to "Join", '#', class: "btn-join" %>
<%= image_tag(neighbourhood.name+".jpg", alt: neighbourhood.name) %>
</div>
<h2 style="margin-bottom:0px"><%= neighbourhood.name.titleize %></h2>
<% neighbourhood.postalcodes.each do |postalcode| %>
<%= postalcode.blocks.map(&:block).join(", ") %>
<% end %>
<br>
<%= neighbourhood.streetname.titleize %>
</div>
</li>
<% end %>
</ul>
Thanks in advance.
Assuming a Neighborhood has_many Users:
<%= neighbourhood.users.size %>
Note that counting is a relatively slow option, so you can optionally cache the number of users for speed using counter_cache:
class User < ActiveRecord::Base
belongs_to :neighborhood, :counter_cache => true
end
Then in a migration:
add_column :neighborhoods, :users_count, :integer, :default => 0
Seems like an awfully deeply nested set of associations. You may want to take a second look at your models and see if you can 'trim them down' a little. Maybe something like just have a User and Unit model, then add block, postal code and neighbourhood to Unit where you could do Unit.block, and Unit.postal_code...ect.
That being said with your current configuration (assuming correct associations of has_many/belongs_to) you should be able to do something like:
Neighbourhood.postal_code.block.unit.users.count
Good luck!
<ol class="noDots">
<% # #screening.cinema.each do |screening| %>
<li>
<h3><%= screening.cinema.name %></h3>
</li>
<% #end %>
</ol>
Hi everyone,
There is an association between cinema and film through screening. Film model is separate and cinema is separate. Screening combines them together. In the cinema model, everything seems to work properly <%= screening.film.title %> works perfectly and displaying them in a loop works.
I want to create a dropdown of cinema.name with the link and it takes you there. The association has to exists as some movies in different cinemas.
Is that possible as the code above doesnt work for me.
Thanks in advance
<h3><%= screening.cinema.name %></h3>
This line should read...
<h3><%= screening.name %></h3>
And you could have this dropdown box in a form with a Submit button next to it to take you to that page...
Sounds like you are getting a lot "nil object" errors. Double check your controller to see what variables you are defining there that can be accessed in the views.
Eg, if you are setting #film, then you can traverse the associations with something like:
<% #film.screenings.each do |screening| %>
<li>
<h3><%= screening.cinema.name %></h3>
</li>
<% end %>
You should be able to alphabetize by cinema name as well, if you eager-load them when you grab the list of screenings:
<% #film.screenings.includes(:cinema).order("cinema.name ASC").each do |screening| %>
<li>
<h3><%= screening.cinema.name %></h3>
</li>
<% end %>
Hope that helps!
From what I see screen has_many :cinemas( not cinema has_many :screenings)
so
<% #screening.cinema.each do |cinema| %>
<li>
<h3><%= cinema.name %></h3>
</li>
<% end %>
please show the screening model and the cinema mode, but based on the gist..
Assuming
class Screening
belongs_to :film
belongs_to :cinema.
.....
end
class Film
has_many :screenings
has_many :cinemas, :through => :screenings
end
class Cinema
has_many :screenings,
has_many :films, :through => screenings
end
I think what you want is something along the lines of the following.
<ol class="noDots">
<% # #screenings.each do |screening| %>
<li>
<h3><%= screening.cinema.name %></h3>
</li>
<% #end %>
</ol>
Assuming that you set #screenings to subset of screenings you want in the controller..
This should work as it worked on your single screening in the comments.
In the controller
#screening = Screening.find(some_id)
In the view
<% #screening.cinema.each do |s| %>
<li>
<h3><%= s.cinema.name %></h3>
</li>
<% end %>