Hello everybody.
I'm trying to sum 2 columns(amount_ensure and vehicle_Value) from different tables in my view
TABLES
|POLICIES|
|id| |amount_ensure|
|POLICY_VEHICLES|
|id| |policy_id|
|VEHICLES|
|Id| |vehicle_value|
Here is my controller
def view_policy
#obj_policy = Policy.find(params[:id])
end
Here is my model
class Policy < ActiveRecord::Base
has_many :policy_vehicles
has_many :vehicles, :through => :policy_vehicles
end
class PolicyVehicle < ActiveRecord::Base
belongs_to :vehicle
belongs_to :policy
end
class Vehicle < ActiveRecord::Base
belongs_to :policy
has_many :policy_vehicles
has_many :policies, :through => :policy_vehicles
end
Here is my view when in my partial view #obj_policy.vehicle is empty show only amount_ensure but when has value do SUM (but is an array from my partial view)
<% if #obj_policy.vehicles.empty? %>
Sum:
<%= #obj_policy.amount_ensure %>
<% else %>
Sum:
<%= #obj_policy.amount_ensure + #obj_policy.vehicles.vehicle_value.to_i %>
<% end %>
<%= render :partial=>"vehicles" %>
My partial view
<% #obj_policy.vehicles.each do |vehicle| %>
<%= vehicle.vehicle_value %>
<% end %>
How can i fix this problem?
I will appreciate help.
This should work
<% else %>
Sum:
<%= #obj_policy.amount_ensure + #obj_policy.vehicles.collect(&:vehicle_value).sum %>
<% end %>
#obj_policy.vehicles.collect(&:vehicle_value).sum will be 0 when vehicles array is empty
Actually it will be better to allow SQL to handle it.
<%= #obj_policy.amount_ensure + #obj_policy.vehicles.sum(:vehicle_value) %>
You can also wrap it into a instance method:
class Policy
def total_value
amount_ensure + vehicles.sum(:vehicle_value) # I don't remember if `to_i` is necessary here in case of empty collection, try it out
end
end
It's also possible to write a custom SQL query that will do this summing in database. In case of original solution proposed it fetches ALL vehicles with ALL fields that might not be necessary at all. Try to use SQL as much as possible for aggregation jobs.
Related
I have three models with the following associations:
class Product < ApplicationRecord
belongs_to :store
has_many :variants, dependent: :destroy
end
class Store < ApplicationRecord
has_many :variants
belongs_to :user
has_many :products, dependent: :destroy
end
class Variant < ApplicationRecord
belongs_to :product
belongs_to :store, optional: true
end
And I'm counting the products & variants of each user with the following:
#products = current_user.store.products.group(:subcategory_id).count
#variants = current_user.store.variants.group(:subcategory_id).count
The above returns this #products => {181=>1, 185=>1}
and this #variants => {181=>2, 185=>1}
Finally when I try to loop through each of the above hashes the results show up correctly but they also show up two times(dublicate results). Any ideas on how to fix this??
<% #products.each do |product_key, product_value| %>
<% #variants.each do |variant_key, variant_value| %>
<%= #child_category.name %> - <%= #subcategory.name %><br>
Products: <%= product_value %><br>
Variants: <%= variant_value %><br>
Total Products: <%= product_value + variant_value %><br>
<% end %>
<% end %>
This is the result:
This is not duplicating anything, this is expected behavior. It shows each product with its variants.
You're looping through two hashes, which contains 2 pairs, so the outer loop executes 2 times and the inner loop executes 2 * 2 => 4 times.
This is the expected behavior.
And if you wanted to show only a single pair, you can add if condition over there for subcategory -
i.e. I wanted to show only results where subcategory is Boys then you can use following code -
<% #products.each do |product_key, product_value| %>
<% #variants.each do |variant_key, variant_value| %>
<% if #subcategory.name == 'Boys' %>
<%= #child_category.name %> - <%= #subcategory.name %><be>
Products: <%= product_value %><be>
Variants: <%= variant_value %><be>
Total Products: <%= product_value + variant_value %><be>
<% end %>
<% end %>
<% end %>
I fail to find the correct syntax to retrieve associated information. I have a model 'companyaccount' that belongs to a model 'company'.
class Company < ActiveRecord::base
has_many :companyaccounts
end
class Companyaccount < ActiveRecord::base
belongs_to :company
end
In the View, I can easily retrieve both the 'Companyaccount' 'number' and the 'id' of the associated company through the 'company_id' field of the 'companyaccount' table.
<%= #companyaccount.each do |companyaccount| %>
<%= companyaccount.company_id %>
<%= companyaccount.number %>
<% end %>
The View is called from this basic Controller
def index
#companyaccount = Companyaccount.all
end
Now, I do not want to have the company_id but the actual name of the company (housed in the 'company' table). I manage to do it for one specific company using a controller like this
def index
#companyaccount = Companyaccount.all
#company = Company.first
end
and then in the view change
<%= companyaccount.company_id %>
by
<%= company.name %>
but of course, this will retrieve, for each companyaccount, the same first company and not each of the company associated with the companyaccount. Could anyone provide me with the appropriate syntax to retrieve the associated company's name for each companyaccount in the "each" loop of my View? Thanks.
You can use delegate for this.
class Companyaccount < ActiveRecord::base
belongs_to :company
delegate :name, to: :company, prefix: true
end
and then you can call <%= companyaccount.company_name %>
You should be able to achieve what you want with this loop:
<%= #companyaccount.each do |companyaccount| %>
<%= companyaccount.company.name %>
<%= companyaccount.number %>
<% end %>
def index
#companyaccount = Companyaccount.all
end
and in view
<% #companyaccount.each do |companyaccount| %>
<%= companyaccount.company.name %>
<% end %>
for less db call you can change controller like
#companyaccount = Companyaccount.includes(:company).all
So I have four models
class User
has_many :user_rows
end
class Assignment
has_many :rows
end
class Row
belongs_to :assignment
has_many :user_rows
end
class UserRow
belongs_to :user
belongs_to :row
end
On the assignment show view I want to loop through the rows and for each row have a user_row to capture user input.
My question is how to intialize the user rows. Would it be best to do this?
class AssignmentController
def show
#assignment = Assignment.include(:rows).find(params[:id])
end
end
Then in the view just use first_or_create
<%= #assignment.rows.each do |row| %>
<%= row.data %>
<%= form_for UserRow.where(row_id: row.id, user_id: current_user.id).first_or_create, remote: true do |f| %>
<%= form_fields %>
<% end %>
<% end %>
As you can see the objects need to be iterated over in the view.
Which I don't like particularly because it's initializing an object in the view. Or is it best to create all the user_rows for each row when a user signs up to the site and if a new row is created create a user_row for all users?
Or is there a better solution I've missed?
I guess, fields_for and accepts_nested_attributes_for might help you. You might check these documents.
fields_for (ActionView::Helpers::FormBuilder) - APIdock
accepts_nested_attributes_for (ActiveRecord::NestedAttributes::ClassMethods) - APIdock
I am trying to calculate the average rating in the view of my rails app through a has_many relationship.
Models:
class Review < ActiveRecord::Base
belongs_to :product
attr_accessible :rating, :review
belongs_to :user
end
class Product < ActiveRecord::Base
attr_accessible :name
has_many :reviews
has_many :supplements
acts_as_taggable
end
Controller:
#products = Product.all
View:
<% #products.each do |product| %>
<%= product.NOT SURE %>
<% end %>
I would like this to show the average rating for that given product in the view, but am not sure how. Any advice?
In your view, you want something like:
<% #products.each do |product| %>
<%= product.average_rating %>
<% end %>
Now you just need to do the average_rating, and that can go in the model:
def average_rating
if self.reviews.size > 0
self.reviews.average(:rating)
else
'undefined'
end
end
So average_rating sums up the review ratings and divides by the number of ratings for the average. You can polish it up for format, etc.
My app has a user model, as well as multiple other date related models/tables such as anniversaries, holidays, birthdays, and and "other dates" custom model.
I have a user dashboard view that lists them all separately as shown below. How can i display all of these lists as one (call it upcoming events or something) that is listed chronologically and shows them upcoming dates for a certain period of time.
View
*note - These are displayed in a table/list but i stripped html for clarity
<h1>Holidays</h1>
<% if #user.holidays.any? %>
<% #user.holidays.each do |hld| %>
<%= hld.name %>
<%= hld.date %>
<% end %>
<h1>Friends Birthdays</h1>
<% if #user.friends.any? %>
<% #user.friends.each do |frd| %>
<%= frd.name %>
<%= frd.dob %>
<% end %>
<h1> Anniversary </h1>
<% if #user.anniversaries.any? %>
<% #user.anniversaries.each do |ann| %>
<%= ann.spouse_name %>
<%= ann.anniversary_date %>
<% end %>
Thanks!
Models
class User < ActiveRecord::Base
has_many :friends
has_many :occasions
has_many :user_holidays
has_many :holidays, :through => :user_holidays
has_many :anniversaries
class Holiday < ActiveRecord::Base
has_many :user_holidays
has_many :users, :through => :user_holidays
end
class Friend < ActiveRecord::Base
belongs_to :user
end
class Anniversary < ActiveRecord::Base
belongs_to :user
end
Assuming you want to be efficient (you could just combine the arrays, sort them and be done with it), there is no direct way to do it through the relations. I am assuming you have an events model which has a foreign key to the user, in that case,
Events.where(:user_id => #user.id).where(<EVENT DATE FILTERS>).order("event_date DESC")
-- EDIT --
This is quite dirty, but I cant think of any other direct db way of accomplishing this.
events = #user.holidays.map{|h| [h.name, h.date, :holiday]} + \
#user.friends.map{|f| [f.name, f.dob, :birthday]} + \
#user.anniversaries.map{|a| [a.spouse_name, a.anniversary.date, :anniversary]}
events.map!{|event| {:name => event[0], :date => event[1], :event_type => event[2]}}
# You now have an array of hashes with the events name, date and type.
events.sort{|a, b| a[:date] <=> b[:date]} # sort / filter