ruby on rails - Table column that automatically calculates average rating -
i'm following tutorial , have models user
, hotel
, rating
. users can create hotels, , users can rate them. users rating value recorded table rating
user_id
, hotel_id
. when render partial <%= render "hotels/hotels_list", :@hotels => hotel.all %>
shows list of hotels average rating calculates in model hotel
model hotel.rb :
class hotel < activerecord::base attr_accessible :user_id belongs_to :user has_many :ratings has_many :raters, :through => :ratings, :source => :users def average_rating @value = 0 self.ratings.each |rating| @value = @value + rating.value end @total = self.ratings.size '%.2f' % (@value.to_f / @total.to_f) end end
model user.rb :
class user < activerecord::base has_many :hotels has_many :ratings has_many :rated_hotels, :through => :ratings, :source => :hotels end
model rating.rb :
class rating < activerecord::base attr_accessible :value belongs_to :user belongs_to :hotel end
i need sort list of hotels average rating, maybe need add column average_rating
@ once calculate average value average_rating
method in hotel model, can access it. how can solve issue? ratingscontroller.rb
class ratingscontroller < applicationcontroller before_filter :authenticate_user! def create @hotel = hotel.find_by_id(params[:hotel_id]) @rating = rating.new(params[:rating]) @rating.hotel_id = @hotel.id @rating.user_id = current_user.id if @rating.save respond_to |format| format.html { redirect_to hotel_path(@hotel), :notice => "your rating has been saved" } format.js end end end def update @hotel = hotel.find_by_id(params[:hotel_id]) @rating = current_user.ratings.find_by_hotel_id(@hotel.id) if @rating.update_attributes(params[:rating]) respond_to |format| format.html { redirect_to hotel_path(@hotel), :notice => "your rating has been updated" } format.js end end end end
very simple. first, add average_rating
column hotel model migration. then, add callback rating model updates value in hotel model. basically, every time rating created, destroyed, or updated, need update average rating. this:
class hotel < activerecord::base [ code snipped ] def update_average_rating @value = 0 self.ratings.each |rating| @value = @value + rating.value end @total = self.ratings.size update_attributes(average_rating: @value.to_f / @total.to_f) end end class rating belongs_to :hotel after_create :update_hotel_rating def update_hotel_rating hotel.update_average_rating end end
now can sort rating. i'm leaving details out think can general idea here.
Comments
Post a Comment