ajaxful_rating_jquery 2.2.9
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +54 -0
- data/Manifest +20 -0
- data/README.textile +237 -0
- data/Rakefile +15 -0
- data/ajaxful_rating_jquery.gemspec +30 -0
- data/generators/ajaxful_rating/USAGE +5 -0
- data/generators/ajaxful_rating/ajaxful_rating_generator.rb +31 -0
- data/generators/ajaxful_rating/templates/images/star.png +0 -0
- data/generators/ajaxful_rating/templates/images/star_medium.png +0 -0
- data/generators/ajaxful_rating/templates/images/star_small.png +0 -0
- data/generators/ajaxful_rating/templates/migration.rb +18 -0
- data/generators/ajaxful_rating/templates/model.rb +6 -0
- data/generators/ajaxful_rating/templates/style.css +99 -0
- data/init.rb +1 -0
- data/lib/ajaxful_rating_jquery.rb +6 -0
- data/lib/axr/css_builder.rb +30 -0
- data/lib/axr/errors.rb +27 -0
- data/lib/axr/helpers.rb +150 -0
- data/lib/axr/locale.rb +30 -0
- data/lib/axr/model.rb +264 -0
- data/lib/axr/stars_builder.rb +112 -0
- metadata +101 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
== 2.2.9 Sept 30, 2010
|
2
|
+
* Released as a separate ajaxful_rating_jquery gem.
|
3
|
+
|
4
|
+
== 2.2.8.1 Jul 02, 2010
|
5
|
+
* Call html_safe only when it's available.
|
6
|
+
|
7
|
+
== 2.2.8 Jun 14, 2010
|
8
|
+
* Fix html for <li> marking it as html_safe when using rails_xss plugin
|
9
|
+
|
10
|
+
== 2.2.7 Jun 12, 2010
|
11
|
+
* Fix generated html marking it as html_safe when using rails_xss plugin
|
12
|
+
|
13
|
+
== 2.2.6 May 27, 2010
|
14
|
+
* Fix wrapper_dom_id with false values for keys
|
15
|
+
|
16
|
+
== 2.2.5 May 21, 2010
|
17
|
+
* Fix wrapper_dom_id with empty values
|
18
|
+
|
19
|
+
== 2.2.4 April 15, 2010
|
20
|
+
* Fix wrapper_dom_id join options
|
21
|
+
|
22
|
+
== 2.2.3 March 10, 2010
|
23
|
+
* Fix validation of current_user to show linked stars
|
24
|
+
|
25
|
+
== 2.2.2 March 9, 2010
|
26
|
+
* Fix bug for jRuby
|
27
|
+
* Fixed user self relational model to be rater and rateable.
|
28
|
+
|
29
|
+
== 2.2.1 March 8, 2010
|
30
|
+
* Changed :force_dynamic for its opposite :force_static.
|
31
|
+
* Fixed I18n texts.
|
32
|
+
* Fixed missed quotes for Rate belongs_to association with User class
|
33
|
+
* Detailed wrapper DOM id with passed hash.
|
34
|
+
|
35
|
+
== 2.2.0 March 7, 2010
|
36
|
+
* Improved model methods and options.
|
37
|
+
* Works now with inherited models.
|
38
|
+
* Removed HTML and CSS options for helper for sake of simpleness.
|
39
|
+
* Renamed helper option :small_stars to :small.
|
40
|
+
* Changed whole helper approach. It should work the same as before.
|
41
|
+
(Except for the renamed and removed options)
|
42
|
+
* Removed :force_dynamic, you should exclude the helper from cache since it uses
|
43
|
+
authorization.
|
44
|
+
* Fixed opened bugs so far.
|
45
|
+
|
46
|
+
== 2.1.5 January 28, 2010
|
47
|
+
* Renamed options method name to avoid collapse.
|
48
|
+
* Removed CSS duplication.
|
49
|
+
|
50
|
+
== 2.1.4 January 25, 2010
|
51
|
+
* Added option for showing current_user's rate instead of global average
|
52
|
+
|
53
|
+
== 2.1.0 July 25, 2009
|
54
|
+
* AjaxfulRating is now available as a gem
|
data/Manifest
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
Manifest
|
3
|
+
README.textile
|
4
|
+
Rakefile
|
5
|
+
generators/ajaxful_rating/USAGE
|
6
|
+
generators/ajaxful_rating/ajaxful_rating_generator.rb
|
7
|
+
generators/ajaxful_rating/templates/images/star.png
|
8
|
+
generators/ajaxful_rating/templates/images/star_medium.png
|
9
|
+
generators/ajaxful_rating/templates/images/star_small.png
|
10
|
+
generators/ajaxful_rating/templates/migration.rb
|
11
|
+
generators/ajaxful_rating/templates/model.rb
|
12
|
+
generators/ajaxful_rating/templates/style.css
|
13
|
+
init.rb
|
14
|
+
lib/ajaxful_rating_jquery.rb
|
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
ADDED
@@ -0,0 +1,237 @@
|
|
1
|
+
h1. Ajaxful Rating
|
2
|
+
|
3
|
+
Provides a simple way to add rating functionality to your application. This fork uses jQuery instead of prototype and uses unobtrusive javascript. Currently, it only supports Rails 2.3.x.
|
4
|
+
|
5
|
+
!http://s3.amazonaws.com/ember/v9SvvO3rdSkA40e1sXBf8JgpuaWCC0uB_o.png!
|
6
|
+
|
7
|
+
h2. Repository
|
8
|
+
|
9
|
+
Find it at "github.com/kamui/ajaxful_rating_jquery":http://github.com/kamui/ajaxful_rating_jquery
|
10
|
+
|
11
|
+
The original repository is located at "github.com/edgarjs/ajaxful-rating":http://github.com/edgarjs/ajaxful-rating
|
12
|
+
|
13
|
+
h2. Demo
|
14
|
+
|
15
|
+
I don't have a working demo up of my form but you can see the original version's demo app at "http://github.com/edgarjs/ajaxful-rating_demo_app":http://github.com/edgarjs/ajaxful-rating_demo_app
|
16
|
+
Just migrate and run...
|
17
|
+
|
18
|
+
Or view it live: "http://axr.heroku.com":http://axr.heroku.com
|
19
|
+
|
20
|
+
*******************************************************************
|
21
|
+
|
22
|
+
h2. Instructions
|
23
|
+
|
24
|
+
h3. Install
|
25
|
+
|
26
|
+
To install the gem run the next command:
|
27
|
+
|
28
|
+
@gem install ajaxful_rating_jquery@
|
29
|
+
|
30
|
+
You can configure it in your environment.rb file also:
|
31
|
+
|
32
|
+
@config.gem "ajaxful_rating_jquery"@
|
33
|
+
|
34
|
+
h3. Generate
|
35
|
+
|
36
|
+
@script/generate ajaxful_rating UserModelName@
|
37
|
+
|
38
|
+
The generator takes one argument: UserModelName, which is the name of your *current*
|
39
|
+
user model. This is necessary to link both the rate and user models.
|
40
|
+
|
41
|
+
Also this generator copies the necessary images, styles, etc.
|
42
|
+
|
43
|
+
Example:
|
44
|
+
_I suppose you have generated already an authenticated model..._
|
45
|
+
|
46
|
+
<pre>
|
47
|
+
script/generate authenticated user sessions
|
48
|
+
script/generate ajaxful_rating user
|
49
|
+
</pre>
|
50
|
+
|
51
|
+
So this call will create a Rate model and will link it to your User model.
|
52
|
+
|
53
|
+
h3. Prepare
|
54
|
+
|
55
|
+
To let a model be rateable just add @ajaxful_rateable@. You can pass a hash of options to
|
56
|
+
customise this call:
|
57
|
+
* @:stars@ Max number of stars that can be submitted.
|
58
|
+
* @:allow_update@ Set to true if you want users to be able to update their votes.
|
59
|
+
* @:cache_column@ Name of the column for storing the cached rating average.
|
60
|
+
* @:dimensions@ Array of dimensions. Allows to rate the model on various specs,
|
61
|
+
like for example: a car could be rated for its speed, beauty or price.
|
62
|
+
|
63
|
+
<pre>
|
64
|
+
class Car < ActiveRecord::Base
|
65
|
+
ajaxful_rateable :stars => 10, :dimensions => [:speed, :beauty, :price]
|
66
|
+
end
|
67
|
+
</pre>
|
68
|
+
|
69
|
+
Then you need to add a call @ajaxful_rater@ in the user model to make your @User@ model able to rate objects.
|
70
|
+
|
71
|
+
<pre>
|
72
|
+
class User < ActiveRecord::Base
|
73
|
+
ajaxful_rater
|
74
|
+
end
|
75
|
+
</pre>
|
76
|
+
|
77
|
+
Finally, as a mere recommendation to make it even easier, modify your routes to
|
78
|
+
map a rate action:
|
79
|
+
|
80
|
+
@map.resources :cars, :member => {:rate => :post}@
|
81
|
+
|
82
|
+
h3. Use it
|
83
|
+
|
84
|
+
To add the star links you need to call the helper method @ratings_for@.
|
85
|
+
It tries to call @current_user@ method as the rater instance. You can pass @:static@
|
86
|
+
as the second param to display only the static stars (not clickables).
|
87
|
+
And also you can pass the dimension you want to show the ratings for.
|
88
|
+
|
89
|
+
<pre>
|
90
|
+
#show.html.erb
|
91
|
+
<%= ratings_for @article %>
|
92
|
+
|
93
|
+
#To display static stars:
|
94
|
+
<%= ratings_for @article, :static %>
|
95
|
+
|
96
|
+
#To display the ratings for a dimension:
|
97
|
+
<%= ratings_for @article, :dimension => :speed %>
|
98
|
+
</pre>
|
99
|
+
|
100
|
+
Or you can specify a custom user instance by passing it as parameter.
|
101
|
+
|
102
|
+
<pre>
|
103
|
+
<%= ratings_for @article, @user %>
|
104
|
+
</pre>
|
105
|
+
|
106
|
+
By default ratings_for will display the average user rating. If you would like it to
|
107
|
+
display the rating for the current_user, then set the :show_user_rating parameter to true.
|
108
|
+
For example:
|
109
|
+
|
110
|
+
<pre>
|
111
|
+
# To display the rating for the current user (current_user):
|
112
|
+
<%= ratings_for @article, :show_user_rating => true %>
|
113
|
+
|
114
|
+
# To change the size of the stars you can also specify an optional :size value. If none is set it uses the large size, otherwise you can specify medium or small:
|
115
|
+
<%= ratings_for @article, :size => "medium" %>
|
116
|
+
|
117
|
+
# To display the rating for the user specified by @user:
|
118
|
+
<%= ratings_for @article, @user, :show_user_rating => true %>
|
119
|
+
</pre>
|
120
|
+
|
121
|
+
There's a condition here, if you didn't add the route @rate@ to your resource
|
122
|
+
(as shown above) or you named it different, you'll need to pass the url to the
|
123
|
+
correct action in your controller:
|
124
|
+
|
125
|
+
<pre>
|
126
|
+
<%= ratings_for @article, :url => your_rate_path(@article) %>
|
127
|
+
</pre>
|
128
|
+
|
129
|
+
+h3. Important!
|
130
|
+
|
131
|
+
*To display the stars properly you need to add a call in the head of your layout, which will generate the
|
132
|
+
required CSS style for the list. Also don't forget to include jQ--uery.*
|
133
|
+
|
134
|
+
It's also important to note that this call MUST be within your head tags in your layout, as for now it seems to doesn't work with the @content_for@ tag.
|
135
|
+
|
136
|
+
<pre>
|
137
|
+
#within the head tags of your layout...
|
138
|
+
<%= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" %>
|
139
|
+
<%= ajaxful_rating_style %>
|
140
|
+
<%= ajaxful_rating_script %>
|
141
|
+
</pre>
|
142
|
+
|
143
|
+
When a user submits a rating it will call the action in your controller, for
|
144
|
+
example (if you added the @rate@ route):
|
145
|
+
|
146
|
+
<pre>
|
147
|
+
def rate
|
148
|
+
@car = Car.find(params[:id])
|
149
|
+
@car.rate(params[:stars], current_user, params[:dimension])
|
150
|
+
average = @product.rate_average(true, params[:dimension])
|
151
|
+
width = (average / @car.class.max_stars.to_f) * 100
|
152
|
+
render :json => {:id => @car.wrapper_dom_id(params), :average => average, :width => width}
|
153
|
+
end
|
154
|
+
</pre>
|
155
|
+
|
156
|
+
There are some more options for this helper, please see the rdoc for details.
|
157
|
+
|
158
|
+
h3. Dimensions
|
159
|
+
|
160
|
+
From now on you can pass an optional parameter to the @rates@ method for your rateable object to retrieve the
|
161
|
+
corresponding rates for the dimension you want.
|
162
|
+
|
163
|
+
For example, you defined these dimensions:
|
164
|
+
|
165
|
+
<pre>
|
166
|
+
class Car < ActiveRecord::Base
|
167
|
+
ajaxful_rateable :dimensions => [:speed, :beauty, :price]
|
168
|
+
end
|
169
|
+
</pre>
|
170
|
+
|
171
|
+
And hence you can call @car.rates(:price)@ for the price rates or @car.rates(:speed)@ for the speed ratings and so on.
|
172
|
+
|
173
|
+
h3. Namespaces
|
174
|
+
|
175
|
+
If you use the plugin inside a namespace you’ll need to specify the rating url which should points to
|
176
|
+
a controller inside a namespace. Your files should be like these:
|
177
|
+
|
178
|
+
<pre>
|
179
|
+
routes.rb:
|
180
|
+
map.namespace :admin do |admin|
|
181
|
+
admin.resources :articles, :member => {:rate => :post}
|
182
|
+
end
|
183
|
+
|
184
|
+
views/admin/articles/show.html.erb
|
185
|
+
<%= ratings_for @article, :url => rate_admin_article_path(@article) %>
|
186
|
+
</pre>
|
187
|
+
|
188
|
+
h3. Cache
|
189
|
+
|
190
|
+
To cache the model's rating average add a column named @rating_average@ to your model table:
|
191
|
+
|
192
|
+
<pre>
|
193
|
+
class AddRatingAverageToArticles < ActiveRecord::Migration
|
194
|
+
def self.up
|
195
|
+
add_column :articles, :rating_average, :decimal, :default => 0, :precision => 6, :scale => 2
|
196
|
+
end
|
197
|
+
|
198
|
+
def self.down
|
199
|
+
remove_column :articles, :rating_average
|
200
|
+
end
|
201
|
+
end
|
202
|
+
</pre>
|
203
|
+
|
204
|
+
If you want to customize the name of the cache column just pass it in the options hash:
|
205
|
+
|
206
|
+
<pre>
|
207
|
+
class Article < ActiveRecord::Base
|
208
|
+
ajaxful_rateable :cache_column => :my_cached_rating
|
209
|
+
end
|
210
|
+
</pre>
|
211
|
+
|
212
|
+
To use caching with dimensions, make sure you have a cache column defined for each dimension you want cached.
|
213
|
+
So if you want to cache the @spelling@ dimension, you’ll need to have a column called @rating_average_spelling@ on the articles table.
|
214
|
+
If you use a custom cache column name, follow the pattern @cache_column_name_dimension_name@ to add cache columns for dimensions.
|
215
|
+
|
216
|
+
h2. Feedback
|
217
|
+
|
218
|
+
If you find bugs please open a ticket at "http://github.com/kamui/ajaxful_rating_jquery/issues":http://github.com/kamui/ajaxful_rating_jquery/issues
|
219
|
+
|
220
|
+
I'll really appreciate your feedback, please contact me at kamuigt[at]gmail[dot]com
|
221
|
+
|
222
|
+
h2. Credits
|
223
|
+
|
224
|
+
The original developer of ajaxify_rating, "Edgar J. Suarez":http://github.com/edgarjs
|
225
|
+
|
226
|
+
The helper's style is from "komodomedia":http://www.komodomedia.com/blog/2007/01/css-star-rating-redux/ with author's permission.
|
227
|
+
|
228
|
+
If you need the psd files of the stars you can grab them "here":http://aws3-edgarjs-zips.s3.amazonaws.com/ajaxful_rating_stars.zip
|
229
|
+
|
230
|
+
Thanks to "bborn":http://github.com/bborn for the dimensions base implementation.
|
231
|
+
|
232
|
+
h2. License
|
233
|
+
|
234
|
+
This code is released under Creative Commons Attribution-Share Alike 3.0 license.
|
235
|
+
|
236
|
+
!http://i.creativecommons.org/l/by-sa/3.0/88x31.png!:http://creativecommons.org/licenses/by-sa/3.0/
|
237
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('ajaxful_rating_jquery', '2.2.9') do |p|
|
6
|
+
p.summary = "Add star rating functionality to your Rails 2.3.x application. Requires jQuery."
|
7
|
+
p.description = "Provides a simple way to add rating functionality to your application. This is a fork of ajaxful_ratings that works with jQuery instead of Prototype and uses unobtrusive javascript instead of link_to_remote."
|
8
|
+
p.url = "http://github.com/kamui/ajaxful_rating_jquery"
|
9
|
+
p.author = "Jack Chu, Edgar J. Suarez"
|
10
|
+
p.email = "kamuigt@gmail.com"
|
11
|
+
p.ignore_pattern = ["tmp/*", "script/*"]
|
12
|
+
p.development_dependencies = []
|
13
|
+
end
|
14
|
+
|
15
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{ajaxful_rating_jquery}
|
5
|
+
s.version = "2.2.9"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Jack Chu, Edgar J. Suarez"]
|
9
|
+
s.date = %q{2010-09-30}
|
10
|
+
s.description = %q{Provides a simple way to add rating functionality to your application. This is a fork of ajaxful_ratings that works with jQuery instead of Prototype and uses unobtrusive javascript instead of link_to_remote.}
|
11
|
+
s.email = %q{kamuigt@gmail.com}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "README.textile", "lib/ajaxful_rating_jquery.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", "generators/ajaxful_rating/USAGE", "generators/ajaxful_rating/ajaxful_rating_generator.rb", "generators/ajaxful_rating/templates/images/star.png", "generators/ajaxful_rating/templates/images/star_medium.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_jquery.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", "ajaxful_rating_jquery.gemspec"]
|
14
|
+
s.homepage = %q{http://github.com/kamui/ajaxful_rating_jquery}
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Ajaxful_rating_jquery", "--main", "README.textile"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{ajaxful_rating_jquery}
|
18
|
+
s.rubygems_version = %q{1.3.7}
|
19
|
+
s.summary = %q{Add star rating functionality to your Rails 2.3.x application. Requires jQuery.}
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 3
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
26
|
+
else
|
27
|
+
end
|
28
|
+
else
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class AjaxfulRatingGenerator < Rails::Generator::NamedBase
|
2
|
+
def initialize(runtime_args, runtime_options = {})
|
3
|
+
super
|
4
|
+
|
5
|
+
# if there's no user model
|
6
|
+
model_file = File.join('app/models', "#{file_path}.rb")
|
7
|
+
raise "User model (#{model_file}) must exits." unless File.exists?(model_file)
|
8
|
+
end
|
9
|
+
|
10
|
+
def manifest
|
11
|
+
record do |m|
|
12
|
+
m.class_collisions 'Rate'
|
13
|
+
m.template 'model.rb', File.join('app/models', 'rate.rb')
|
14
|
+
m.migration_template 'migration.rb', 'db/migrate',
|
15
|
+
:migration_file_name => 'create_rates'
|
16
|
+
|
17
|
+
# style
|
18
|
+
m.directory 'public/images/ajaxful_rating'
|
19
|
+
m.file 'images/star.png', 'public/images/ajaxful_rating/star.png'
|
20
|
+
m.file 'images/star_medium.png', 'public/images/ajaxful_rating/star_medium.png'
|
21
|
+
m.file 'images/star_small.png', 'public/images/ajaxful_rating/star_small.png'
|
22
|
+
m.file 'style.css', 'public/stylesheets/ajaxful_rating.css'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def banner
|
29
|
+
"Usage: #{$0} ajaxful_rating UserModelName"
|
30
|
+
end
|
31
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateRates < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :rates do |t|
|
4
|
+
t.belongs_to :rater
|
5
|
+
t.belongs_to :rateable, :polymorphic => true
|
6
|
+
t.integer :stars, :null => false
|
7
|
+
t.string :dimension
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :rates, :rater_id
|
12
|
+
add_index :rates, [:rateable_id, :rateable_type]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.down
|
16
|
+
drop_table :rates
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
/*
|
2
|
+
* Style by Rogie http://www.komodomedia.com/blog/2007/01/css-star-rating-redux/
|
3
|
+
*/
|
4
|
+
|
5
|
+
.ajaxful-rating,
|
6
|
+
.ajaxful-rating a:hover,
|
7
|
+
.ajaxful-rating a:active,
|
8
|
+
.ajaxful-rating a:focus,
|
9
|
+
.ajaxful-rating .show-value{
|
10
|
+
background: url(/images/ajaxful_rating/star.png) left -1000px repeat-x;
|
11
|
+
}
|
12
|
+
.ajaxful-rating{
|
13
|
+
position: relative;
|
14
|
+
/*width: 125px; this is setted dynamically */
|
15
|
+
height: 25px;
|
16
|
+
overflow: hidden;
|
17
|
+
list-style: none;
|
18
|
+
margin: 0;
|
19
|
+
padding: 0;
|
20
|
+
background-position: left top;
|
21
|
+
}
|
22
|
+
.ajaxful-rating li{ display: inline; }
|
23
|
+
.ajaxful-rating a,
|
24
|
+
.ajaxful-rating span,
|
25
|
+
.ajaxful-rating .show-value{
|
26
|
+
position: absolute;
|
27
|
+
top: 0;
|
28
|
+
left: 0;
|
29
|
+
text-indent: -1000em;
|
30
|
+
height: 25px;
|
31
|
+
line-height: 25px;
|
32
|
+
outline: none;
|
33
|
+
overflow: hidden;
|
34
|
+
border: none;
|
35
|
+
}
|
36
|
+
.ajaxful-rating a:hover,
|
37
|
+
.ajaxful-rating a:active,
|
38
|
+
.ajaxful-rating a:focus{
|
39
|
+
background-position: left bottom;
|
40
|
+
}
|
41
|
+
|
42
|
+
/* This section is generated dynamically.
|
43
|
+
Just add a call to the helper method 'ajaxful_rating_style' within
|
44
|
+
the head tags in your main layout
|
45
|
+
.ajaxful-rating .stars-1{
|
46
|
+
width: 20%;
|
47
|
+
z-index: 6;
|
48
|
+
}
|
49
|
+
.ajaxful-rating .stars-2{
|
50
|
+
width: 40%;
|
51
|
+
z-index: 5;
|
52
|
+
}
|
53
|
+
.ajaxful-rating .stars-3{
|
54
|
+
width: 60%;
|
55
|
+
z-index: 4;
|
56
|
+
}
|
57
|
+
.ajaxful-rating .stars-4{
|
58
|
+
width: 80%;
|
59
|
+
z-index: 3;
|
60
|
+
}
|
61
|
+
.ajaxful-rating .stars-5{
|
62
|
+
width: 100%;
|
63
|
+
z-index: 2;
|
64
|
+
}
|
65
|
+
*/
|
66
|
+
.ajaxful-rating .show-value{
|
67
|
+
z-index: 1;
|
68
|
+
background-position: left center;
|
69
|
+
}
|
70
|
+
|
71
|
+
/* medium star */
|
72
|
+
.ajaxful-rating.medium{
|
73
|
+
/*width: 54px; this is setted dynamically */
|
74
|
+
height: 18px;
|
75
|
+
}
|
76
|
+
.ajaxful-rating.medium,
|
77
|
+
.ajaxful-rating.medium a:hover,
|
78
|
+
.ajaxful-rating.medium a:active,
|
79
|
+
.ajaxful-rating.medium a:focus,
|
80
|
+
.ajaxful-rating.medium .show-value{
|
81
|
+
background-image: url(/images/ajaxful_rating/star_medium.png);
|
82
|
+
line-height: 18px;
|
83
|
+
height: 18px;
|
84
|
+
}
|
85
|
+
|
86
|
+
/* smaller star */
|
87
|
+
.ajaxful-rating.small{
|
88
|
+
/*width: 50px; this is setted dynamically */
|
89
|
+
height: 10px;
|
90
|
+
}
|
91
|
+
.ajaxful-rating.small,
|
92
|
+
.ajaxful-rating.small a:hover,
|
93
|
+
.ajaxful-rating.small a:active,
|
94
|
+
.ajaxful-rating.small a:focus,
|
95
|
+
.ajaxful-rating.small .show-value{
|
96
|
+
background-image: url(/images/ajaxful_rating/star_small.png);
|
97
|
+
line-height: 10px;
|
98
|
+
height: 10px;
|
99
|
+
}
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'ajaxful_rating_jquery'
|
@@ -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,150 @@
|
|
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
|
+
def ajaxful_rating_script
|
14
|
+
if protect_against_forgery?
|
15
|
+
authenticity_script = %{
|
16
|
+
csrf_param = "authenticity_token";
|
17
|
+
csrf_token = #{form_authenticity_token.inspect};
|
18
|
+
|
19
|
+
// Always send the authenticity_token with ajax
|
20
|
+
$(document).ajaxSend(function(event, request, settings) {
|
21
|
+
if ( settings.type == 'post' ) {
|
22
|
+
settings.data = (settings.data ? settings.data + "&" : "")
|
23
|
+
+ encodeURIComponent( csrf_param ) + "=" + encodeURIComponent( csrf_token );
|
24
|
+
}
|
25
|
+
});
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
%{<script>
|
30
|
+
#{authenticity_script}
|
31
|
+
|
32
|
+
$(document).ready(function(){
|
33
|
+
$('.ajaxful-rating a').bind('click',function(event){
|
34
|
+
event.preventDefault();
|
35
|
+
$.ajax({
|
36
|
+
type: $(this).attr('data-method'),
|
37
|
+
url: $(this).attr('href'),
|
38
|
+
data: {
|
39
|
+
stars: $(this).attr('data-stars'),
|
40
|
+
dimension: $(this).attr('data-dimension'),
|
41
|
+
size: $(this).attr('data-size'),
|
42
|
+
show_user_rating: $(this).attr('data-show_user_rating')
|
43
|
+
},
|
44
|
+
success: function(response){
|
45
|
+
$('#' + response.id + ' .show-value').css('width', response.width + '%');
|
46
|
+
}
|
47
|
+
});
|
48
|
+
});
|
49
|
+
});
|
50
|
+
</script>}
|
51
|
+
end
|
52
|
+
|
53
|
+
def ajaxful_rating_script_prototype
|
54
|
+
%{
|
55
|
+
$$('.ajaxful-rating a').observe('click', rateProduct);
|
56
|
+
|
57
|
+
function rateProduct(event) {
|
58
|
+
var element = event.element();
|
59
|
+
|
60
|
+
new Ajax.Request(element.readAttribute('data-url'), {
|
61
|
+
method: element.readAttribute('data-method'),
|
62
|
+
parameters: {
|
63
|
+
data-stars: element.readAttribute('data-stars'),
|
64
|
+
data-dimension: element.readAttribute('data-dimension'),
|
65
|
+
data-size: element.readAttribute('data-size'),
|
66
|
+
data-show_user_rating: element.readAttribute('data-show_user_rating')
|
67
|
+
},
|
68
|
+
onSuccess: function(transport, json){
|
69
|
+
alert(json ? Object.inspect(json) : "no JSON object");
|
70
|
+
}
|
71
|
+
});
|
72
|
+
}
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
# Generates the stars list to submit a rate.
|
77
|
+
#
|
78
|
+
# It accepts the next options:
|
79
|
+
# * <tt>:size</tt> Set this param to medium or small to display medium/small images. Default is false.
|
80
|
+
# Default is {:method => :post, :url => rate_rateablemodel_path(rateable)}.
|
81
|
+
# * <tt>:wrap</tt> Whether the star list is wrapped within a div tag or not. This is useful when page updating. Default is true.
|
82
|
+
# * <tt>:show_user_rating</tt> Set to true if you want to display only the current user's rating, instead of the global average.
|
83
|
+
# * <tt>:dimension</tt> The dimension to show the ratings for.
|
84
|
+
# * <tt>:force_static</tt> Force static stars even when you're passing a user instance.
|
85
|
+
#
|
86
|
+
# Example:
|
87
|
+
# <%= ratings_for @article, :wrap => false %> # => Will produce something like:
|
88
|
+
# <ul class="ajaxful-rating">
|
89
|
+
# <li class="current-rating" style="width: 60%;">3</li>
|
90
|
+
# <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>
|
91
|
+
# <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>
|
92
|
+
# <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>
|
93
|
+
# <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>
|
94
|
+
# <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>
|
95
|
+
# </ul>
|
96
|
+
#
|
97
|
+
# 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
|
98
|
+
# or pass <tt>:static</tt> to leave the list of stars static.
|
99
|
+
#
|
100
|
+
# Example:
|
101
|
+
# <%= ratings_for @article, @user, :size => 'small' %>
|
102
|
+
# # => Will use @user instead <tt>current_user</tt>
|
103
|
+
#
|
104
|
+
# <%= ratings_for @article, :static, :size => 'medium' %>
|
105
|
+
# # => Will produce a static list of stars showing the current rating average for @article.
|
106
|
+
#
|
107
|
+
# 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.
|
108
|
+
# 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
|
109
|
+
# configuration (accepts update of rates, etc).
|
110
|
+
#
|
111
|
+
# So to actually set the user who will rate the model you need to do it in your controller:
|
112
|
+
#
|
113
|
+
# # controller
|
114
|
+
# def rate
|
115
|
+
# @article = Article.find(params[:id])
|
116
|
+
# @article.rate(params[:stars], current_user) # or any user instance
|
117
|
+
# # update page, etc.
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# 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.
|
121
|
+
# For example:
|
122
|
+
#
|
123
|
+
# <%= ratings_for @article, :show_user_rating => true %>
|
124
|
+
# Or
|
125
|
+
# <%= ratings_for @article, @user, :show_user_rating => true %>
|
126
|
+
#
|
127
|
+
# I18n:
|
128
|
+
#
|
129
|
+
# You can translate the title of the images (the tool tip that shows when the mouse is over) and the 'Currently x/x stars'
|
130
|
+
# string by setting these keys on your translation hash:
|
131
|
+
#
|
132
|
+
# ajaxful_rating:
|
133
|
+
# helper:
|
134
|
+
# global_average: "Global rating average: {{value}} out of {{max}}"
|
135
|
+
# user_rating: "Your rating: {{value}} out of {{max}}"
|
136
|
+
# hover: "Rate {{value}} out of {{max}}" def ratings_for(*args)
|
137
|
+
def ratings_for(*args)
|
138
|
+
@axr_css ||= CSSBuilder.new
|
139
|
+
options = args.extract_options!.symbolize_keys.slice(:size, :url, :method,
|
140
|
+
:wrap, :show_user_rating, :dimension, :force_static, :current_user)
|
141
|
+
rateable = args.shift
|
142
|
+
user = args.shift || (respond_to?(:current_user) ? current_user : raise(NoUserSpecified))
|
143
|
+
StarsBuilder.new(rateable, user, self, @axr_css, options).render
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
class ActionView::Base # :nodoc:
|
149
|
+
include AjaxfulRating::Helpers
|
150
|
+
end
|
data/lib/axr/locale.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module AjaxfulRating # :nodoc:
|
2
|
+
|
3
|
+
# Customize messages by adding I18n keys:
|
4
|
+
#
|
5
|
+
# ajaxful_rating:
|
6
|
+
# helper:
|
7
|
+
# global_average: "Global rating average: {{value}} out of {{max}}"
|
8
|
+
# user_rating: "Your rating: {{value}} out of {{max}}"
|
9
|
+
# hover: "Rate {{value}} out of {{max}}"
|
10
|
+
module Locale
|
11
|
+
|
12
|
+
DEFAULTS = {
|
13
|
+
:user_rating => "Your rating: {{value}} out of {{max}}",
|
14
|
+
:global_average => "Global rating average: {{value}} out of {{max}}",
|
15
|
+
:hover => "Rate {{value}} out of {{max}}"
|
16
|
+
}
|
17
|
+
|
18
|
+
def i18n(key, value = nil)
|
19
|
+
key = if key == :current
|
20
|
+
options[:show_user_rating] ? :user_rating : :global_average
|
21
|
+
else
|
22
|
+
key.to_sym
|
23
|
+
end
|
24
|
+
default = DEFAULTS[key]
|
25
|
+
key = "ajaxful_rating.helper.#{key}"
|
26
|
+
I18n.t(key, :value => (value || show_value),
|
27
|
+
:max => rateable.class.max_stars, :default => default)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/axr/model.rb
ADDED
@@ -0,0 +1,264 @@
|
|
1
|
+
module AjaxfulRating # :nodoc:
|
2
|
+
include AjaxfulRating::Errors
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
# Extends the model to be easy ajaxly rateable.
|
10
|
+
#
|
11
|
+
# Options:
|
12
|
+
# * <tt>:stars</tt> Max number of stars that can be submitted.
|
13
|
+
# * <tt>:allow_update</tt> Set to true if you want users to be able to update their votes.
|
14
|
+
# * <tt>:cache_column</tt> Name of the column for storing the cached rating average.
|
15
|
+
#
|
16
|
+
# Example:
|
17
|
+
# class Article < ActiveRecord::Base
|
18
|
+
# ajaxful_rateable :stars => 10, :cache_column => :custom_column
|
19
|
+
# end
|
20
|
+
def ajaxful_rateable(options = {})
|
21
|
+
has_many :rates_without_dimension, :as => :rateable, :class_name => 'Rate',
|
22
|
+
:dependent => :destroy, :conditions => {:dimension => nil}
|
23
|
+
has_many :raters_without_dimension, :through => :rates_without_dimension, :source => :rater
|
24
|
+
|
25
|
+
options[:dimensions].each do |dimension|
|
26
|
+
has_many "#{dimension}_rates", :dependent => :destroy,
|
27
|
+
:conditions => {:dimension => dimension.to_s}, :class_name => 'Rate', :as => :rateable
|
28
|
+
has_many "#{dimension}_raters", :through => "#{dimension}_rates", :source => :rater
|
29
|
+
end if options[:dimensions].is_a?(Array)
|
30
|
+
|
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
|
+
|
45
|
+
include AjaxfulRating::InstanceMethods
|
46
|
+
extend AjaxfulRating::SingletonMethods
|
47
|
+
end
|
48
|
+
|
49
|
+
# Makes the association between user and Rate model.
|
50
|
+
def ajaxful_rater(options = {})
|
51
|
+
has_many :ratings_given, options.merge(:class_name => "Rate", :foreign_key => :rater_id)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Instance methods for the rateable object.
|
56
|
+
module InstanceMethods
|
57
|
+
|
58
|
+
# Proxy for axr_config singleton method.
|
59
|
+
def axr_config
|
60
|
+
self.class.axr_config
|
61
|
+
end
|
62
|
+
|
63
|
+
# Submits a new rate. Accepts a hash of tipical Ajax request.
|
64
|
+
#
|
65
|
+
# Example:
|
66
|
+
# # Articles Controller
|
67
|
+
# def rate
|
68
|
+
# @article = Article.find(params[:id])
|
69
|
+
# @article.rate(params[:stars], current_user, params[:dimension])
|
70
|
+
# # some page update here ...
|
71
|
+
# end
|
72
|
+
def rate(stars, user, dimension = nil)
|
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
|
+
|
76
|
+
rate = if self.class.axr_config[:allow_update] && rated_by?(user, dimension)
|
77
|
+
rate_by(user, dimension)
|
78
|
+
else
|
79
|
+
returning rates(dimension).build do |r|
|
80
|
+
r.rater = user
|
81
|
+
end
|
82
|
+
end
|
83
|
+
rate.stars = stars
|
84
|
+
rate.save!
|
85
|
+
self.update_cached_average(dimension)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Builds the DOM id attribute for the wrapper in view.
|
89
|
+
def wrapper_dom_id(options = {})
|
90
|
+
options = options.symbolize_keys.slice(:size, :dimension)
|
91
|
+
options = options.select { |k, v| v.present? or (v == false) }.map do |k, v|
|
92
|
+
if k == :dimension
|
93
|
+
v.to_s
|
94
|
+
else
|
95
|
+
v.to_s == 'true' ? k.to_s : "no-#{k}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
options.unshift("ajaxful_rating")
|
99
|
+
ApplicationController.helpers.dom_id(self, options.sort.join('_'))
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns an array with the users that have rated this object for the
|
103
|
+
# passed dimension.
|
104
|
+
#
|
105
|
+
# It may works as an alias for +dimension_raters+ methods.
|
106
|
+
def raters(dimension = nil)
|
107
|
+
sql = "SELECT DISTINCT u.* FROM #{self.class.user_class.table_name} u "\
|
108
|
+
"INNER JOIN rates r ON u.id = r.rater_id WHERE "
|
109
|
+
|
110
|
+
sql << self.class.send(:sanitize_sql_for_conditions, {
|
111
|
+
:rateable_id => id,
|
112
|
+
:rateable_type => self.class.base_class.name,
|
113
|
+
:dimension => (dimension.to_s if dimension)
|
114
|
+
}, 'r')
|
115
|
+
|
116
|
+
self.class.user_class.find_by_sql(sql)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Finds the rate made by the user if he/she has already voted.
|
120
|
+
def rate_by(user, dimension = nil)
|
121
|
+
rates(dimension).find_by_rater_id(user.id)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Return true if the user has rated the object, otherwise false
|
125
|
+
def rated_by?(user, dimension = nil)
|
126
|
+
!rate_by(user, dimension).nil?
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns whether or not the user can rate this object.
|
130
|
+
# Based on if the user has already rated the object or the
|
131
|
+
# :allow_update option is enabled.
|
132
|
+
def can_rate_by?(user, dimension = nil)
|
133
|
+
!rated_by?(user, dimension) || self.class.axr_config[:allow_update]
|
134
|
+
end
|
135
|
+
|
136
|
+
# Instance's total rates.
|
137
|
+
def total_rates(dimension = nil)
|
138
|
+
rates(dimension).size
|
139
|
+
end
|
140
|
+
|
141
|
+
# Total sum of the rates.
|
142
|
+
def rates_sum(dimension = nil)
|
143
|
+
rates(dimension).sum(:stars)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Rating average for the object.
|
147
|
+
#
|
148
|
+
# Pass false as param to force the calculation if you are caching it.
|
149
|
+
def rate_average(cached = true, dimension = nil)
|
150
|
+
avg = if cached && self.class.caching_average?(dimension)
|
151
|
+
send(caching_column_name(dimension)).to_f
|
152
|
+
else
|
153
|
+
self.rates_sum(dimension).to_f / self.total_rates(dimension).to_f
|
154
|
+
end
|
155
|
+
avg.nan? ? 0.0 : avg
|
156
|
+
end
|
157
|
+
|
158
|
+
# Overrides the default +rates+ method and returns the propper array
|
159
|
+
# for the dimension passed.
|
160
|
+
#
|
161
|
+
# It may works as an alias for +dimension_rates+ methods.
|
162
|
+
def rates(dimension = nil)
|
163
|
+
unless dimension.blank?
|
164
|
+
send("#{dimension}_rates")
|
165
|
+
else
|
166
|
+
rates_without_dimension
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# Returns the name of the cache column for the passed dimension.
|
171
|
+
def caching_column_name(dimension = nil)
|
172
|
+
self.class.caching_column_name(dimension)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Updates the cached average column in the rateable model.
|
176
|
+
def update_cached_average(dimension = nil)
|
177
|
+
if self.class.caching_average?(dimension)
|
178
|
+
update_attribute caching_column_name(dimension), self.rate_average(false, dimension)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
module SingletonMethods
|
184
|
+
|
185
|
+
# Maximum value accepted when rating the model. Default is 5.
|
186
|
+
#
|
187
|
+
# Change it by passing the :stars option to +ajaxful_rateable+
|
188
|
+
#
|
189
|
+
# ajaxful_rateable :stars => 10
|
190
|
+
def max_stars
|
191
|
+
axr_config[:stars]
|
192
|
+
end
|
193
|
+
|
194
|
+
# Name of the class for the user model.
|
195
|
+
def user_class_name
|
196
|
+
Rate.reflect_on_association(:rater).options[:class_name]
|
197
|
+
end
|
198
|
+
|
199
|
+
# Gets the user's class
|
200
|
+
def user_class
|
201
|
+
user_class_name.constantize
|
202
|
+
end
|
203
|
+
|
204
|
+
# Finds all rateable objects rated by the +user+.
|
205
|
+
def find_rated_by(user, dimension = nil)
|
206
|
+
find_statement(:rater_id, user.id, dimension)
|
207
|
+
end
|
208
|
+
|
209
|
+
# Finds all rateable objects rated with +stars+.
|
210
|
+
def find_rated_with(stars, dimension = nil)
|
211
|
+
find_statement(:stars, stars, dimension)
|
212
|
+
end
|
213
|
+
|
214
|
+
# Finds the rateable object with the highest rate average.
|
215
|
+
def find_most_popular(dimension = nil)
|
216
|
+
all.sort_by { |o| o.rate_average(true, dimension) }.last
|
217
|
+
end
|
218
|
+
|
219
|
+
# Finds the rateable object with the lowest rate average.
|
220
|
+
def find_less_popular(dimension = nil)
|
221
|
+
all.sort_by { |o| o.rate_average(true, dimension) }.first
|
222
|
+
end
|
223
|
+
|
224
|
+
# Finds rateable objects by Rate's attribute.
|
225
|
+
def find_statement(attr_name, attr_value, dimension = nil)
|
226
|
+
sql = "SELECT DISTINCT r2.* FROM rates r1 INNER JOIN "\
|
227
|
+
"#{self.base_class.table_name} r2 ON r1.rateable_id = r2.id WHERE "
|
228
|
+
|
229
|
+
sql << sanitize_sql_for_conditions({
|
230
|
+
:rateable_type => self.base_class.name,
|
231
|
+
attr_name => attr_value,
|
232
|
+
:dimension => (dimension.to_s if dimension)
|
233
|
+
}, 'r1')
|
234
|
+
|
235
|
+
find_by_sql(sql)
|
236
|
+
end
|
237
|
+
|
238
|
+
# Indicates if the rateable model is able to cache the rate average.
|
239
|
+
#
|
240
|
+
# Include a column named +rating_average+ in your rateable model with
|
241
|
+
# default null, as decimal:
|
242
|
+
#
|
243
|
+
# t.decimal :rating_average, :precision => 3, :scale => 1, :default => 0
|
244
|
+
#
|
245
|
+
# To customize the name of the column specify the option <tt>:cache_column</tt> to ajaxful_rateable
|
246
|
+
#
|
247
|
+
# ajaxful_rateable :cache_column => :my_custom_column
|
248
|
+
#
|
249
|
+
def caching_average?(dimension = nil)
|
250
|
+
column_names.include?(caching_column_name(dimension))
|
251
|
+
end
|
252
|
+
|
253
|
+
# Returns the name of the cache column for the passed dimension.
|
254
|
+
def caching_column_name(dimension = nil)
|
255
|
+
name = axr_config[:cache_column].to_s
|
256
|
+
name += "_#{dimension.to_s.underscore}" unless dimension.blank?
|
257
|
+
name
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
class ActiveRecord::Base
|
263
|
+
include AjaxfulRating
|
264
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module AjaxfulRating # :nodoc:
|
2
|
+
class StarsBuilder # :nodoc:
|
3
|
+
include AjaxfulRating::Locale
|
4
|
+
|
5
|
+
attr_reader :rateable, :user, :options
|
6
|
+
|
7
|
+
def initialize(rateable, user_or_static, template, css_builder, 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)
|
11
|
+
end
|
12
|
+
|
13
|
+
def show_value
|
14
|
+
if options[:show_user_rating]
|
15
|
+
rate = rateable.rate_by(user, options[:dimension]) if user
|
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)
|
29
|
+
@options = {
|
30
|
+
:url => nil,
|
31
|
+
:method => :post,
|
32
|
+
:wrap => true,
|
33
|
+
:size => nil,
|
34
|
+
:show_user_rating => false,
|
35
|
+
:force_static => false,
|
36
|
+
:current_user => (@template.current_user if @template.respond_to?(:current_user))
|
37
|
+
}.merge(options)
|
38
|
+
|
39
|
+
@options[:show_user_rating] = @options[:show_user_rating].to_s == 'true'
|
40
|
+
@options[:wrap] = @options[:wrap].to_s == 'true'
|
41
|
+
|
42
|
+
if @options[:url].nil?
|
43
|
+
rateable_name = ActionController::RecordIdentifier.singular_class_name(rateable)
|
44
|
+
url = "rate_#{rateable_name}_path"
|
45
|
+
if @template.respond_to?(url)
|
46
|
+
@options[:url] = @template.send(url, rateable)
|
47
|
+
else
|
48
|
+
raise(MissingRateRoute)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def ratings_tag
|
54
|
+
stars = []
|
55
|
+
width = (show_value / rateable.class.max_stars.to_f) * 100
|
56
|
+
li_class = "axr-#{show_value}-#{rateable.class.max_stars}".gsub('.', '_')
|
57
|
+
@css_builder.rule('.ajaxful-rating', :width => (rateable.class.max_stars * 25))
|
58
|
+
@css_builder.rule('.ajaxful-rating.medium',
|
59
|
+
:width => (rateable.class.max_stars * 18)) if options[:size] == 'medium'
|
60
|
+
@css_builder.rule('.ajaxful-rating.small',
|
61
|
+
:width => (rateable.class.max_stars * 10)) if options[:size] == 'small'
|
62
|
+
|
63
|
+
stars << @template.content_tag(:li, i18n(:current), :class => "show-value",
|
64
|
+
:style => "width: #{width}%")
|
65
|
+
stars += (1..rateable.class.max_stars).map do |i|
|
66
|
+
star_tag(i)
|
67
|
+
end
|
68
|
+
if options[:size] == 'small'
|
69
|
+
size = ' small'
|
70
|
+
elsif options[:size] == 'medium'
|
71
|
+
size = ' medium'
|
72
|
+
end
|
73
|
+
# When using rails_xss plugin, it needs to render as HTML
|
74
|
+
@template.content_tag(:ul, stars.join.try(:html_safe), :class => "ajaxful-rating#{size}")
|
75
|
+
end
|
76
|
+
|
77
|
+
def star_tag(value)
|
78
|
+
already_rated = rateable.rated_by?(user, options[:dimension]) if user
|
79
|
+
css_class = "stars-#{value}"
|
80
|
+
@css_builder.rule(".ajaxful-rating .#{css_class}", {
|
81
|
+
:width => "#{(value / rateable.class.max_stars.to_f) * 100}%",
|
82
|
+
:zIndex => (rateable.class.max_stars + 2 - value).to_s
|
83
|
+
})
|
84
|
+
@template.content_tag(:li) do
|
85
|
+
if !options[:force_static] && (user && options[:current_user] == user &&
|
86
|
+
(!already_rated || rateable.axr_config[:allow_update]))
|
87
|
+
link_star_tag(value, css_class)
|
88
|
+
else
|
89
|
+
@template.content_tag(:span, show_value, :class => css_class, :title => i18n(:current))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def link_star_tag(value, css_class)
|
95
|
+
html = {
|
96
|
+
:"data-method" => options[:method],
|
97
|
+
:"data-stars" => value,
|
98
|
+
:"data-dimension" => options[:dimension],
|
99
|
+
:"data-size" => options[:size],
|
100
|
+
:"data-show_user_rating" => options[:show_user_rating],
|
101
|
+
:class => css_class,
|
102
|
+
:title => i18n(:hover, value)
|
103
|
+
}
|
104
|
+
@template.link_to(value, options[:url], html)
|
105
|
+
end
|
106
|
+
|
107
|
+
def wrapper_tag
|
108
|
+
@template.content_tag(:div, ratings_tag, :class => "ajaxful-rating-wrapper",
|
109
|
+
:id => rateable.wrapper_dom_id(options))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ajaxful_rating_jquery
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 2
|
8
|
+
- 2
|
9
|
+
- 9
|
10
|
+
version: 2.2.9
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jack Chu, Edgar J. Suarez
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-09-30 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Provides a simple way to add rating functionality to your application. This is a fork of ajaxful_ratings that works with jQuery instead of Prototype and uses unobtrusive javascript instead of link_to_remote.
|
23
|
+
email: kamuigt@gmail.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- CHANGELOG
|
30
|
+
- README.textile
|
31
|
+
- lib/ajaxful_rating_jquery.rb
|
32
|
+
- lib/axr/css_builder.rb
|
33
|
+
- lib/axr/errors.rb
|
34
|
+
- lib/axr/helpers.rb
|
35
|
+
- lib/axr/locale.rb
|
36
|
+
- lib/axr/model.rb
|
37
|
+
- lib/axr/stars_builder.rb
|
38
|
+
files:
|
39
|
+
- CHANGELOG
|
40
|
+
- Manifest
|
41
|
+
- README.textile
|
42
|
+
- Rakefile
|
43
|
+
- generators/ajaxful_rating/USAGE
|
44
|
+
- generators/ajaxful_rating/ajaxful_rating_generator.rb
|
45
|
+
- generators/ajaxful_rating/templates/images/star.png
|
46
|
+
- generators/ajaxful_rating/templates/images/star_medium.png
|
47
|
+
- generators/ajaxful_rating/templates/images/star_small.png
|
48
|
+
- generators/ajaxful_rating/templates/migration.rb
|
49
|
+
- generators/ajaxful_rating/templates/model.rb
|
50
|
+
- generators/ajaxful_rating/templates/style.css
|
51
|
+
- init.rb
|
52
|
+
- lib/ajaxful_rating_jquery.rb
|
53
|
+
- lib/axr/css_builder.rb
|
54
|
+
- lib/axr/errors.rb
|
55
|
+
- lib/axr/helpers.rb
|
56
|
+
- lib/axr/locale.rb
|
57
|
+
- lib/axr/model.rb
|
58
|
+
- lib/axr/stars_builder.rb
|
59
|
+
- ajaxful_rating_jquery.gemspec
|
60
|
+
has_rdoc: true
|
61
|
+
homepage: http://github.com/kamui/ajaxful_rating_jquery
|
62
|
+
licenses: []
|
63
|
+
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options:
|
66
|
+
- --line-numbers
|
67
|
+
- --inline-source
|
68
|
+
- --title
|
69
|
+
- Ajaxful_rating_jquery
|
70
|
+
- --main
|
71
|
+
- README.textile
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 3
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 11
|
89
|
+
segments:
|
90
|
+
- 1
|
91
|
+
- 2
|
92
|
+
version: "1.2"
|
93
|
+
requirements: []
|
94
|
+
|
95
|
+
rubyforge_project: ajaxful_rating_jquery
|
96
|
+
rubygems_version: 1.3.7
|
97
|
+
signing_key:
|
98
|
+
specification_version: 3
|
99
|
+
summary: Add star rating functionality to your Rails 2.3.x application. Requires jQuery.
|
100
|
+
test_files: []
|
101
|
+
|