How to calculate average in rails app view through has_many? - ruby-on-rails

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.

Related

Rails loop showing duplicate results

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 %>

Counting how many objects belong to a parent parent in rails

Basically I have 3 different models
class Zone < ApplicationRecord
has_many :providers
end
class Provider < ApplicationRecord
has_many :referrals
belongs_to :zone
end
class Referrals < ApplicationRecord
belongs_to :provider
end
Referrals belong to Providers which then belongs to a Zone. Now the problem im having is counting how many referrals from a zone?
this is the erb tag I tried
<% #zones.each do |z| %>
<li style="color: green">
<%= link_to z.name, z %>
<% z.providers.each do |p| %>
<%= p.referrals.count %>
<% end %>
</li>
<% end %>
But that counts the referrals from each provider and displays it. I want it to just show the total only?
class Zone < ApplicationRecord
has_many :providers
has_many :referrals, through: :providers
end
This will let you do...
z.referrals.count

Rails Join Table Nested form_for

I'm learning Rails building an ordering system and I'm stuck trying to build a form for Orders. Where Orders is a nested resource for Restaurant.
Routes:
resources :restaurants do
resources :orders
resources :recipes
end
My models look like this:
class Restaurant < ActiveRecord::Base
has_many :orders
has_many :recipes, dependent: :destroy
end
class Order < ActiveRecord::Base
belongs_to :restaurant
has_many :order_recipes, dependent: :destroy
has_many :recipes, through: :order_recipes
end
class Recipe < ActiveRecord::Base
belongs_to :restaurant
has_many :order_recipes
has_many :orders, through: :order_recipes
end
My controller:
#recipes = #restaurant.recipes
#order_recipes = #recipes.map{|r| #order.order_recipes.build(recipe: r)}
And my view:
<%= form_for([#restaurant, #order]) do |order_form| %>
<%= order_form.label :Table_Number %>
<%= order_form.number_field :table_id %>
<%= order_form.fields_for :order_recipes, #order_recipes do |orf| %>
<%= order_form.hidden_field :recipe_ids %>
<%= order_form.label Recipe.where(id: :recipe_id) %>
<%= orf.number_field :quantity %>
My current problem is displaying the names of each recipe. It seems that :recipe_id is being passed as null all the time. My ultimate goal is to be able to build order_recipes populating the quantity column, and I thought having the recipe_id from order_recipes I could also access the correct recipe object from the DB to display the name or any other relevant data.
try so in your controller:
#order_recipes = #recipes.map{|r| #order.build_order_recipes(recipe: r)}
Eventually I got this the answer posted in this question to work: Rails 4 Accessing Join Table Attributes
I'm only struggling with passing the correct parameters now, but the form is correct.
I assumed, you have a restaurant, it has recipes, it takes orders, orders are tracked by order_recipes table.
# controller
#recipes = #restaurant.recipes
#order = #recipes.map{|r| r.order.build}
# view
<%= form_for([#restaurant, #order]) do |order_form| %>
...
<% #order.each do |index, ord| %>
<%= order_form.fields_for :orders, #order do |orf| %>
...
<%= order_form.label #recipes[index] %>
<%= orf.number_field :quantity %>
# also in restaurant model
accepts_nested_attributes_for :orders

Sum 2 columns a value with array

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.

Rails: Create form for #score while in different model no direct associations

I want to create a multiple form for editing scores from a different model.
The main model is a Formrule model that consists of a habtm association with a Scoretype model
and has a habtm association with a Room model.
Both models are used to query a Scores model resulting in a #scores instance. It is for this instance I want to create a form, but the problem is that no field_for are being created. I know that the #scores is populated correctly, but the form does not show up.
This is the form as I have it now
<%= form_tag '/scores/update_scores' do %>
<table>
<tr>...</tr>
<% for score in #scores %>
<% fields_for :scores, score do |score| %>
<tr>
<td>
<%= score.hidden_field(:form_id) %>
<%= score.hidden_field(:team_id) %>
<%= score.hidden_field(:scoretype_id) %>
</td>
<td>
<%= score.number_field :scorevalue %>
</td>
</tr>
<% end %>
<% end %>
</table>
<%= submit_tag 'Update' %>
<% end %>
And these are the Models:
Formrule
class Formrule < ActiveRecord::Base
belongs_to :form
has_and_belongs_to_many :scoretypes
has_and_belongs_to_many :rooms
has_many :teams, :through => :rooms
end
Scoretype
class Scoretype < ActiveRecord::Base
has_many :scores
has_and_belongs_to_many :formrules
end
Room
class Room < ActiveRecord::Base
has_many :teams
has_and_belongs_to_many :formrules
end
Team
class Team < ActiveRecord::Base
has_many :scores
belongs_to :room
belongs_to :group
end
Score
class Score < ActiveRecord::Base
belongs_to :form
belongs_to :team
belongs_to :scoretype
validates_uniqueness_of :id, :scope => [:team, :scoretype]
end
And finally, the used controller (Formrule)
def show
#formrule = Formrule.find(params[:id])
#scoretypes = #formrule.scoretypes.all.collect
#rooms = #formrule.rooms.all.collect
#teams = Team.find(:all, :conditions => {:room_id => #rooms})
#scores = Score.order("team_id").all(:conditions => {:scoretype_id => #scoretypes, :team_id => #teams})
...
end
Why is the form not showing up? any suggestions?
Thank you all in advance!
Try using <%= fields_for ... %> instead of <% fields_for ...%>.

Resources