How to Display count of subscribers for particular speaker - ruby-on-rails

I want to display count of subscribers for particular speaker in my index page. I didnt do anything in my route because i am simply looping in my index page. I have working listenerspeakers association. In my pages controller i have
class PagesController < ApplicationController
def home
#messages = Message.all.order("created_at DESC")
#speakers = Speaker.all
#sub = ListenersSpeakers.all
end
end
in my view i try to loop and insert this code but it doesnt work.
<% #sub.each do |sub| %>
<%= #sub.speaker.count %> Subscribers</span>
<% end %>
my model
class ListenersSpeakers < ActiveRecord::Base
belongs_to :listener
belongs_to :speaker
end
Update
my Speaker model has
has_many :listeners_speakers, class_name: 'ListenersSpeakers'

So I assume that in the Speaker model, it has_many :listener_speakers like:
class Speaker < ActiveRecord::Base
has_many :listener_speakers
end
You can then use
#sub.speaker.listener_speakers.count
in the view to get the number of listeners.
Not related to the question, but you may also want to consider adding a:
has_many :listeners, through: :listener_speakers
as that may eventually prove useful.

Related

How to loop through a joined table

The models I have:
Category:
class Category < ApplicationRecord
has_many :categorizations
has_many :providers, through: :categorizations
accepts_nested_attributes_for :categorizations
end
Provider:
class Provider < ApplicationRecord
has_many :categorizations
has_many :categories, through: :categorizations
accepts_nested_attributes_for :categorizations
end
Categorization:
class Categorization < ApplicationRecord
belongs_to :category
belongs_to :provider
has_many :games, dependent: :destroy
accepts_nested_attributes_for :games
end
Game:
class Game < ApplicationRecord
belongs_to :categorization
end
I need to display the games, that belongs to a specific provider. I tried to do it like:
<% #provider.categorizations.joins(:games).each do |game| %>
<%= game.title %>
<% end %>
It gives me an error: NoMethodError: undefined method 'title' for #<Categorization:0x007f2cf6ee49e8>. So, it loops through the Categorization. What is the best way to loop through the joined games table? Thanks.
First, you should do the request in your controller, or even better call a scope (defined in a model) from the controller.
Do not forget that Active Record is just an ORM, a tool allowing you to manipulate SQL.
With #provider.categorizations.joins(:games) you are not asking for games. You are asking for the categorizations and you do a JOIN with the games table. This joins is usually to allow to filter by games attributes.
To do what you want you should do the following :
#games = Game.joins(:categorization).where('categorization.provider_id = ?',#provider.id)
As you can see, the join do not return categorization, it allow me to use categorization as a filter.
You should always be aware of the SQL generated by Active Record. Look at the SQL query generated in your server's traces.
I'm guessing 'title' is an attribute of games and not categorization, so you either need to return an array of games, or add a select on the end to pull the title attribute into the categorization object, like so:
<% #provider.categorizations.joins(:games).select('dba.games.title').each do |game| %>
<%= game.title %>
<% end %>
Just to add- you shouldn't really be doing this in the view file. I'd go as far as not even doing this in the controller. I tend to encapsulate this sort of logic into a service class, which is instantiated in the controller to return a set of results. The controller should only be passing the result set on, which is then presented by the view.
class Provider < ActiveRecrord::Base
# this could be a scope instead, or in a seperate class which
# the provider model delegates to- whatever floats you boat
def get_games
# you could use pluck instead, which would return an array of titles
categorizations.joins(:games).select('dba.games.title')
end
end
class ProviderController < ApplicationController
def show
provider = Provide.find(params[:id])
#games = provider.get_games
end
end
<% #games.each do |game| %>
<%= game.title %>
<% end %>

Model methods work in Bookings model but not in Events and Tickets

I'm creating a ticket booking app as my sample project using Ruby on Rails 4.1. Three are three models - Events, Tickets and Bookings. Events have many tickets and bookings. Tickets have many bookings and they belong to events. Bookings belongs to events and tickets.
I am able to create model methods in Booking.rb and able to use them in my views. I am even able to pull data from other models in these methods. However, when I try to use model methods in Event and Ticket and try to use them in their show pages I get undefined method 'maximum_tickets_allowed'error (or whatever the method name is) when trying to print #event.event_fire or #ticket.maximum_tickets_allowed in the show pages. PFA the screenshot.
http://imgur.com/z74qAnN
The Bookings Model:
class Booking < ActiveRecord::Base
belongs_to :event
belongs_to :ticket
has_many :charges
def total_amount
ticket.ticket_price.to_i * order_quantity.to_i
end
def test
ticket.maximum_quantity.to_i
end
end
Bookings Show page:
<h2>Booking Show</h2>
<p><%= #booking.buyer_name %></p>
<p><%= #booking.order_quantity %></p>
<p><%= #booking.ticket.ticket_name %></p>
<p><%= number_to_currency(#booking.total_amount) %></p>
<p><%= #booking.test %></p>
This renders fine. The problem arises in event.rb:
class Event < ActiveRecord::Base
has_many :tickets, dependent: :destroy
has_many :bookings
has_many :charges
def self.event_fire
self.about.upcase
#ticket.maximum_quantity.to_i * ticket.minimum_quantity.to_i
end
end
Even simple calculations aren't recognized in the show template. When I use #event.event_fire to print the value. The same happens in the ticket model methods as well.
class Ticket < ActiveRecord::Base
belongs_to :event
has_many :bookings
def self.maximum_tickets_allowed
(1..maximum_quantity.to_i).to_a
#max = maximum_quantity.to_i
#self.maximum_quantity = (1..max).to_a
#self.maximum_quantity = max
end
end
The source code is here https://bitbucket.org/stravarius/ticket-fire. How do I get past this?
Try using
class Ticket < ActiveRecord::Base
belongs_to :event
has_many :bookings
def maximum_tickets_allowed
(1..maximum_quantity.to_i).to_a
#max = maximum_quantity.to_i
#self.maximum_quantity = (1..max).to_a
#self.maximum_quantity = max
end
end
remove self from self.maximum_tickets_allowed. Self is for class method. You cannot access a class method from instance methods. Check more http://www.railstips.org/blog/archives/2009/05/11/class-and-instance-methods-in-ruby/

Rails: Show all associated records on a has_many through association

I'm building a guestlist app and I have defined both Guest (name) and List models - guests can have many lists and lists can have many guests. Both are associated in a has_many through association (after reading that HABTM associations aren't a good idea).
Here are my models:
class Guest < ActiveRecord::Base
has_many :lists, through: :checklists
end
class List < ActiveRecord::Base
has_many :guests, through: :checklists
end
class Checklist < ActiveRecord::Base
belongs_to :list
belongs_to :guest
end
EDIT - my lists controller for show:
def show
#list = List.find(params[:id])
end
On the List show view, I want to display the all of the guest names that are tied to that list through the checklist table. I can figure out if I need a do loop or an array...this is a bit beyond my current skill.
I've tried things like the following:
<%= #list.checklist.guest.name %>
I'm clearly missing some key bit of code and concept here.
Thanks in advance.
You need to iterate over guests like this:
<% #list.guests.each do |guest| %> # For each guest in list.guests
<%= guest.name %> # print guest.name
<% end %>
It should be something like this
<% #list.guests.each do |guest| %>
<%= guest.name %>
<% end %>

Rails sorting associated records

Using Rails 3.0.10 & Ruby 1.9.2.
I have a Book model which has many Pages.
class Book < ActiveRecord::Base
has_many :pages
# is this right?
def pages
Page.order('page_number asc').find_all_by_book_id(:id)
end
end
class Page < ActiveRecord::Base
belongs_to :book
end
When I retrieve the pages of a book, I always want them ordered by their page number. What is the proper way to handle this so that calling book.pages will return all pages in sequence?
When editing the book I also show the content of each page which can be edited. If I am using nested attributes would this return the pages in their proper sequence, assuming my previous question is resolved?
<%= form_for [#book, #pages] do |f| %>
<%= f.fields_for :pages do |page| %>
do something
<% end %>
<% end %>
Thanks
I believe you could actually specify the default order directly on the association declaration:
class Book < ActiveRecord::Base
has_many :pages, :order => "page_number asc"
end
class Page < ActiveRecord::Base
belongs_to :book
end
This way, you won't have to specify the Book#pages method yourself, and it will still be ordered by page_number asc by default.
for newer versions of Rails, the syntax has changed:
class Book < ActiveRecord::Base
has_many :pages, -> { order "page_number asc" }
end
class Page < ActiveRecord::Base
belongs_to :book
end

is there better way to count for three level nested forms

I have a nested forms like:
class House < ActiveRecord::Base
has_many :rooms
accepts_nested_attributes_for :rooms
attr_accessible :rooms_attributes
end
class Room < ActiveRecord::Base
has_one :tv
accepts_nested_attributes_for :tv
attr_accessible :tv_attributes
end
class Tv
belongs_to :user
attr_accessible :manufacturer
validates_presence_of :user
end
Now, I want to know for house.id = 1 how many rooms and tvs totally.
In the houses_controller I gave
#houses = House.all
And it's quit simple to get the room count for each house like
<% for house in #houses %>
<%= house.rooms.count %>
<% end -%>
My question is how to get tvs count? I am using this now
<%= house.rooms.map {|room| room.tvs.count}.sum %>
It works, but I am not sure this is good or not.
Is there any better way to get it?
I'd put a method in the model, trying to avoid code in the views.
class House
...
def tvs
rooms.inject(0) {|r, t| t + r.tvs }
end
end
class Room
...
def tvs
tv ? 1 : 0 # it's has_one association right now
end
end
Also, if in your controller your are loading all House's objects, and after that you are going to need the Rooms objects, you should load the houses like:
House.find :all, :include => { :rooms => :tv }
This way you are going to do 1 query, with your approach there will be 1 + N_rooms + N_tvs queries

Resources