Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New options #73

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ class Car < ActiveRecord::Base
letsrate_rateable "speed", "engine", "price"
end
```
Set :can_change option if you want to allow users to change their ratings

```ruby
class Car < ActiveRecord::Base
letsrate_rateable "speed", "engine", "price", :can_change => true
end
```

Then you need to add a call letsrate_rater in the user model.

Expand Down Expand Up @@ -93,6 +100,12 @@ You can use the rating_for_user helper method to show the star rating for the us
Speed : <%= rating_for_user @car, current_user, "speed", :star => 10 %>
```

Use :readonly option if you need only show rating, without ability to set rating

```erb
Speed : <%= rating_for @car, "speed", :readonly => true %>
Speed : <%= rating_for_user @car, current_user, "speed", :readonly => true %>
```

## Feedback
If you find bugs please open a ticket at [https://github.com/muratguzel/letsrate/issues](https://github.com/muratguzel/letsrate/issues)
21 changes: 15 additions & 6 deletions lib/letsrate/helpers.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
module Helpers

# show rate widget
# @options[:readonly] show widget in read only mode
# @options[:disable_after_rate] disable widget after rate
def rating_for(rateable_obj, dimension=nil, options={})

cached_average = rateable_obj.average dimension
Expand All @@ -10,6 +14,8 @@ def rating_for(rateable_obj, dimension=nil, options={})
disable_after_rate = options[:disable_after_rate] || true

readonly = !(current_user && rateable_obj.can_rate?(current_user, dimension))
# now we can force readonly attribute
readonly = options[:readonly] || readonly unless readonly

content_tag :div, '', "data-dimension" => dimension, :class => "star", "data-rating" => avg,
"data-id" => rateable_obj.id, "data-classname" => rateable_obj.class.name,
Expand All @@ -18,24 +24,27 @@ def rating_for(rateable_obj, dimension=nil, options={})
"data-star-count" => star
end

# show rate widget for user
# @options[:readonly] show widget in read only mode
# @options[:disable_after_rate] disable widget after rate
def rating_for_user(rateable_obj, rating_user, dimension = nil, options = {})
@object = rateable_obj
@user = rating_user
@rating = Rate.find_by_rater_id_and_rateable_id_and_dimension(@user.id, @object.id, dimension)
stars = @rating ? @rating.stars : 0

@rating = Rate.find_by_rater_id_and_rateable_id_and_dimension(@user.id, @object.id, dimension)
stars = @rating ? @rating.stars : 0
stars_count = options[:stars_count] || stars
disable_after_rate = options[:disable_after_rate] || false

readonly=false
readonly= options[:readonly] || false
if disable_after_rate
readonly = current_user.present? ? !rateable_obj.can_rate?(current_user.id, dimension) : true
readonly = current_user.present? ? !rateable_obj.can_rate?(current_user, dimension) : true
end

content_tag :div, '', "data-dimension" => dimension, :class => "star", "data-rating" => stars,
"data-id" => rateable_obj.id, "data-classname" => rateable_obj.class.name,
"data-disable-after-rate" => disable_after_rate,
"data-readonly" => readonly,
"data-star-count" => stars
"data-star-count" => stars_count
end

end
Expand Down
50 changes: 40 additions & 10 deletions lib/letsrate/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ def can_rate?(user, dimension=nil)
user.ratings_given.where(dimension: dimension, rateable_id: id, rateable_type: self.class.name).size.zero?
end

def has_rate?(user, dimension=nil)
user.ratings_given.where(dimension: dimension, rateable_id: id, rateable_type: self.class.name).size.nonzero?
end

def rates(dimension=nil)
dimension ? self.send("#{dimension}_rates") : rates_without_dimension
end
Expand All @@ -84,24 +88,50 @@ def letsrate_rater
end

def letsrate_rateable(*dimensions)
has_many :rates_without_dimension, -> { where dimension: nil}, :as => :rateable, :class_name => "Rate", :dependent => :destroy
opts = dimensions.extract_options!
has_many :rates_without_dimension, :as => :rateable, :class_name => "Rate", :dependent => :destroy, :conditions => {:dimension => nil}
has_many :raters_without_dimension, :through => :rates_without_dimension, :source => :rater

has_one :rate_average_without_dimension, -> { where dimension: nil}, :as => :cacheable,
:class_name => "RatingCache", :dependent => :destroy
has_one :rate_average_without_dimension, :as => :cacheable, :class_name => "RatingCache",
:dependent => :destroy, :conditions => {:dimension => nil}


dimensions.each do |dimension|
has_many "#{dimension}_rates".to_sym, -> {where dimension: dimension.to_s},
:dependent => :destroy,
:class_name => "Rate",
:as => :rateable
has_many "#{dimension}_rates".to_sym, :dependent => :destroy,
:conditions => {:dimension => dimension.to_s},
:class_name => "Rate",
:as => :rateable

has_many "#{dimension}_raters".to_sym, :through => "#{dimension}_rates", :source => :rater

has_one "#{dimension}_average".to_sym, -> { where dimension: dimension.to_s },
:as => :cacheable, :class_name => "RatingCache",
:dependent => :destroy
has_one "#{dimension}_average", :as => :cacheable, :class_name => "RatingCache",
:dependent => :destroy, :conditions => {:dimension => dimension.to_s}
end

if opts[:can_change]
class_eval <<-RUBY, __FILE__, __LINE__+1
def rate(stars, user, dimension=nil, dirichlet_method=false)
dimension = nil if dimension.blank?

if has_rate? user, dimension
user.ratings_given.where(dimension: dimension, rateable_id: id, rateable_type: self.class.name).first.update_attribute(:stars,stars)
else
rates(dimension).create! do |r|
r.stars = stars
r.rater = user
end
end
if dirichlet_method
update_rate_average_dirichlet(stars, dimension)
else
update_rate_average(stars, dimension)
end
end

def can_rate?(user, dimension=nil)
true
end
RUBY
end
end
end
Expand Down