How to show the sum of all Prices that a Student has - ruby-on-rails

Student has_many Lessons
Lesson belongs_to Prices
How can I show the sum of all Prices that Student has in show action of the StudentsController?

As #mgidea already correctly said:
You want to create a has_many :through relationship in your Student model first and then you want to convert the prices of your Student into an Array with #to_a and then create the sum of your price_attribute.
Add the following to your Student model:
class Student < ActiveRecord::Base
has_many :lessons
has_many :prices, through: :lessons # <= Add this here
end
Your show action could than look like:
class StudentsController < ApplicationController
def show
#student = Student.find(params[:id]
#sum = #student.prices.to_a.sum(&:price)
# Equivalent to:
# #sum = #student.prices.to_a.sum { |p| return p.price }
end
end
Than you could use the instance variable #sum in your view.
Hope this helps!
Happy coding :)

Addin a query of sum in controller does it.
Answer: https://github.com/yshmarov/myclass101/commit/9a998da2af07caee76948d2941ad006029a0f47a

Related

Association not working

I have three models:
Department
class Department < ActiveRecord::Base
has_many :patients, :dependent => :destroy
has_many :waitingrooms, :dependent => :destroy
end
Waitingroom with fields patient_id:integer and department_id:integer
class Waitingroom < ActiveRecord::Base
belongs_to :patient
end
Patient with department_id:integer
class Patient < ActiveRecord::Base
belongs_to :department
has_many :waitingrooms
end
I save a waitingroom after a patient was in the waitingroom! So now i tried to retrieve the patients who where in the the waitingroom of the department:
def index
#waited = #current_department.waitingrooms.patients
end
Somehow it didnt worked it returned this error:
undefined method `patients' for #<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Waitingroom:0x374c658>
But this worked: What did i wrong? Thanks!
def index
#waited = #current_department.waitingrooms
end
You can't invoke an association on a collection. You need to invoke it on a specific record. If you want to get all the patients for a set of waiting rooms, you need to do this:
def index
rooms = #current_department.waitingrooms
#waited = rooms.map { |r| r.patients }
end
If you want a flat array, you could (as a naive first pass) use rooms.map { |r| r.patients }.flatten.uniq. A better attempt would just build a list of patient ids and fetch patients once:
#waited = Patient.where(id: rooms.pluck(:patient_id).uniq)

Using sunspot to search down model hierarchy

Example:
I have the following:
class Person < ActiveRecord::Base
has_many :educations
end
class Education < ActiveRecord::Base
belongs_to :school
belongs_to :degree
belongs_to :major
end
class School < ActiveRecord::Base
has_many :educations
# has a :name
end
I want to be able to return all people who went to a specific school so in my PeopleController#index I have
#search = Person.search do
keywords params[:query]
end
#people = #search.results
How do I create the searchable method on the Person model to reach down into school? Do I do something like this:
searchable do
text :school_names do
educations.map { |e| e.school.name }
end
end
which I would eventually have to do with each attribute on education (degree etc) or can I make a searchable method on Education and somehow "call" that from Person.searchable?
Thanks
It would be best if you keep the declaration of all the indexed fields for an specific model in the same place.
Also, you were doing a good job indexing :school_names, just do the same thing for the rest of the associations fields' that you want to index.

Include column from a :belongs_to association?

Product model
Class Product < ActiveRecord::Base
belongs_to :product_group
end
ProductGroup model
Class ProductGroup < ActiveRecord::Base
has_many :products
end
Is the a way to declare a shortcut for product.product_group.name as product.name,
and have product_group.name included in product.to_json as name whenever a Product is converted to json?
To answer your first question: create a name method in Product
def name
product_group.name
end
As for your second question, you can customize as_json, also in your Product model. Something like this should work.
def as_json(options = {})
super.merge({ name: name })
end

How to perform calculations on nested form items?

I am fairly new to Rails and I have these two models...
class Invoice < ActiveRecord::Base
has_many :items
accepts_nested_attributes_for :items
...
end
class Item < ActiveRecord::Base
belongs_to :invoice
def self.total
price * quantity
end
...
end
... and a nested (!) form that creates new invoice records and their associated items.
However, I find it very difficult to perform calculations on these items. For example next to each item I would like to put the total for this item using the total method above.
Unfortunately, it's not working. In my form I put this next to each item:
<%= #invoice.items.amount %>
which is derived from my controller:
def new
#invoice = Invoice.new
3.times {#invoice.items.build}
end
It keeps throwing an error saying undefined local variable or method price
What am I missing here??
Thanks for any help.
You have created a class method on Item, when I think what you want is an instance method.
class Item < ActiveRecord::Base
belongs_to :invoice
def total
price * quantity
end
...
end
which you can call on an individual item #item.total or, if you do you the total of all the items, then you'd need to do something like this:
class Item < ActiveRecord::Base
belongs_to :invoice
def self.total
all.collect { |item| item.price * item.quantity }
end
...
end
#invoice.items.total
Hope that helps.

Active Relation: Retrieving records through an association?

I have the following models:
class User < ActiveRecord::Base
has_many :survey_takings
end
class SurveyTaking < ActiveRecord::Base
belongs_to :survey
def self.surveys_taken # must return surveys, not survey_takings
where(:state => 'completed').map(&:survey)
end
def self.last_survey_taken
surveys_taken.maximum(:position) # that's Survey#position
end
end
The goal is to be able to call #user.survey_takings.last_survey_taken from a controller. (That's contrived, but go with it; the general goal is to be able to call class methods on #user.survey_takings that can use relations on the associated surveys.)
In its current form, this code won't work; surveys_taken collapses the ActiveRelation into an array when I call .map(&:survey). Is there some way to instead return a relation for all the joined surveys? I can't just do this:
def self.surveys_taken
Survey.join(:survey_takings).where("survey_takings.state = 'completed'")
end
because #user.survey_takings.surveys_taken would join all the completed survey_takings, not just the completed survey_takings for #user.
I guess what I want is the equivalent of
class User < ActiveRecord::Base
has_many :survey_takings
has_many :surveys_taken, :through => :survey_takings, :source => :surveys
end
but I can't access that surveys_taken association from SurveyTaking.last_survey_taken.
If I'm understanding correctly you want to find completed surveys by a certain user? If so you can do:
Survey.join(:survey_takings).where("survey_takings.state = 'completed'", :user => #user)
Also it looks like instead of:
def self.surveys_taken
where(:state => 'completed').map(&:survey)
end
You may want to use scopes:
scope :surveys_taken, where(:state => 'completed')
I think what I'm looking for is this:
class SurveyTaking < ActiveRecord::Base
def self.surveys_taken
Survey.joins(:survey_takings).where("survey_takings.state = 'completed'").merge(self.scoped)
end
end
This way, SurveyTaking.surveys_taken returns surveys taken by anyone, but #user.survey_takings.surveys_taken returns surveys taken by #user. The key is merge(self.scoped).
Waiting for further comments before I accept..

Resources