ajaxful_rating 2.1.5 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|