ajaxful_rating 2.1.5 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +11 -0
- data/Manifest +6 -2
- data/README.textile +9 -10
- data/Rakefile +1 -1
- data/ajaxful_rating.gemspec +5 -5
- data/generators/ajaxful_rating/templates/migration.rb +5 -6
- data/generators/ajaxful_rating/templates/model.rb +1 -1
- data/generators/ajaxful_rating/templates/style.css +9 -9
- data/init.rb +5 -0
- data/lib/ajaxful_rating.rb +11 -2
- data/lib/axr/css_builder.rb +30 -0
- data/lib/axr/errors.rb +27 -0
- data/lib/axr/helpers.rb +89 -0
- data/lib/axr/locale.rb +21 -0
- data/lib/{ajaxful_rating_model.rb → axr/model.rb} +91 -56
- data/lib/axr/stars_builder.rb +111 -0
- metadata +25 -9
- data/lib/ajaxful_rating_helper.rb +0 -195
data/CHANGELOG
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
== 2.2.0 March 7, 2010
|
2
|
+
* Improved model methods and options.
|
3
|
+
* Works now with inherited models.
|
4
|
+
* Removed HTML and CSS options for helper for sake of simpleness.
|
5
|
+
* Renamed helper option :small_stars to :small.
|
6
|
+
* Changed whole helper approach. It should work the same as before.
|
7
|
+
(Except for the renamed and removed options)
|
8
|
+
* Removed :force_dynamic, you should exclude the helper from cache since it uses
|
9
|
+
authorization.
|
10
|
+
* Fixed opened bugs so far.
|
11
|
+
|
1
12
|
== 2.1.5 January 28, 2010
|
2
13
|
* Renamed options method name to avoid collapse.
|
3
14
|
* Removed CSS duplication.
|
data/Manifest
CHANGED
@@ -12,5 +12,9 @@ generators/ajaxful_rating/templates/model.rb
|
|
12
12
|
generators/ajaxful_rating/templates/style.css
|
13
13
|
init.rb
|
14
14
|
lib/ajaxful_rating.rb
|
15
|
-
lib/
|
16
|
-
lib/
|
15
|
+
lib/axr/css_builder.rb
|
16
|
+
lib/axr/errors.rb
|
17
|
+
lib/axr/helpers.rb
|
18
|
+
lib/axr/locale.rb
|
19
|
+
lib/axr/model.rb
|
20
|
+
lib/axr/stars_builder.rb
|
data/README.textile
CHANGED
@@ -34,7 +34,7 @@ You can configure it in your environment.rb file also:
|
|
34
34
|
h3. Generate
|
35
35
|
|
36
36
|
@script/generate ajaxful_rating UserModelName@
|
37
|
-
|
37
|
+
|
38
38
|
The generator takes one argument: UserModelName, which is the name of your *current*
|
39
39
|
user model. This is necessary to link both the rate and user models.
|
40
40
|
|
@@ -132,20 +132,19 @@ required CSS style for the list. Also don't forget to include the javascripts.*
|
|
132
132
|
<%= javascript_include_tag :defaults %>
|
133
133
|
<%= ajaxful_rating_style %>
|
134
134
|
</pre>
|
135
|
-
|
135
|
+
|
136
136
|
When a user submits a rating it will call the action in your controller, for
|
137
137
|
example (if you added the @rate@ route):
|
138
138
|
|
139
139
|
<pre>
|
140
|
-
def rate
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
140
|
+
def rate
|
141
|
+
@car = Car.find(params[:id])
|
142
|
+
@car.rate(params[:stars], current_user, params[:dimension])
|
143
|
+
render :update do |page|
|
144
|
+
page.replace_html @car.wrapper_dom_id(params[:dimension]), ratings_for(@car, params.merge(:wrap => false))
|
145
|
+
page.visual_effect :highlight, @car.wrapper_dom_id(params[:dimension])
|
146
|
+
end
|
147
147
|
end
|
148
|
-
end
|
149
148
|
</pre>
|
150
149
|
|
151
150
|
There are some more options for this helper, please see the rdoc for details.
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
Echoe.new('ajaxful_rating', '2.
|
5
|
+
Echoe.new('ajaxful_rating', '2.2.0') do |p|
|
6
6
|
p.description = "Provides a simple way to add rating functionality to your application."
|
7
7
|
p.url = "http://github.com/edgarjs/ajaxful-rating"
|
8
8
|
p.author = "Edgar J. Suarez"
|
data/ajaxful_rating.gemspec
CHANGED
@@ -2,20 +2,20 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{ajaxful_rating}
|
5
|
-
s.version = "2.
|
5
|
+
s.version = "2.2.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Edgar J. Suarez"]
|
9
|
-
s.date = %q{2010-
|
9
|
+
s.date = %q{2010-03-07}
|
10
10
|
s.description = %q{Provides a simple way to add rating functionality to your application.}
|
11
11
|
s.email = %q{edgar.js@gmail.com}
|
12
|
-
s.extra_rdoc_files = ["CHANGELOG", "README.textile", "lib/ajaxful_rating.rb", "lib/
|
13
|
-
s.files = ["CHANGELOG", "Manifest", "README.textile", "Rakefile", "ajaxful_rating.gemspec", "generators/ajaxful_rating/USAGE", "generators/ajaxful_rating/ajaxful_rating_generator.rb", "generators/ajaxful_rating/templates/images/star.png", "generators/ajaxful_rating/templates/images/star_small.png", "generators/ajaxful_rating/templates/migration.rb", "generators/ajaxful_rating/templates/model.rb", "generators/ajaxful_rating/templates/style.css", "init.rb", "lib/ajaxful_rating.rb", "lib/
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "README.textile", "lib/ajaxful_rating.rb", "lib/axr/css_builder.rb", "lib/axr/errors.rb", "lib/axr/helpers.rb", "lib/axr/locale.rb", "lib/axr/model.rb", "lib/axr/stars_builder.rb"]
|
13
|
+
s.files = ["CHANGELOG", "Manifest", "README.textile", "Rakefile", "ajaxful_rating.gemspec", "generators/ajaxful_rating/USAGE", "generators/ajaxful_rating/ajaxful_rating_generator.rb", "generators/ajaxful_rating/templates/images/star.png", "generators/ajaxful_rating/templates/images/star_small.png", "generators/ajaxful_rating/templates/migration.rb", "generators/ajaxful_rating/templates/model.rb", "generators/ajaxful_rating/templates/style.css", "init.rb", "lib/ajaxful_rating.rb", "lib/axr/css_builder.rb", "lib/axr/errors.rb", "lib/axr/helpers.rb", "lib/axr/locale.rb", "lib/axr/model.rb", "lib/axr/stars_builder.rb"]
|
14
14
|
s.homepage = %q{http://github.com/edgarjs/ajaxful-rating}
|
15
15
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Ajaxful_rating", "--main", "README.textile"]
|
16
16
|
s.require_paths = ["lib"]
|
17
17
|
s.rubyforge_project = %q{ajaxful_rating}
|
18
|
-
s.rubygems_version = %q{1.3.
|
18
|
+
s.rubygems_version = %q{1.3.6}
|
19
19
|
s.summary = %q{Provides a simple way to add rating functionality to your application.}
|
20
20
|
|
21
21
|
if s.respond_to? :specification_version then
|
@@ -1,16 +1,15 @@
|
|
1
1
|
class CreateRates < ActiveRecord::Migration
|
2
2
|
def self.up
|
3
3
|
create_table :rates do |t|
|
4
|
-
t.
|
5
|
-
t.
|
6
|
-
t.integer :stars
|
4
|
+
t.belongs_to :rater
|
5
|
+
t.belongs_to :rateable, :polymorphic => true
|
6
|
+
t.integer :stars, :null => false
|
7
7
|
t.string :dimension
|
8
|
-
|
9
8
|
t.timestamps
|
10
9
|
end
|
11
10
|
|
12
|
-
add_index :rates,
|
13
|
-
add_index :rates, :rateable_id
|
11
|
+
add_index :rates, :rater_id
|
12
|
+
add_index :rates, [:rateable_id, :rateable_type]
|
14
13
|
end
|
15
14
|
|
16
15
|
def self.down
|
@@ -6,7 +6,7 @@
|
|
6
6
|
.ajaxful-rating a:hover,
|
7
7
|
.ajaxful-rating a:active,
|
8
8
|
.ajaxful-rating a:focus,
|
9
|
-
.ajaxful-rating .
|
9
|
+
.ajaxful-rating .show-value{
|
10
10
|
background: url(/images/ajaxful_rating/star.png) left -1000px repeat-x;
|
11
11
|
}
|
12
12
|
.ajaxful-rating{
|
@@ -22,7 +22,7 @@
|
|
22
22
|
.ajaxful-rating li{ display: inline; }
|
23
23
|
.ajaxful-rating a,
|
24
24
|
.ajaxful-rating span,
|
25
|
-
.ajaxful-rating .
|
25
|
+
.ajaxful-rating .show-value{
|
26
26
|
position: absolute;
|
27
27
|
top: 0;
|
28
28
|
left: 0;
|
@@ -63,21 +63,21 @@ width: 100%;
|
|
63
63
|
z-index: 2;
|
64
64
|
}
|
65
65
|
*/
|
66
|
-
.ajaxful-rating .
|
66
|
+
.ajaxful-rating .show-value{
|
67
67
|
z-index: 1;
|
68
68
|
background-position: left center;
|
69
69
|
}
|
70
70
|
|
71
71
|
/* smaller star */
|
72
|
-
.small
|
72
|
+
.ajaxful-rating.small{
|
73
73
|
/*width: 50px; this is setted dynamically */
|
74
74
|
height: 10px;
|
75
75
|
}
|
76
|
-
.small
|
77
|
-
.small
|
78
|
-
.small
|
79
|
-
.small
|
80
|
-
.small
|
76
|
+
.ajaxful-rating.small,
|
77
|
+
.ajaxful-rating.small a:hover,
|
78
|
+
.ajaxful-rating.small a:active,
|
79
|
+
.ajaxful-rating.small a:focus,
|
80
|
+
.ajaxful-rating.small .show-value{
|
81
81
|
background-image: url(/images/ajaxful_rating/star_small.png);
|
82
82
|
line-height: 10px;
|
83
83
|
height: 10px;
|
data/init.rb
CHANGED
@@ -1 +1,6 @@
|
|
1
|
+
puts "------------------------------------------"
|
2
|
+
puts "IMPORTANT: AjaxfulRating has been updated to v2.2.x and some options changed."\
|
3
|
+
"Please read the changelog at http://github.com/edgarjs/ajaxful-rating/blob/master/CHANGELOG"
|
4
|
+
puts "------------------------------------------"
|
5
|
+
|
1
6
|
require 'ajaxful_rating'
|
data/lib/ajaxful_rating.rb
CHANGED
@@ -1,2 +1,11 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
puts "------------------------------------------"
|
2
|
+
puts "IMPORTANT: AjaxfulRating has been updated to v2.2.x and some options changed."\
|
3
|
+
"Please read the changelog at http://github.com/edgarjs/ajaxful-rating/blob/master/CHANGELOG"
|
4
|
+
puts "------------------------------------------"
|
5
|
+
|
6
|
+
require 'axr/locale'
|
7
|
+
require 'axr/errors'
|
8
|
+
require 'axr/model'
|
9
|
+
require 'axr/css_builder'
|
10
|
+
require 'axr/stars_builder'
|
11
|
+
require 'axr/helpers'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module AjaxfulRating # :nodoc:
|
2
|
+
class CSSBuilder
|
3
|
+
attr_reader :rules
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@rules = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def rule(selector, attrs)
|
10
|
+
@rules[selector] = self.class.stringify_properties(attrs) unless @rules.has_key?(selector)
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_css
|
14
|
+
css = ''
|
15
|
+
@rules.each do |key, value|
|
16
|
+
css << "#{key} {#{value}}\n"
|
17
|
+
end
|
18
|
+
css
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.stringify_properties(properties)
|
22
|
+
css = ''
|
23
|
+
properties.each do |key, value|
|
24
|
+
value = value.is_a?(Fixnum) || value.is_a?(Float) ? "#{value}px" : value
|
25
|
+
css << "#{key.to_s.underscore.dasherize}: #{value}; "
|
26
|
+
end
|
27
|
+
css
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/axr/errors.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module AjaxfulRating # :nodoc:
|
2
|
+
module Errors
|
3
|
+
class AlreadyRatedError < StandardError
|
4
|
+
def to_s
|
5
|
+
"Model has already been rated by this user. To allow update of ratings pass :allow_update => true to the ajaxful_rateable call."
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class MissingRateRoute < StandardError
|
10
|
+
def to_s
|
11
|
+
"Add a member route to your routes file for rate with :post method. Or specify a custom url in the options."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class NoUserSpecified < StandardError
|
16
|
+
def to_s
|
17
|
+
"You need to specify a user instance or create a helper with the name current_user."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class MissingStarsCSSBuilder < StandardError
|
22
|
+
def to_s
|
23
|
+
"Add a call to ajaxful_rating_style within the head of your layout."
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/axr/helpers.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
module AjaxfulRating # :nodoc:
|
2
|
+
module Helpers
|
3
|
+
include AjaxfulRating::Errors
|
4
|
+
|
5
|
+
# Outputs the required css file, and the dynamic CSS generated for the
|
6
|
+
# current page.
|
7
|
+
def ajaxful_rating_style
|
8
|
+
@axr_css ||= CSSBuilder.new
|
9
|
+
stylesheet_link_tag('ajaxful_rating') +
|
10
|
+
content_tag(:style, @axr_css.to_css, :type => "text/css")
|
11
|
+
end
|
12
|
+
|
13
|
+
# Generates the stars list to submit a rate.
|
14
|
+
#
|
15
|
+
# It accepts the next options:
|
16
|
+
# * <tt>:small</tt> Set this param to true to display smaller images. Default is false.
|
17
|
+
# * <tt>:remote_options</tt> Hash of options for the link_to_remote function.
|
18
|
+
# Default is {:method => :post, :url => rate_rateablemodel_path(rateable)}.
|
19
|
+
# * <tt>:wrap</tt> Whether the star list is wrapped within a div tag or not. This is useful when page updating. Default is true.
|
20
|
+
# * <tt>:show_user_rating</tt> Set to true if you want to display only the current user's rating, instead of the global average.
|
21
|
+
# * <tt>:dimension</tt> The dimension to show the ratings for.
|
22
|
+
#
|
23
|
+
# Example:
|
24
|
+
# <%= ratings_for @article, :wrap => false %> # => Will produce something like:
|
25
|
+
# <ul class="ajaxful-rating">
|
26
|
+
# <li class="current-rating" style="width: 60%;">3</li>
|
27
|
+
# <li><%= link_to_remote 1, :url => rate_article_path(@article, :stars => 1), :method => :post, :html => {:class => 'stars-1', :title => '1 star out of 5'} %></li>
|
28
|
+
# <li><%= link_to_remote 2, :url => rate_article_path(@article, :stars => 2), :method => :post, :html => {:class => 'stars-2', :title => '2 stars out of 5'} %></li>
|
29
|
+
# <li><%= link_to_remote 3, :url => rate_article_path(@article, :stars => 3), :method => :post, :html => {:class => 'stars-3', :title => '3 stars out of 5'} %></li>
|
30
|
+
# <li><%= link_to_remote 4, :url => rate_article_path(@article, :stars => 4), :method => :post, :html => {:class => 'stars-4', :title => '4 stars out of 5'} %></li>
|
31
|
+
# <li><%= link_to_remote 5, :url => rate_article_path(@article, :stars => 5), :method => :post, :html => {:class => 'stars-5', :title => '5 stars out of 5'} %></li>
|
32
|
+
# </ul>
|
33
|
+
#
|
34
|
+
# It will try to use the method <tt>current_user</tt> as the user instance. You can specify a custom instance in the second parameter
|
35
|
+
# or pass <tt>:static</tt> to leave the list of stars static.
|
36
|
+
#
|
37
|
+
# Example:
|
38
|
+
# <%= ratings_for @article, @user, :small => true %>
|
39
|
+
# # => Will use @user instead <tt>current_user</tt>
|
40
|
+
#
|
41
|
+
# <%= ratings_for @article, :static, :small => true %>
|
42
|
+
# # => Will produce a static list of stars showing the current rating average for @article.
|
43
|
+
#
|
44
|
+
# The user passed here will *not* be the one who submits the rate. It will be used only for the display behavior of the stars.
|
45
|
+
# Like for example, if there is a user logged in or if the current logged in user is able to submit a rate depending on the
|
46
|
+
# configuration (accepts update of rates, etc).
|
47
|
+
#
|
48
|
+
# So to actually set the user who will rate the model you need to do it in your controller:
|
49
|
+
#
|
50
|
+
# # controller
|
51
|
+
# def rate
|
52
|
+
# @article = Article.find(params[:id])
|
53
|
+
# @article.rate(params[:stars], current_user) # or any user instance
|
54
|
+
# # update page, etc.
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# By default ratings_for will render the average rating for all users. If however you would like to display the rating for a single user, then set the :show_user_rating option to true.
|
58
|
+
# For example:
|
59
|
+
#
|
60
|
+
# <%= ratings_for @article, :show_user_rating => true %>
|
61
|
+
# Or
|
62
|
+
# <%= ratings_for @article, @user, :show_user_rating => true %>
|
63
|
+
#
|
64
|
+
# I18n:
|
65
|
+
#
|
66
|
+
# You can translate the title of the images (the tool tip that shows when the mouse is over) and the 'Currently x/x stars'
|
67
|
+
# string by setting these keys on your translation hash:
|
68
|
+
#
|
69
|
+
# ajaxful_rating:
|
70
|
+
# stars:
|
71
|
+
# current_average: "Current rating: {{average}}/{{max}}"
|
72
|
+
# title:
|
73
|
+
# one: 1 star out of {{total}}
|
74
|
+
# other: "{{count}} stars out of {{total}}"
|
75
|
+
def ratings_for(*args)
|
76
|
+
@axr_css ||= CSSBuilder.new
|
77
|
+
options = args.extract_options!.symbolize_keys.slice(:small, :remote_options,
|
78
|
+
:wrap, :show_user_rating, :dimension)
|
79
|
+
remote_options = options.delete(:remote_options) || {}
|
80
|
+
rateable = args.shift
|
81
|
+
user = args.shift || (respond_to?(:current_user) ? current_user : raise(NoUserSpecified))
|
82
|
+
StarsBuilder.new(rateable, user, self, @axr_css, options, remote_options).render
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class ActionView::Base # :nodoc:
|
88
|
+
include AjaxfulRating::Helpers
|
89
|
+
end
|
data/lib/axr/locale.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module AjaxfulRating # :nodoc:
|
2
|
+
|
3
|
+
# Customize messages by adding I18n keys:
|
4
|
+
#
|
5
|
+
# ajaxful_rating:
|
6
|
+
# helper:
|
7
|
+
# global_average: "Current rating average: {{value}} out of {{max}}"
|
8
|
+
# user_rating: "Your rating: {{value}} out of {{max}}"
|
9
|
+
module Locale
|
10
|
+
def i18n(global = true)
|
11
|
+
key = "ajaxful_rating.helper.#{global ? 'global_average' : 'user_rating'}"
|
12
|
+
default =
|
13
|
+
if global
|
14
|
+
"Current rating average: {{value}} out of {{max}}"
|
15
|
+
else
|
16
|
+
"Your rating: {{value}} out of {{max}}"
|
17
|
+
end
|
18
|
+
I18n.t(key, :value => show_value, :max => rateable.class.max_stars, :default => default)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,17 +1,11 @@
|
|
1
1
|
module AjaxfulRating # :nodoc:
|
2
|
-
|
3
|
-
def to_s
|
4
|
-
"Model has already been rated by this user. To allow update of ratings pass :allow_update => true to the ajaxful_rateable call."
|
5
|
-
end
|
6
|
-
end
|
2
|
+
include AjaxfulRating::Errors
|
7
3
|
|
8
4
|
def self.included(base)
|
9
5
|
base.extend ClassMethods
|
10
6
|
end
|
11
7
|
|
12
8
|
module ClassMethods
|
13
|
-
attr_reader :ajaxful_rating_options
|
14
|
-
|
15
9
|
# Extends the model to be easy ajaxly rateable.
|
16
10
|
#
|
17
11
|
# Options:
|
@@ -26,18 +20,28 @@ module AjaxfulRating # :nodoc:
|
|
26
20
|
def ajaxful_rateable(options = {})
|
27
21
|
has_many :rates_without_dimension, :as => :rateable, :class_name => 'Rate',
|
28
22
|
:dependent => :destroy, :conditions => {:dimension => nil}
|
29
|
-
|
23
|
+
has_many :raters_without_dimension, :through => :rates_without_dimension, :source => :rater
|
30
24
|
|
31
25
|
options[:dimensions].each do |dimension|
|
32
26
|
has_many "#{dimension}_rates", :dependent => :destroy,
|
33
27
|
:conditions => {:dimension => dimension.to_s}, :class_name => 'Rate', :as => :rateable
|
28
|
+
has_many "#{dimension}_raters", :through => "#{dimension}_rates", :source => :rater
|
34
29
|
end if options[:dimensions].is_a?(Array)
|
35
30
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
31
|
+
class << self
|
32
|
+
def axr_config
|
33
|
+
@axr_config ||= {
|
34
|
+
:stars => 5,
|
35
|
+
:allow_update => true,
|
36
|
+
:cache_column => :rating_average
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method :ajaxful_rating_options, :axr_config
|
41
|
+
end
|
42
|
+
|
43
|
+
axr_config.update(options)
|
44
|
+
|
41
45
|
include AjaxfulRating::InstanceMethods
|
42
46
|
extend AjaxfulRating::SingletonMethods
|
43
47
|
end
|
@@ -46,19 +50,15 @@ module AjaxfulRating # :nodoc:
|
|
46
50
|
def ajaxful_rater(options = {})
|
47
51
|
has_many :rates, options
|
48
52
|
end
|
49
|
-
|
50
|
-
# Maximum value accepted when rating the model. Default is 5.
|
51
|
-
#
|
52
|
-
# Change it by passing the :stars option to +ajaxful_rateable+
|
53
|
-
#
|
54
|
-
# ajaxful_rateable :stars => 10
|
55
|
-
def max_rate_value
|
56
|
-
ajaxful_rating_options[:stars]
|
57
|
-
end
|
58
53
|
end
|
59
54
|
|
60
55
|
# Instance methods for the rateable object.
|
61
56
|
module InstanceMethods
|
57
|
+
|
58
|
+
# Proxy for axr_config singleton method.
|
59
|
+
def axr_config
|
60
|
+
self.class.axr_config
|
61
|
+
end
|
62
62
|
|
63
63
|
# Submits a new rate. Accepts a hash of tipical Ajax request.
|
64
64
|
#
|
@@ -70,40 +70,61 @@ module AjaxfulRating # :nodoc:
|
|
70
70
|
# # some page update here ...
|
71
71
|
# end
|
72
72
|
def rate(stars, user, dimension = nil)
|
73
|
-
return false if (stars.to_i > self.class.
|
74
|
-
raise AlreadyRatedError if (!self.class.
|
73
|
+
return false if (stars.to_i > self.class.max_stars)
|
74
|
+
raise AlreadyRatedError if (!self.class.axr_config[:allow_update] && rated_by?(user, dimension))
|
75
75
|
|
76
|
-
rate =
|
77
|
-
rate_by(user, dimension)
|
78
|
-
rate.stars = stars
|
79
|
-
if user.respond_to?(:rates)
|
80
|
-
user.rates << rate
|
76
|
+
rate = if self.class.axr_config[:allow_update] && rated_by?(user, dimension)
|
77
|
+
rate_by(user, dimension)
|
81
78
|
else
|
82
|
-
|
83
|
-
|
79
|
+
returning rates(dimension).build do |r|
|
80
|
+
r.rater = user
|
81
|
+
end
|
82
|
+
end
|
83
|
+
rate.stars = stars
|
84
84
|
rate.save!
|
85
85
|
self.update_cached_average(dimension)
|
86
86
|
end
|
87
|
+
|
88
|
+
# Builds the DOM id attribute for the wrapper in view.
|
89
|
+
def wrapper_dom_id(dimension = nil)
|
90
|
+
prefix = "ajaxful_rating"
|
91
|
+
prefix << "_#{dimension}" unless dimension.blank?
|
92
|
+
ApplicationController.helpers.dom_id(self, prefix)
|
93
|
+
end
|
87
94
|
|
88
|
-
# Returns an array with
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
+
# Returns an array with the users that have rated this object for the
|
96
|
+
# passed dimension.
|
97
|
+
#
|
98
|
+
# It may works as an alias for +dimension_raters+ methods.
|
99
|
+
def raters(dimension = nil)
|
100
|
+
sql = "SELECT DISTINCT u.* FROM #{self.class.user_class.table_name} u "\
|
101
|
+
"INNER JOIN rates r ON u.id = r.rater_id WHERE "
|
102
|
+
|
103
|
+
sql << self.class.send(:sanitize_sql_for_conditions, {
|
104
|
+
:rateable_id => id,
|
105
|
+
:rateable_type => self.class.base_class.name,
|
106
|
+
:dimension => (dimension.to_s if dimension)
|
107
|
+
}, 'r')
|
108
|
+
|
109
|
+
self.class.user_class.find_by_sql(sql)
|
95
110
|
end
|
96
111
|
|
97
112
|
# Finds the rate made by the user if he/she has already voted.
|
98
113
|
def rate_by(user, dimension = nil)
|
99
|
-
|
100
|
-
rates(dimension).send filter, user
|
114
|
+
rates(dimension).find_by_rater_id(user.id)
|
101
115
|
end
|
102
116
|
|
103
117
|
# Return true if the user has rated the object, otherwise false
|
104
118
|
def rated_by?(user, dimension = nil)
|
105
119
|
!rate_by(user, dimension).nil?
|
106
120
|
end
|
121
|
+
|
122
|
+
# Returns whether or not the user can rate this object.
|
123
|
+
# Based on if the user has already rated the object or the
|
124
|
+
# :allow_update option is enabled.
|
125
|
+
def can_rate_by?(user, dimension = nil)
|
126
|
+
!rated_by?(user, dimension) || self.class.axr_config[:allow_update]
|
127
|
+
end
|
107
128
|
|
108
129
|
# Instance's total rates.
|
109
130
|
def total_rates(dimension = nil)
|
@@ -147,30 +168,40 @@ module AjaxfulRating # :nodoc:
|
|
147
168
|
# Updates the cached average column in the rateable model.
|
148
169
|
def update_cached_average(dimension = nil)
|
149
170
|
if self.class.caching_average?(dimension)
|
150
|
-
rates(:refresh).size if self.respond_to?(:rates_count)
|
151
171
|
update_attribute caching_column_name(dimension), self.rate_average(false, dimension)
|
152
172
|
end
|
153
173
|
end
|
154
174
|
end
|
155
175
|
|
156
176
|
module SingletonMethods
|
177
|
+
|
178
|
+
# Maximum value accepted when rating the model. Default is 5.
|
179
|
+
#
|
180
|
+
# Change it by passing the :stars option to +ajaxful_rateable+
|
181
|
+
#
|
182
|
+
# ajaxful_rateable :stars => 10
|
183
|
+
def max_stars
|
184
|
+
axr_config[:stars]
|
185
|
+
end
|
157
186
|
|
158
187
|
# Name of the class for the user model.
|
159
188
|
def user_class_name
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
189
|
+
Rate.reflect_on_association(:rater).options[:class_name]
|
190
|
+
end
|
191
|
+
|
192
|
+
# Gets the user's class
|
193
|
+
def user_class
|
194
|
+
user_class_name.constantize
|
164
195
|
end
|
165
196
|
|
166
197
|
# Finds all rateable objects rated by the +user+.
|
167
|
-
def find_rated_by(user)
|
168
|
-
find_statement(:
|
198
|
+
def find_rated_by(user, dimension = nil)
|
199
|
+
find_statement(:rater_id, user.id, dimension)
|
169
200
|
end
|
170
201
|
|
171
202
|
# Finds all rateable objects rated with +stars+.
|
172
|
-
def find_rated_with(stars)
|
173
|
-
find_statement(:stars, stars)
|
203
|
+
def find_rated_with(stars, dimension = nil)
|
204
|
+
find_statement(:stars, stars, dimension)
|
174
205
|
end
|
175
206
|
|
176
207
|
# Finds the rateable object with the highest rate average.
|
@@ -184,12 +215,16 @@ module AjaxfulRating # :nodoc:
|
|
184
215
|
end
|
185
216
|
|
186
217
|
# Finds rateable objects by Rate's attribute.
|
187
|
-
def find_statement(attr_name, attr_value)
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
218
|
+
def find_statement(attr_name, attr_value, dimension = nil)
|
219
|
+
sql = "SELECT DISTINCT r2.* FROM rates r1 INNER JOIN "\
|
220
|
+
"#{self.base_class.table_name} r2 ON r1.rateable_id = r2.id WHERE "
|
221
|
+
|
222
|
+
sql << sanitize_sql_for_conditions({
|
223
|
+
:rateable_type => self.base_class.name,
|
224
|
+
attr_name => attr_value,
|
225
|
+
:dimension => (dimension.to_s if dimension)
|
226
|
+
}, 'r1')
|
227
|
+
|
193
228
|
find_by_sql(sql)
|
194
229
|
end
|
195
230
|
|
@@ -210,7 +245,7 @@ module AjaxfulRating # :nodoc:
|
|
210
245
|
|
211
246
|
# Returns the name of the cache column for the passed dimension.
|
212
247
|
def caching_column_name(dimension = nil)
|
213
|
-
name =
|
248
|
+
name = axr_config[:cache_column].to_s
|
214
249
|
name += "_#{dimension.to_s.underscore}" unless dimension.blank?
|
215
250
|
name
|
216
251
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module AjaxfulRating # :nodoc:
|
2
|
+
class StarsBuilder # :nodoc:
|
3
|
+
include AjaxfulRating::Locale
|
4
|
+
|
5
|
+
attr_reader :rateable, :user, :options, :remote_options
|
6
|
+
|
7
|
+
def initialize(rateable, user_or_static, template, css_builder, options = {}, remote_options = {})
|
8
|
+
@user = user_or_static unless user_or_static == :static
|
9
|
+
@rateable, @template, @css_builder = rateable, template, css_builder
|
10
|
+
apply_stars_builder_options!(options, remote_options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def show_value
|
14
|
+
if options[:show_user_rating]
|
15
|
+
rate = rateable.rate_by(user, options[:dimension])
|
16
|
+
rate ? rate.stars : 0
|
17
|
+
else
|
18
|
+
rateable.rate_average(true, options[:dimension])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def render
|
23
|
+
options[:wrap] ? wrapper_tag : ratings_tag
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def apply_stars_builder_options!(options, remote_options)
|
29
|
+
@options = {
|
30
|
+
:wrap => true,
|
31
|
+
:small => false,
|
32
|
+
:show_user_rating => false
|
33
|
+
}.merge(options)
|
34
|
+
|
35
|
+
@options[:small] = @options[:small].to_s == 'true'
|
36
|
+
@options[:show_user_rating] = @options[:show_user_rating].to_s == 'true'
|
37
|
+
@options[:wrap] = @options[:wrap].to_s == 'true'
|
38
|
+
|
39
|
+
@remote_options = {
|
40
|
+
:url => nil,
|
41
|
+
:method => :post
|
42
|
+
}.merge(remote_options)
|
43
|
+
|
44
|
+
if @remote_options[:url].nil?
|
45
|
+
rateable_name = ActionController::RecordIdentifier.singular_class_name(rateable)
|
46
|
+
url = "rate_#{rateable_name}_path"
|
47
|
+
if @template.respond_to?(url)
|
48
|
+
@remote_options[:url] = @template.send(url, rateable)
|
49
|
+
else
|
50
|
+
raise(MissingRateRoute)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def ratings_tag
|
56
|
+
stars = []
|
57
|
+
width = (show_value / rateable.class.max_stars.to_f) * 100
|
58
|
+
li_class = "axr-#{show_value}-#{rateable.class.max_stars}".gsub('.', '_')
|
59
|
+
@css_builder.rule('.ajaxful-rating', :width => (rateable.class.max_stars * 25))
|
60
|
+
@css_builder.rule('.ajaxful-rating.small',
|
61
|
+
:width => (rateable.class.max_stars * 10)) if options[:small]
|
62
|
+
|
63
|
+
stars << @template.content_tag(:li, i18n, :class => "show-value",
|
64
|
+
:style => "width: #{width}%")
|
65
|
+
stars += (1..rateable.class.max_stars).map do |i|
|
66
|
+
star_tag(i)
|
67
|
+
end
|
68
|
+
@template.content_tag(:ul, stars.join, :class => "ajaxful-rating#{' small' if options[:small]}")
|
69
|
+
end
|
70
|
+
|
71
|
+
def star_tag(value)
|
72
|
+
already_rated = rateable.rated_by?(user, options[:dimension]) if user
|
73
|
+
css_class = "stars-#{value}"
|
74
|
+
@css_builder.rule(".ajaxful-rating .#{css_class}", {
|
75
|
+
:width => "#{(value / rateable.class.max_stars.to_f) * 100}%",
|
76
|
+
:zIndex => (rateable.class.max_stars + 2 - value).to_s
|
77
|
+
})
|
78
|
+
|
79
|
+
@template.content_tag(:li) do
|
80
|
+
if user && (!already_rated || rateable.axr_config[:allow_update])
|
81
|
+
link_star_tag(value, css_class)
|
82
|
+
else
|
83
|
+
@template.content_tag(:span, show_value, :class => css_class, :title => i18n)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def link_star_tag(value, css_class)
|
89
|
+
query = {
|
90
|
+
:stars => value,
|
91
|
+
:dimension => options[:dimension],
|
92
|
+
:small => options[:small],
|
93
|
+
:show_user_rating => options[:show_user_rating]
|
94
|
+
}.to_query
|
95
|
+
config = {
|
96
|
+
:html => {
|
97
|
+
:class => css_class,
|
98
|
+
:title => i18n(false)
|
99
|
+
},
|
100
|
+
:url => "#{remote_options[:url]}",
|
101
|
+
:with => "'#{query}'"
|
102
|
+
}
|
103
|
+
@template.link_to_remote(value, remote_options.merge(config))
|
104
|
+
end
|
105
|
+
|
106
|
+
def wrapper_tag
|
107
|
+
@template.content_tag(:div, ratings_tag, :class => "ajaxful-rating-wrapper",
|
108
|
+
:id => rateable.wrapper_dom_id(options[:dimension]))
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ajaxful_rating
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 2
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 2.2.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Edgar J. Suarez
|
@@ -9,7 +14,7 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-03-07 00:00:00 -06:00
|
13
18
|
default_executable:
|
14
19
|
dependencies: []
|
15
20
|
|
@@ -23,8 +28,12 @@ extra_rdoc_files:
|
|
23
28
|
- CHANGELOG
|
24
29
|
- README.textile
|
25
30
|
- lib/ajaxful_rating.rb
|
26
|
-
- lib/
|
27
|
-
- lib/
|
31
|
+
- lib/axr/css_builder.rb
|
32
|
+
- lib/axr/errors.rb
|
33
|
+
- lib/axr/helpers.rb
|
34
|
+
- lib/axr/locale.rb
|
35
|
+
- lib/axr/model.rb
|
36
|
+
- lib/axr/stars_builder.rb
|
28
37
|
files:
|
29
38
|
- CHANGELOG
|
30
39
|
- Manifest
|
@@ -40,8 +49,12 @@ files:
|
|
40
49
|
- generators/ajaxful_rating/templates/style.css
|
41
50
|
- init.rb
|
42
51
|
- lib/ajaxful_rating.rb
|
43
|
-
- lib/
|
44
|
-
- lib/
|
52
|
+
- lib/axr/css_builder.rb
|
53
|
+
- lib/axr/errors.rb
|
54
|
+
- lib/axr/helpers.rb
|
55
|
+
- lib/axr/locale.rb
|
56
|
+
- lib/axr/model.rb
|
57
|
+
- lib/axr/stars_builder.rb
|
45
58
|
has_rdoc: true
|
46
59
|
homepage: http://github.com/edgarjs/ajaxful-rating
|
47
60
|
licenses: []
|
@@ -60,18 +73,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
60
73
|
requirements:
|
61
74
|
- - ">="
|
62
75
|
- !ruby/object:Gem::Version
|
76
|
+
segments:
|
77
|
+
- 0
|
63
78
|
version: "0"
|
64
|
-
version:
|
65
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
80
|
requirements:
|
67
81
|
- - ">="
|
68
82
|
- !ruby/object:Gem::Version
|
83
|
+
segments:
|
84
|
+
- 1
|
85
|
+
- 2
|
69
86
|
version: "1.2"
|
70
|
-
version:
|
71
87
|
requirements: []
|
72
88
|
|
73
89
|
rubyforge_project: ajaxful_rating
|
74
|
-
rubygems_version: 1.3.
|
90
|
+
rubygems_version: 1.3.6
|
75
91
|
signing_key:
|
76
92
|
specification_version: 3
|
77
93
|
summary: Provides a simple way to add rating functionality to your application.
|
@@ -1,195 +0,0 @@
|
|
1
|
-
module AjaxfulRating # :nodoc:
|
2
|
-
module Helper
|
3
|
-
class MissingRateRoute < StandardError
|
4
|
-
def to_s
|
5
|
-
"Add :member => {:rate => :post} to your routes, or specify a custom url in the options."
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
# Generates the stars list to submit a rate.
|
10
|
-
#
|
11
|
-
# It accepts the next options:
|
12
|
-
# * <tt>:class</tt> CSS class for the ul. Default is 'ajaxful-rating'.
|
13
|
-
# * <tt>:link_class_prefix</tt> Prefix for the li a CSS class. Default is 'stars'.
|
14
|
-
# * <tt>:small_stars</tt> Set this param to true to display smaller images. Default is false.
|
15
|
-
# * <tt>:small_star_class</tt> CSS class for the list when using small images. Default is 'small-stars'.
|
16
|
-
# * <tt>:html</tt> Hash of options to customise the ul tag.
|
17
|
-
# * <tt>:remote_options</tt> Hash of options for the link_to_remote function.
|
18
|
-
# Default is {:method => :post, :url => rate_rateablemodel_path(rateable)}.
|
19
|
-
# * <tt>:wrap</tt> Whether the star list is wrapped within a div tag or not. This is useful when page updating. Default is true.
|
20
|
-
# * <tt>:force_dynamic</tt> Whether the star list is always clickable. This is useful for page caching when set to true. Default is false.
|
21
|
-
#
|
22
|
-
# Example:
|
23
|
-
# <%= ratings_for @article %>
|
24
|
-
# # => Will produce something like:
|
25
|
-
# <ul class="ajaxful-rating">
|
26
|
-
# <li class="current-rating" style="width: 60%;">Currently 3/5 stars</li>
|
27
|
-
# <li><%= link_to_remote 1, :url => rate_article_path(@article, :stars => 1), :method => :post, :html => {:class => 'stars-1', :title => '1 star out of 5'} %></li>
|
28
|
-
# <li><%= link_to_remote 2, :url => rate_article_path(@article, :stars => 2), :method => :post, :html => {:class => 'stars-2', :title => '2 stars out of 5'} %></li>
|
29
|
-
# <li><%= link_to_remote 3, :url => rate_article_path(@article, :stars => 3), :method => :post, :html => {:class => 'stars-3', :title => '3 stars out of 5'} %></li>
|
30
|
-
# <li><%= link_to_remote 4, :url => rate_article_path(@article, :stars => 4), :method => :post, :html => {:class => 'stars-4', :title => '4 stars out of 5'} %></li>
|
31
|
-
# <li><%= link_to_remote 5, :url => rate_article_path(@article, :stars => 5), :method => :post, :html => {:class => 'stars-5', :title => '5 stars out of 5'} %></li>
|
32
|
-
# </ul>
|
33
|
-
#
|
34
|
-
# It will try to use the method <tt>current_user</tt> as the user instance. You can specify a custom instance in the second parameter
|
35
|
-
# or pass <tt>:static</tt> to leave the list of stars static.
|
36
|
-
#
|
37
|
-
# Example:
|
38
|
-
# <%= ratings_for @article, @user, :small_stars => true %>
|
39
|
-
# # => Will use @user instead <tt>current_user</tt>
|
40
|
-
#
|
41
|
-
# <%= ratings_for @article, :static, :small_stars => true %>
|
42
|
-
# # => Will produce a static list of stars showing the current rating average for @article.
|
43
|
-
#
|
44
|
-
# The user passed here will *not* be the one who submits the rate. It will be used only for the display behavior of the stars.
|
45
|
-
# Like for example, if there is a user logged in or if the current logged in user is able to submit a rate depending on the
|
46
|
-
# configuration (accepts update of rates, etc).
|
47
|
-
#
|
48
|
-
# So to actually set the user who will rate the model you need to do it in your controller:
|
49
|
-
#
|
50
|
-
# # controller
|
51
|
-
# def rate
|
52
|
-
# @article = Article.find(params[:id])
|
53
|
-
# @article.rate(params[:stars], current_user) # or any user instance
|
54
|
-
# # update page, etc.
|
55
|
-
# end
|
56
|
-
#
|
57
|
-
# By default ratings_for will render the average rating for all users. If however you would like to display the rating for a single user, then set the :show_user_rating option to true.
|
58
|
-
# For example:
|
59
|
-
#
|
60
|
-
# <%= ratings_for @article, :show_user_rating => true %>
|
61
|
-
# Or
|
62
|
-
# <%= ratings_for @article, @user, :show_user_rating => true %>
|
63
|
-
#
|
64
|
-
# I18n:
|
65
|
-
#
|
66
|
-
# You can translate the title of the images (the tool tip that shows when the mouse is over) and the 'Currently x/x stars'
|
67
|
-
# string by setting these keys on your translation hash:
|
68
|
-
#
|
69
|
-
# ajaxful_rating:
|
70
|
-
# stars:
|
71
|
-
# current_average: "Current rating: {{average}}/{{max}}"
|
72
|
-
# title:
|
73
|
-
# one: 1 star out of {{total}}
|
74
|
-
# other: "{{count}} stars out of {{total}}"
|
75
|
-
def ratings_for(rateable, *args)
|
76
|
-
user = extract_options(rateable, *args)
|
77
|
-
user_rating = if ajaxful_rating_options[:show_user_rating] == true and rateable.rated_by?(user, ajaxful_rating_options[:dimension])
|
78
|
-
rateable.rates(ajaxful_rating_options[:dimension]).find_by_user_id(user).stars
|
79
|
-
else
|
80
|
-
user_rating = 0
|
81
|
-
end
|
82
|
-
ajaxful_styles[ajaxful_rating_options[:class]] ||= ".#{ajaxful_rating_options[:class]} { width: #{rateable.class.max_rate_value * 25}px; }"
|
83
|
-
ajaxful_styles[ajaxful_rating_options[:small_star_class]] ||= ".#{ajaxful_rating_options[:class]}.#{ajaxful_rating_options[:small_star_class]} { width: #{rateable.class.max_rate_value * 10}px; }"
|
84
|
-
width = ((ajaxful_rating_options[:show_user_rating] == true ? user_rating : rateable.rate_average(true, ajaxful_rating_options[:dimension])) / rateable.class.max_rate_value.to_f) * 100
|
85
|
-
ul = content_tag(:ul, ajaxful_rating_options[:html]) do
|
86
|
-
(1..rateable.class.max_rate_value).collect do |i|
|
87
|
-
build_star rateable, user, i
|
88
|
-
end.insert(0, content_tag(:li, current_average(rateable), :class => 'current-rating', :style => "width:#{width}%")).join
|
89
|
-
end
|
90
|
-
if ajaxful_rating_options[:wrap]
|
91
|
-
content_tag(:div, ul, :class => 'ajaxful-rating-wrapper', :id => "ajaxful-rating-#{!ajaxful_rating_options[:dimension].blank? ?
|
92
|
-
"#{ajaxful_rating_options[:dimension]}-" : ''}#{rateable.class.name.tableize.singularize}-#{rateable.id}")
|
93
|
-
else
|
94
|
-
ul
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# Call this method <strong>within head tags</strong> of the main layout to yield the dynamic styles.
|
99
|
-
# It will include the necessary stlyesheet and output the dynamic CSS.
|
100
|
-
#
|
101
|
-
# Example:
|
102
|
-
# <head>
|
103
|
-
# <%= ajaxful_rating_style %>
|
104
|
-
# </head>
|
105
|
-
def ajaxful_rating_style
|
106
|
-
stylesheet_link_tag('ajaxful_rating') + content_tag(:style, ajaxful_styles.values.join("\n"),
|
107
|
-
:type => 'text/css') unless ajaxful_styles.blank?
|
108
|
-
end
|
109
|
-
|
110
|
-
private
|
111
|
-
|
112
|
-
# Builds a star
|
113
|
-
def build_star(rateable, user, i)
|
114
|
-
a_class = "#{ajaxful_rating_options[:link_class_prefix]}-#{i}"
|
115
|
-
selector = ".#{ajaxful_rating_options[:class]} .#{a_class}"
|
116
|
-
ajaxful_styles[selector] ||= <<-EOS
|
117
|
-
#{selector} {
|
118
|
-
width: #{(i / rateable.class.max_rate_value.to_f) * 100}%;
|
119
|
-
z-index: #{rateable.class.max_rate_value + 2 - i};
|
120
|
-
}
|
121
|
-
EOS
|
122
|
-
rated = rateable.rated_by?(user, ajaxful_rating_options[:dimension]) if user
|
123
|
-
star = if ajaxful_rating_options[:force_dynamic] || (user && ((rated && rateable.class.ajaxful_rating_options[:allow_update]) || !rated))
|
124
|
-
link_to_remote(i, build_remote_options({:class => a_class, :title => pluralize_title(i, rateable.class.max_rate_value)}, i))
|
125
|
-
else
|
126
|
-
content_tag(:span, i, :class => a_class, :title => current_average(rateable))
|
127
|
-
end
|
128
|
-
content_tag(:li, star)
|
129
|
-
end
|
130
|
-
|
131
|
-
# Default options for the helper.
|
132
|
-
def ajaxful_rating_options
|
133
|
-
@ajaxful_rating_options ||= {
|
134
|
-
:wrap => true,
|
135
|
-
:force_dynamic => false,
|
136
|
-
:class => 'ajaxful-rating',
|
137
|
-
:link_class_prefix => :stars,
|
138
|
-
:small_stars => false,
|
139
|
-
:small_star_class => 'small-star',
|
140
|
-
:html => {},
|
141
|
-
:remote_options => {:method => :post}
|
142
|
-
}
|
143
|
-
end
|
144
|
-
|
145
|
-
# Builds the proper title for the star.
|
146
|
-
def pluralize_title(current, max)
|
147
|
-
(current == 1) ? I18n.t('ajaxful_rating.stars.title.one', :max => max, :default => "1 star out of {{max}}") :
|
148
|
-
I18n.t('ajaxful_rating.stars.title.other', :count => current, :max => max, :default => "{{count}} stars out of {{max}}")
|
149
|
-
end
|
150
|
-
|
151
|
-
# Returns the current average string.
|
152
|
-
def current_average(rateable)
|
153
|
-
I18n.t('ajaxful_rating.stars.current_average', :average => rateable.rate_average(true, ajaxful_rating_options[:dimension]),
|
154
|
-
:max => rateable.class.max_rate_value, :default => "Current rating: {{average}}/{{max}}")
|
155
|
-
end
|
156
|
-
|
157
|
-
# Temporary instance to hold dynamic styles.
|
158
|
-
def ajaxful_styles
|
159
|
-
@ajaxful_styles ||= {}
|
160
|
-
end
|
161
|
-
|
162
|
-
# Builds the default options for the link_to_remote function.
|
163
|
-
def build_remote_options(html, i)
|
164
|
-
ajaxful_rating_options[:remote_options].reverse_merge(:html => html).merge(
|
165
|
-
:url => "#{ajaxful_rating_options[:remote_options][:url]}?#{{:stars => i, :dimension => ajaxful_rating_options[:dimension], :small_stars => ajaxful_rating_options[:small_stars]}.to_query}")
|
166
|
-
end
|
167
|
-
|
168
|
-
# Extracts the hash options and returns the user instance.
|
169
|
-
def extract_options(rateable, *args)
|
170
|
-
ajaxful_rating_options[:show_user_rating] = false # Reset
|
171
|
-
user = if args.first.class.name == rateable.class.user_class_name.classify
|
172
|
-
args.shift
|
173
|
-
elsif args.first != :static
|
174
|
-
current_user if respond_to?(:current_user)
|
175
|
-
end
|
176
|
-
config = (!args.empty? && args.last.is_a?(Hash)) ? args.last : {}
|
177
|
-
if config[:remote_options] && config[:remote_options][:url]
|
178
|
-
# we keep the passed url
|
179
|
-
else#if user
|
180
|
-
config[:remote_options] = {
|
181
|
-
:url => respond_to?(url = "rate_#{rateable.class.name.tableize.singularize}_path") ?
|
182
|
-
send(url, rateable) : raise(MissingRateRoute)
|
183
|
-
}
|
184
|
-
end
|
185
|
-
config[:small_stars] = (config[:small_stars].downcase == "true") if config[:small_stars].is_a?(String)
|
186
|
-
ajaxful_rating_options.merge!(config)
|
187
|
-
ajaxful_rating_options[:html].reverse_merge!(:class => "#{ajaxful_rating_options[:class]} #{ajaxful_rating_options[:small_star_class] if ajaxful_rating_options[:small_stars]}")
|
188
|
-
user
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
class ActionView::Base
|
194
|
-
include AjaxfulRating::Helper
|
195
|
-
end
|