ratyrate 1.2.0.alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +8 -0
  5. data/Gemfile.lock +51 -0
  6. data/README.md +169 -0
  7. data/Rakefile +12 -0
  8. data/lib/generators/ratyrate/USAGE +0 -0
  9. data/lib/generators/ratyrate/ratyrate_generator.rb +56 -0
  10. data/lib/generators/ratyrate/templates/average_cache_migration.rb +17 -0
  11. data/lib/generators/ratyrate/templates/average_cache_model.rb +4 -0
  12. data/lib/generators/ratyrate/templates/big-star.png +0 -0
  13. data/lib/generators/ratyrate/templates/cache_migration.rb +19 -0
  14. data/lib/generators/ratyrate/templates/cache_model.rb +3 -0
  15. data/lib/generators/ratyrate/templates/cancel-off.png +0 -0
  16. data/lib/generators/ratyrate/templates/cancel-on.png +0 -0
  17. data/lib/generators/ratyrate/templates/jquery.raty.js +464 -0
  18. data/lib/generators/ratyrate/templates/mid-star.png +0 -0
  19. data/lib/generators/ratyrate/templates/migration.rb +20 -0
  20. data/lib/generators/ratyrate/templates/model.rb +7 -0
  21. data/lib/generators/ratyrate/templates/overall_average_migration.rb +16 -0
  22. data/lib/generators/ratyrate/templates/overall_average_model.rb +4 -0
  23. data/lib/generators/ratyrate/templates/rater_controller.rb +13 -0
  24. data/lib/generators/ratyrate/templates/ratyrate.js.erb +59 -0
  25. data/lib/generators/ratyrate/templates/star-half.png +0 -0
  26. data/lib/generators/ratyrate/templates/star-off.png +0 -0
  27. data/lib/generators/ratyrate/templates/star-on.png +0 -0
  28. data/lib/ratyrate/helpers.rb +144 -0
  29. data/lib/ratyrate/model.rb +153 -0
  30. data/lib/ratyrate/version.rb +3 -0
  31. data/lib/ratyrate.rb +7 -0
  32. data/ratyrate.gemspec +24 -0
  33. metadata +76 -0
@@ -0,0 +1,144 @@
1
+ module Helpers
2
+ def rating_for(rateable_obj, dimension=nil, options={})
3
+
4
+ cached_average = rateable_obj.average dimension
5
+ avg = cached_average ? cached_average.avg : 0
6
+
7
+ star = options[:star] || 5
8
+ enable_half = options[:enable_half] || true
9
+ half_show = options[:half_show] || true
10
+ star_path = options[:star_path] || "/assets"
11
+ star_on = options[:star_on] || "star-on.png"
12
+ star_off = options[:star_off] || "star-off.png"
13
+ star_half = options[:star_half] || "star-half.png"
14
+ cancel = options[:cancel] || false
15
+ cancel_place = options[:cancel_place] || "left"
16
+ cancel_hint = options[:cancel_hint] || "Cancel current rating!"
17
+ cancel_on = options[:cancel_on] || "cancel-on.png"
18
+ cancel_off = options[:cancel_off] || "cancel-off.png"
19
+ noRatedMsg = options[:noRatedMsg] || "I'am readOnly and I haven't rated yet!"
20
+ # round = options[:round] || { down: .26, full: .6, up: .76 }
21
+ space = options[:space] || false
22
+ single = options[:single] || false
23
+ target = options[:target] || ''
24
+ targetText = options[:targetText] || ''
25
+ targetType = options[:targetType] || 'hint'
26
+ targetFormat = options[:targetFormat] || '{score}'
27
+ targetScore = options[:targetScore] || ''
28
+
29
+ disable_after_rate = options[:disable_after_rate] && true
30
+ disable_after_rate = true if disable_after_rate == nil
31
+
32
+ if disable_after_rate
33
+ readonly = !(current_user && rateable_obj.can_rate?(current_user, dimension))
34
+ else
35
+ readonly = false
36
+ end
37
+
38
+ if options[:imdb_avg] && readonly
39
+ content_tag :div, '', :style => "background-image:url(/assets/mid-star.png);width:61px;height:57px;margin-top:10px;" do
40
+ content_tag :p, avg, :style => "position:relative;font-size:.8rem;text-align:center;line-height:60px;"
41
+ end
42
+ else
43
+ content_tag :div, '', "data-dimension" => dimension, :class => "star", "data-rating" => avg,
44
+ "data-id" => rateable_obj.id, "data-classname" => rateable_obj.class.name,
45
+ "data-disable-after-rate" => disable_after_rate,
46
+ "data-readonly" => readonly,
47
+ "data-enable-half" => enable_half,
48
+ "data-half-show" => half_show,
49
+ "data-star-count" => star,
50
+ "data-star-path" => star_path,
51
+ "data-star-on" => star_on,
52
+ "data-star-off" => star_off,
53
+ "data-star-half" => star_half,
54
+ "data-cancel" => cancel,
55
+ "data-cancel-place" => cancel_place,
56
+ "data-cancel-hint" => cancel_hint,
57
+ "data-cancel-on" => cancel_on,
58
+ "data-cancel-off" => cancel_off,
59
+ "data-no-rated-message" => noRatedMsg,
60
+ # "data-round" => round,
61
+ "data-space" => space,
62
+ "data-single" => single,
63
+ "data-target" => target,
64
+ "data-target-text" => targetText,
65
+ "data-target-type" => targetType,
66
+ "data-target-format" => targetFormat,
67
+ "data-target-score" => targetScore
68
+ end
69
+ end
70
+
71
+ def imdb_style_rating_for(rateable_obj, user, options = {})
72
+ overall_avg = rateable_obj.overall_avg(user)
73
+
74
+ content_tag :div, '', :style => "background-image:url(/assets/big-star.png);width:81px;height:81px;margin-top:10px;" do
75
+ content_tag :p, overall_avg, :style => "position:relative;line-height:85px;text-align:center;"
76
+ end
77
+ end
78
+
79
+ def rating_for_user(rateable_obj, rating_user, dimension = nil, options = {})
80
+ @object = rateable_obj
81
+ @user = rating_user
82
+ @rating = Rate.find_by_rater_id_and_rateable_id_and_dimension(@user.id, @object.id, dimension)
83
+ stars = @rating ? @rating.stars : 0
84
+
85
+ star = options[:star] || 5
86
+ enable_half = options[:enable_half] || true
87
+ half_show = options[:half_show] || true
88
+ star_path = options[:star_path] || "/assets"
89
+ star_on = options[:star_on] || "star-on.png"
90
+ star_off = options[:star_off] || "star-off.png"
91
+ star_half = options[:star_half] || "star-half.png"
92
+ cancel = options[:cancel] || false
93
+ cancel_place = options[:cancel_place] || "left"
94
+ cancel_hint = options[:cancel_hint] || "Cancel current rating!"
95
+ cancel_on = options[:cancel_on] || "cancel-on.png"
96
+ cancel_off = options[:cancel_off] || "cancel-off.png"
97
+ noRatedMsg = options[:noRatedMsg] || "I'am readOnly and I haven't rated yet!"
98
+ # round = options[:round] || { down: .26, full: .6, up: .76 }
99
+ space = options[:space] || false
100
+ single = options[:single] || false
101
+ target = options[:target] || ''
102
+ targetText = options[:targetText] || ''
103
+ targetType = options[:targetType] || 'hint'
104
+ targetFormat = options[:targetFormat] || '{score}'
105
+ targetScore = options[:targetScore] || ''
106
+
107
+ disable_after_rate = options[:disable_after_rate] || false
108
+
109
+ readonly=false
110
+ if disable_after_rate
111
+ readonly = current_user.present? ? !rateable_obj.can_rate?(current_user.id, dimension) : true
112
+ end
113
+
114
+ content_tag :div, '', "data-dimension" => dimension, :class => "star", "data-rating" => stars,
115
+ "data-id" => rateable_obj.id, "data-classname" => rateable_obj.class.name,
116
+ "data-disable-after-rate" => disable_after_rate,
117
+ "data-readonly" => readonly,
118
+ "data-enable-half" => enable_half,
119
+ "data-half-show" => half_show,
120
+ "data-star-count" => stars,
121
+ "data-star-path" => star_path,
122
+ "data-star-on" => star_on,
123
+ "data-star-off" => star_off,
124
+ "data-star-half" => star_half,
125
+ "data-cancel" => cancel,
126
+ "data-cancel-place" => cancel_place,
127
+ "data-cancel-hint" => cancel_hint,
128
+ "data-cancel-on" => cancel_on,
129
+ "data-cancel-off" => cancel_off,
130
+ "data-no-rated-message" => noRatedMsg,
131
+ # "data-round" => round,
132
+ "data-space" => space,
133
+ "data-single" => single,
134
+ "data-target" => target,
135
+ "data-target-text" => targetText,
136
+ "data-target-format" => targetFormat,
137
+ "data-target-score" => targetScore
138
+ end
139
+
140
+ end
141
+
142
+ class ActionView::Base
143
+ include Helpers
144
+ end
@@ -0,0 +1,153 @@
1
+ require 'active_support/concern'
2
+ module Ratyrate
3
+ extend ActiveSupport::Concern
4
+
5
+ def rate(stars, user, dimension=nil, dirichlet_method=false)
6
+ dimension = nil if dimension.blank?
7
+
8
+ if can_rate? user, dimension
9
+ rates(dimension).create! do |r|
10
+ r.stars = stars
11
+ r.rater = user
12
+ end
13
+ if dirichlet_method
14
+ update_rate_average_dirichlet(stars, dimension)
15
+ else
16
+ update_rate_average(stars, dimension)
17
+ end
18
+ else
19
+ update_current_rate(stars, user, dimension)
20
+ end
21
+ end
22
+
23
+ def update_rate_average_dirichlet(stars, dimension=nil)
24
+ ## assumes 5 possible vote categories
25
+ dp = {1 => 1, 2 => 1, 3 => 1, 4 => 1, 5 => 1}
26
+ stars_group = Hash[rates(dimension).group(:stars).count.map{|k,v| [k.to_i,v] }]
27
+ posterior = dp.merge(stars_group){|key, a, b| a + b}
28
+ sum = posterior.map{ |i, v| v }.inject { |a, b| a + b }
29
+ davg = posterior.map{ |i, v| i * v }.inject { |a, b| a + b }.to_f / sum
30
+
31
+ if average(dimension).nil?
32
+ RatingCache.create! do |avg|
33
+ avg.cacheable_id = self.id
34
+ avg.cacheable_type = self.class.name
35
+ avg.qty = 1
36
+ avg.avg = davg
37
+ avg.dimension = dimension
38
+ end
39
+ else
40
+ a = average(dimension)
41
+ a.qty = rates(dimension).count
42
+ a.avg = davg
43
+ a.save!(validate: false)
44
+ end
45
+ end
46
+
47
+ def update_rate_average(stars, dimension=nil)
48
+ if average(dimension).nil?
49
+ RatingCache.create! do |avg|
50
+ avg.cacheable_id = self.id
51
+ avg.cacheable_type = self.class.name
52
+ avg.avg = stars
53
+ avg.qty = 1
54
+ avg.dimension = dimension
55
+ end
56
+ else
57
+ a = average(dimension)
58
+ a.qty = rates(dimension).count
59
+ a.avg = rates(dimension).average(:stars)
60
+ a.save!(validate: false)
61
+ end
62
+ end
63
+
64
+ def update_current_rate(stars, user, dimension)
65
+ current_rate = user.ratings_given.where(rater_id: user.id, rateable_id: self.id, dimension: dimension).take
66
+ current_rate.stars = stars
67
+ current_rate.save!(validate: false)
68
+
69
+ if rates(dimension).count > 1
70
+ update_rate_average(stars, dimension)
71
+ else # Set the avarage to the exact number of stars
72
+ a = average(dimension)
73
+ a.avg = stars
74
+ a.save!(validate: false)
75
+ end
76
+ end
77
+
78
+ def overall_avg(user)
79
+ # avg = OverallAverage.where(rateable_id: self.id)
80
+ # #FIXME: Fix the bug when the movie has no ratings
81
+ # unless avg.empty?
82
+ # return avg.take.avg unless avg.take.avg == 0
83
+ # else # calculate average, and save it
84
+ # dimensions_count = overall_score = 0
85
+ # user.ratings_given.select('DISTINCT dimension').each do |d|
86
+ # dimensions_count = dimensions_count + 1
87
+ # unless average(d.dimension).nil?
88
+ # overall_score = overall_score + average(d.dimension).avg
89
+ # end
90
+ # end
91
+ # overall_avg = (overall_score / dimensions_count).to_f.round(1)
92
+ # AverageCache.create! do |a|
93
+ # a.rater_id = user.id
94
+ # a.rateable_id = self.id
95
+ # a.avg = overall_avg
96
+ # end
97
+ # overall_avg
98
+ # end
99
+ end
100
+
101
+ # calculate the movie overall average rating for all users
102
+ def calculate_overall_average
103
+ end
104
+
105
+ def average(dimension=nil)
106
+ dimension ? self.send("#{dimension}_average") : rate_average_without_dimension
107
+ end
108
+
109
+ def can_rate?(user, dimension=nil)
110
+ user.ratings_given.where(dimension: dimension, rateable_id: id, rateable_type: self.class.name).size.zero?
111
+ end
112
+
113
+ def rates(dimension=nil)
114
+ dimension ? self.send("#{dimension}_rates") : rates_without_dimension
115
+ end
116
+
117
+ def raters(dimension=nil)
118
+ dimension ? self.send("#{dimension}_raters") : raters_without_dimension
119
+ end
120
+
121
+ module ClassMethods
122
+
123
+ def ratyrate_rater
124
+ has_many :ratings_given, :class_name => "Rate", :foreign_key => :rater_id
125
+ end
126
+
127
+ def ratyrate_rateable(*dimensions)
128
+ has_many :rates_without_dimension, -> { where dimension: nil}, :as => :rateable, :class_name => "Rate", :dependent => :destroy
129
+ has_many :raters_without_dimension, :through => :rates_without_dimension, :source => :rater
130
+
131
+ has_one :rate_average_without_dimension, -> { where dimension: nil}, :as => :cacheable,
132
+ :class_name => "RatingCache", :dependent => :destroy
133
+
134
+ dimensions.each do |dimension|
135
+ has_many "#{dimension}_rates".to_sym, -> {where dimension: dimension.to_s},
136
+ :dependent => :destroy,
137
+ :class_name => "Rate",
138
+ :as => :rateable
139
+
140
+ has_many "#{dimension}_raters".to_sym, :through => "#{dimension}_rates", :source => :rater
141
+
142
+ has_one "#{dimension}_average".to_sym, -> { where dimension: dimension.to_s },
143
+ :as => :cacheable, :class_name => "RatingCache",
144
+ :dependent => :destroy
145
+ end
146
+ end
147
+ end
148
+
149
+ end
150
+
151
+ class ActiveRecord::Base
152
+ include Ratyrate
153
+ end
@@ -0,0 +1,3 @@
1
+ module Ratyrate
2
+ VERSION = "1.2.0.alpha"
3
+ end
data/lib/ratyrate.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "ratyrate/version"
2
+ require "ratyrate/model"
3
+ require "ratyrate/helpers"
4
+
5
+ module Ratyrate
6
+
7
+ end
data/ratyrate.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "ratyrate/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ratyrate"
7
+ s.version = Ratyrate::VERSION
8
+ s.authors = ["Islam Wazery"]
9
+ s.email = ["wazery@ubuntu.com"]
10
+ s.homepage = "http://github.com/wazery/ratyrate"
11
+ s.summary = %q{A Ruby Gem that provides the same functionality of jQuery Raty library, and adds IMDB style rating.}
12
+ s.description = %q{A Ruby Gem that provides the same functionality of jQuery Raty library, and adds IMDB style rating.}
13
+
14
+ s.rubyforge_project = "ratyrate"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ratyrate
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0.alpha
5
+ platform: ruby
6
+ authors:
7
+ - Islam Wazery
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A Ruby Gem that provides the same functionality of jQuery Raty library,
14
+ and adds IMDB style rating.
15
+ email:
16
+ - wazery@ubuntu.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - ".gitignore"
22
+ - ".travis.yml"
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - README.md
26
+ - Rakefile
27
+ - lib/generators/ratyrate/USAGE
28
+ - lib/generators/ratyrate/ratyrate_generator.rb
29
+ - lib/generators/ratyrate/templates/average_cache_migration.rb
30
+ - lib/generators/ratyrate/templates/average_cache_model.rb
31
+ - lib/generators/ratyrate/templates/big-star.png
32
+ - lib/generators/ratyrate/templates/cache_migration.rb
33
+ - lib/generators/ratyrate/templates/cache_model.rb
34
+ - lib/generators/ratyrate/templates/cancel-off.png
35
+ - lib/generators/ratyrate/templates/cancel-on.png
36
+ - lib/generators/ratyrate/templates/jquery.raty.js
37
+ - lib/generators/ratyrate/templates/mid-star.png
38
+ - lib/generators/ratyrate/templates/migration.rb
39
+ - lib/generators/ratyrate/templates/model.rb
40
+ - lib/generators/ratyrate/templates/overall_average_migration.rb
41
+ - lib/generators/ratyrate/templates/overall_average_model.rb
42
+ - lib/generators/ratyrate/templates/rater_controller.rb
43
+ - lib/generators/ratyrate/templates/ratyrate.js.erb
44
+ - lib/generators/ratyrate/templates/star-half.png
45
+ - lib/generators/ratyrate/templates/star-off.png
46
+ - lib/generators/ratyrate/templates/star-on.png
47
+ - lib/ratyrate.rb
48
+ - lib/ratyrate/helpers.rb
49
+ - lib/ratyrate/model.rb
50
+ - lib/ratyrate/version.rb
51
+ - ratyrate.gemspec
52
+ homepage: http://github.com/wazery/ratyrate
53
+ licenses: []
54
+ metadata: {}
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.3.1
69
+ requirements: []
70
+ rubyforge_project: ratyrate
71
+ rubygems_version: 2.2.2
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: A Ruby Gem that provides the same functionality of jQuery Raty library, and
75
+ adds IMDB style rating.
76
+ test_files: []