Module: Mongoid::Rating::Model::ClassMethods
- Defined in:
- lib/mongoid_rating/model.rb
Instance Method Summary collapse
-
#rateable(field, opt = {}) ⇒ Object
Make model rateable.
Instance Method Details
#rateable(field, opt = {}) ⇒ Object
Make model rateable
rateable :overall, range: -5..5
Disable average completely rateable :design, range: -5..5, average: false rateable :quality, range: -5..5, average: true
float: whether to allow non-integer rates (default true)
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/mongoid_rating/model.rb', line 19 def rateable(field, opt = {}) = { range: 1..5, rerate: true, counters: true, float: true, }.merge(opt) [:no_rate] ||= [:float] ? '0.0' : '0' [:format] ||= [:float] ? '%.1f' : '%d' field = field.to_sym sfield = field.inspect # total rates count field "#{field}_count", type: Integer, default: 0 # rates data "#{field}_data", as: :rateable, class_name: 'Mongoid::Rating::Rate', counter_cache: true # sum of all rates to calculate average field "#{field}_sum".to_sym, type: [:float] ? Float : Integer # average rate value avg = "#{field}_average".to_sym field avg, type: Float savg = avg.inspect class_eval " scope :\#{field}_by, ->(rater) {\n where(\"\#{field}_data.rater_id\" => rater.id, \"\#{field}_data.rater_type\" => rater.class.to_s)\n }\n scope :\#{field}_in, ->(range) {\n where(\#{savg}.gte => range.begin, \#{savg}.lte => range.end)\n }\n\n scope :by_\#{field}, -> {\n order_by([\#{savg}, :desc])\n }\n scope :highest_\#{field}, -> {\n where(\#{savg}.ne => nil).order_by([\#{savg}, :desc])\n }\n\n # return user's rate if rated otherwise formatted rate value\n # good for Raty JS plugin\n def fmt_\#{field}(user = nil)\n if !user.nil? && \#{field}_by?(user)\n \#{options[:format].inspect} % \#{field}_by(user)\n elsif \#{field}.nil?\n \#{options[:no_rate].class.name == 'String' ? options[:no_rate].inspect : options[:no_rate]}\n else\n \#{options[:format].inspect} % \#{field}\n end\n end\n\n def \#{field}!(value, rater)\n if \#{options[:float]}\n value = value.to_f\n else\n value = value.to_i \n end\n unless (\#{options[:range]}).include?(value)\n raise \"bad vote value\"\n end\n raise \"can't rate\" unless can_\#{field}?(rater)\n un\#{field}!(rater)\n atomically do\n inc(\"\#{field}_count\" => 1, \"\#{field}_sum\" => value)\n \#{field}_data.create!(rater: rater, value: value)\n set(\"\#{field}_average\" => calc_\#{field}_avg)\n end\n end\n def calc_\#{field}_avg\n if \#{field}_count < 1\n nil\n else\n \#{field}_sum.to_f / \#{field}_count.to_f\n end\n end\n def un\#{field}!(rater)\n r = \#{field}_data.where(rater_id: rater.id).first\n if r.nil?\n # not rated before\n else\n atomically do\n inc(\"\#{field}_count\" => -1, \"\#{field}_sum\" => -r.value)\n set(\"\#{field}_average\" => calc_\#{field}_avg)\n r.destroy\n end\n end\n end\n alias_method :un\#{field}, :un\#{field}!\n \n def did_\#{field}?(rater)\n !raw_\#{field}_by(rater).nil?\n end\n\n def can_\#{field}?(rater)\n if \#{options[:rerate]}\n true\n else\n !did_\#{field}?(rater)\n end\n end\n\n def raw_\#{field}_by(rater)\n \#{field}_data.select do |rate|\n rate[:rater_id] == rater.id && rate[:rater_type] == rater.class.name\n end.first\n end\n\n def \#{field}(value=nil, rater=nil)\n if rater.nil? && value.nil?\n \#{field}_count.nil? ? nil : \#{field}_average\n else\n \#{field}!(value, rater)\n end\n end\n\n def \#{field}_values\n \#{field}_data.map(&:value)\n end\n\n def \#{field}_by(rater)\n rate = raw_\#{field}_by(rater)\n if rate.nil?\n nil\n else\n rate.value\n end\n end\n def \#{field}_by?(rater)\n !\#{field}_by(rater).nil?\n end\n RUBY\nend\n", __FILE__, __LINE__+1 |