Merge branch 'develop' of 10.0.47.245:/home/trustie2 into develop
2
Gemfile
|
@ -6,7 +6,7 @@ unless RUBY_PLATFORM =~ /w32/
|
|||
gem 'rubyzip'
|
||||
gem 'zip-zip'
|
||||
end
|
||||
gem 'seems_rateable'
|
||||
gem 'seems_rateable', path: 'lib/seems_rateable'
|
||||
gem "rails", "3.2.13"
|
||||
gem "jquery-rails", "~> 2.0.2"
|
||||
gem "i18n", "~> 0.6.0"
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
require_dependency "seems_rateable/application_controller"
|
||||
|
||||
class RatingsController < ::ApplicationController
|
||||
def create
|
||||
raise NoCurrentUserInstanceError unless current_user
|
||||
|
||||
obj = params[:kls].classify.constantize.find(params[:idBox])
|
||||
begin
|
||||
obj.rate(params[:rate].to_i, current_user.id, params[:dimension])
|
||||
render :json => true
|
||||
rescue Errors::AlreadyRatedError
|
||||
render :json => {:error => true}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -16,7 +16,8 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
RedmineApp::Application.routes.draw do
|
||||
resources :ratings, :only => :create
|
||||
mount SeemsRateable::Engine => '/rateable', :as => :rateable
|
||||
|
||||
namespace :zipdown do
|
||||
match 'assort'
|
||||
end
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
*.gem
|
||||
*.rbc
|
||||
.bundle
|
||||
.config
|
||||
.yardoc
|
||||
Gemfile.lock
|
||||
InstalledFiles
|
||||
_yardoc
|
||||
coverage
|
||||
doc/
|
||||
lib/bundler/man
|
||||
pkg
|
||||
rdoc
|
||||
spec/reports
|
||||
test/tmp
|
||||
test/version_tmp
|
||||
tmp
|
||||
.project
|
||||
.rvmrc
|
||||
spec
|
||||
test
|
|
@ -1,32 +0,0 @@
|
|||
begin
|
||||
require 'bundler/setup'
|
||||
rescue LoadError
|
||||
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
||||
end
|
||||
|
||||
require 'rdoc/task'
|
||||
|
||||
RDoc::Task.new(:rdoc) do |rdoc|
|
||||
rdoc.rdoc_dir = 'rdoc'
|
||||
rdoc.title = 'SeemsRateable'
|
||||
rdoc.options << '--line-numbers'
|
||||
rdoc.rdoc_files.include('README.rdoc')
|
||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||
end
|
||||
|
||||
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
||||
load 'rails/tasks/engine.rake'
|
||||
Bundler::GemHelper.install_tasks
|
||||
|
||||
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
||||
load 'rails/tasks/engine.rake'
|
||||
|
||||
Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f }
|
||||
require 'rspec/core'
|
||||
require 'rspec/core/rake_task'
|
||||
|
||||
task :default => :spec
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
module SeemsRateable
|
||||
class ApplicationController < ActionController::Base
|
||||
end
|
||||
end
|
|
@ -1,4 +0,0 @@
|
|||
module SeemsRateable
|
||||
module ApplicationHelper
|
||||
end
|
||||
end
|
|
@ -1,4 +0,0 @@
|
|||
module SeemsRateable
|
||||
module RatingsHelper
|
||||
end
|
||||
end
|
|
@ -1,6 +0,0 @@
|
|||
module SeemsRateable
|
||||
class Rate < ActiveRecord::Base
|
||||
belongs_to :rater, :class_name => SeemsRateable::Engine.config.owner_class
|
||||
belongs_to :rateable, :polymorphic => true
|
||||
end
|
||||
end
|
|
@ -1,14 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>SeemsRateable</title>
|
||||
<%= stylesheet_link_tag "seems_rateable/application", media: "all" %>
|
||||
<%= javascript_include_tag "seems_rateable/application" %>
|
||||
<%= csrf_meta_tags %>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<%= yield %>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,39 +0,0 @@
|
|||
require 'rails/generators/migration'
|
||||
require 'fileutils'
|
||||
|
||||
module SeemsRateable
|
||||
module Generators
|
||||
class InstallGenerator < ::Rails::Generators::Base
|
||||
include Rails::Generators::Migration
|
||||
source_root File.expand_path('../templates', __FILE__)
|
||||
|
||||
def self.next_migration_number(path)
|
||||
unless @prev_migration_nr
|
||||
@prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
||||
else
|
||||
@prev_migration_nr += 1
|
||||
end
|
||||
@prev_migration_nr.to_s
|
||||
end
|
||||
|
||||
desc "generating migration files"
|
||||
def copy_migrations
|
||||
migration_template "rates_migration.rb", "db/migrate/create_seems_rateable_rates.rb"
|
||||
migration_template "cached_ratings_migration.rb", "db/migrate/create_seems_rateable_cached_ratings.rb"
|
||||
end
|
||||
|
||||
desc "generating initializer"
|
||||
def copy_initializer
|
||||
template "initializer.rb", "config/initializers/seems_rateable.rb"
|
||||
end
|
||||
|
||||
desc "generating javascript files"
|
||||
def copy_javascript_asset
|
||||
Dir.mkdir "app/assets/javascripts/rateable" unless File.directory?("app/assets/javascripts/rateable")
|
||||
copy_file "rateable.js.erb", "app/assets/javascripts/rateable/rateable.js.erb" unless File.exists?("app/assets/javascripts/rateable/rateable.js.erb")
|
||||
copy_file "jRating.js.erb", "app/assets/javascripts/rateable/jRating.js.erb" unless File.exists?("app/assets/javascripts/rateable/jRating.js.erb")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,17 +0,0 @@
|
|||
class CreateSeemsRateableCachedRatings < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :seems_rateable_cached_ratings do |t|
|
||||
t.belongs_to :cacheable, :polymorphic => true
|
||||
t.float :avg, :null => false
|
||||
t.integer :cnt, :null => false
|
||||
t.string :dimension
|
||||
t.integer :cacheable_id, :limit => 8
|
||||
t.string :cacheable_type
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :cached_ratings
|
||||
end
|
||||
end
|
|
@ -1,17 +0,0 @@
|
|||
module SeemsRateable
|
||||
class Engine < ::Rails::Engine
|
||||
isolate_namespace SeemsRateable
|
||||
|
||||
config.generators do |g|
|
||||
g.test_framework :rspec, :fixture => false
|
||||
g.fixture_replacement :factory_girl, :dir => 'spec/factories'
|
||||
end
|
||||
|
||||
initializer :seems_rateable do
|
||||
ActiveRecord::Base.send :include, SeemsRateable::Model
|
||||
ActionView::Base.send :include, SeemsRateable::Helpers
|
||||
ActionDispatch::Routing::Mapper.send :include, SeemsRateable::Routes
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -1,21 +0,0 @@
|
|||
module SeemsRateable
|
||||
module Errors
|
||||
class InvalidRateableObjectError < StandardError
|
||||
def to_s
|
||||
"Stated object is not rateable. Add 'seems_rateable' to your object's class model."
|
||||
end
|
||||
end
|
||||
|
||||
class NoCurrentUserInstanceError < StandardError
|
||||
def to_s
|
||||
"User instance current_user is not available."
|
||||
end
|
||||
end
|
||||
|
||||
class AlreadyRatedError < StandardError
|
||||
def to_s
|
||||
"User has already rated an object."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,27 +0,0 @@
|
|||
module SeemsRateable
|
||||
module Helpers
|
||||
def rating_for(obj, opts={})
|
||||
raise Errors::InvalidRateableObjectError unless obj.class.respond_to?(:rateable?)
|
||||
|
||||
options = {
|
||||
:dimension => nil,
|
||||
:static => false,
|
||||
:class => 'rateable',
|
||||
:id => nil
|
||||
}.update(opts)
|
||||
|
||||
content_tag :div, "", "data-average" => obj.average(options[:dimension]) ? obj.average(options[:dimension]).avg : 0, :id => options[:id],
|
||||
:class => "#{options[:class]}#{jdisabled?(options[:static])}",
|
||||
"data-id" => obj.id, "data-kls" => obj.class.name, "data-dimension" => options[:dimension]
|
||||
end
|
||||
|
||||
def seems_rateable_stylesheet
|
||||
stylesheet_link_tag "seems_rateable/application", media: "all", "data-turbolinks-track" => true
|
||||
end
|
||||
|
||||
private
|
||||
def jdisabled?(option)
|
||||
" jDisabled" if option || !current_user
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,111 +0,0 @@
|
|||
require 'active_support/concern'
|
||||
module SeemsRateable
|
||||
module Model
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def rate(stars, user_id, dimension=nil)
|
||||
if !has_rated?(user_id, dimension)
|
||||
self.rates.create do |r|
|
||||
r.stars = stars
|
||||
r.rater_id = user_id
|
||||
end
|
||||
update_overall_average_rating(stars, dimension)
|
||||
elsif has_rated?(user_id, dimension) && can_update?
|
||||
update_users_rating(stars, user_id, dimension)
|
||||
else
|
||||
raise Errors::AlreadyRatedError
|
||||
end
|
||||
end
|
||||
|
||||
def update_overall_average_rating(stars, dimension=nil)
|
||||
if average(dimension).nil?
|
||||
CachedRating.create do |r|
|
||||
r.avg = stars
|
||||
r.dimension = dimension
|
||||
r.cacheable_id = self.id
|
||||
r.cacheable_type = self.class.name
|
||||
r.cnt = 1
|
||||
end
|
||||
else
|
||||
r = average(dimension)
|
||||
r.avg = (r.avg * r.cnt + stars) / (r.cnt+1)
|
||||
r.cnt += 1
|
||||
r.save!
|
||||
end
|
||||
end
|
||||
|
||||
def update_users_rating(stars, user_id, dimension=nil)
|
||||
obj = rates(dimension).where(:rater_id => user_id).first
|
||||
current_record = average(dimension)
|
||||
current_record.avg = (current_record.avg*current_record.cnt - obj.stars + stars) / (current_record.cnt)
|
||||
current_record.save!
|
||||
obj.stars = stars
|
||||
obj.save!
|
||||
end
|
||||
|
||||
|
||||
def average(dimension=nil)
|
||||
if dimension.nil?
|
||||
self.send "rate_average_without_dimension"
|
||||
else
|
||||
self.send "#{dimension}_average"
|
||||
end
|
||||
end
|
||||
|
||||
def rates(dimension=nil)
|
||||
if dimension.nil?
|
||||
self.send "rates_without_dimension"
|
||||
else
|
||||
self.send "#{dimension}_rates"
|
||||
end
|
||||
end
|
||||
|
||||
def raters(dimension=nil)
|
||||
if dimension.nil?
|
||||
self.send "raters_without_dimension"
|
||||
else
|
||||
self.send "#{dimension}_raters"
|
||||
end
|
||||
end
|
||||
|
||||
def has_rated?(user_id, dimension=nil)
|
||||
record = self.rates(dimension).where(:rater_id => user_id)
|
||||
record.empty? ? false : true
|
||||
end
|
||||
|
||||
def can_update?
|
||||
self.class.can_update?
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def seems_rateable(opts={})
|
||||
#has_many :rates_without_dimension, -> { where(dimension: nil) }, :as => :rateable, :class_name => SeemsRateable::Rate, :dependent => :destroy
|
||||
has_many :rates_without_dimension, :conditions => { dimension: nil }, :as => :rateable, :class_name => SeemsRateable::Rate, :dependent => :destroy
|
||||
has_many :raters_without_dimension, :through => :rates_without_dimension, :source => :rater
|
||||
has_one :rate_average_without_dimension, :conditions => { dimension: nil }, :as => :cacheable, :class_name => SeemsRateable::CachedRating, :dependent => :destroy
|
||||
|
||||
@permission = opts[:allow_update] ? true : false
|
||||
|
||||
def self.can_update?
|
||||
@permission
|
||||
end
|
||||
|
||||
def self.rateable?
|
||||
true
|
||||
end
|
||||
|
||||
if opts[:dimensions].is_a?(Array)
|
||||
opts[:dimensions].each do |dimension|
|
||||
has_many :"#{dimension}_rates", :conditions => { dimension: dimension.to_s }, :dependent => :destroy, :class_name => SeemsRateable::Rate, :as => :rateable
|
||||
has_many :"#{dimension}_raters", :through => :"#{dimension}_rates", :source => :rater
|
||||
has_one :"#{dimension}_average", :conditions => { dimension: dimension.to_s }, :as => :cacheable, :class_name => SeemsRateable::CachedRating, :dependent => :destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def seems_rateable_rater
|
||||
has_many :ratings_given, :class_name => SeemsRateable::Rate, :foreign_key => :rater_id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +0,0 @@
|
|||
# desc "Explaining what the task does"
|
||||
# task :seems_rateable do
|
||||
# # Task goes here
|
||||
# end
|
|
@ -0,0 +1,17 @@
|
|||
begin
|
||||
require 'bundler/setup'
|
||||
rescue LoadError
|
||||
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
||||
end
|
||||
|
||||
require 'rdoc/task'
|
||||
|
||||
RDoc::Task.new(:rdoc) do |rdoc|
|
||||
rdoc.rdoc_dir = 'rdoc'
|
||||
rdoc.title = 'SeemsRateable'
|
||||
rdoc.options << '--line-numbers'
|
||||
rdoc.rdoc_files.include('README.md')
|
||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||
end
|
||||
|
||||
Bundler::GemHelper.install_tasks
|
Before Width: | Height: | Size: 572 B After Width: | Height: | Size: 572 B |
Before Width: | Height: | Size: 427 B After Width: | Height: | Size: 427 B |
Before Width: | Height: | Size: 1018 B After Width: | Height: | Size: 1018 B |
|
@ -20,43 +20,43 @@
|
|||
|
||||
|
||||
.jRatingAverage {
|
||||
background-color:#f62929;
|
||||
position:relative;
|
||||
top:0;
|
||||
left:0;
|
||||
z-index:2;
|
||||
height:100%;
|
||||
background-color:#f62929;
|
||||
position:relative;
|
||||
top:0;
|
||||
left:0;
|
||||
z-index:2;
|
||||
height:100%;
|
||||
}
|
||||
.jRatingColor {
|
||||
background-color:#FFD400; /* bgcolor of the stars*/
|
||||
position:relative;
|
||||
top:0;
|
||||
left:0;
|
||||
z-index:2;
|
||||
height:100%;
|
||||
background-color:#FFD400; /* bgcolor of the stars*/
|
||||
position:relative;
|
||||
top:0;
|
||||
left:0;
|
||||
z-index:2;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
/** Div containing the stars **/
|
||||
.jStar {
|
||||
position:relative;
|
||||
left:0;
|
||||
z-index:3;
|
||||
position:relative;
|
||||
left:0;
|
||||
z-index:3;
|
||||
}
|
||||
|
||||
/** P containing the rate informations **/
|
||||
p.jRatingInfos {
|
||||
position: absolute;
|
||||
z-index:9999;
|
||||
background: transparent url('bg_jRatingInfos.png') no-repeat;
|
||||
color: #CACACA;
|
||||
display: none;
|
||||
width: 91px;
|
||||
height: 29px;
|
||||
font-size:16px;
|
||||
text-align:center;
|
||||
padding-top:5px;
|
||||
position: absolute;
|
||||
z-index:9999;
|
||||
background: transparent url('bg_jRatingInfos.png') no-repeat;
|
||||
color: #CACACA;
|
||||
display: none;
|
||||
width: 91px;
|
||||
height: 29px;
|
||||
font-size:16px;
|
||||
text-align:center;
|
||||
padding-top:5px;
|
||||
}
|
||||
p.jRatingInfos span.maxRate {
|
||||
color:#c9c9c9;
|
||||
font-size:14px;
|
||||
color:#c9c9c9;
|
||||
font-size:14px;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
module SeemsRateable
|
||||
class ApplicationController < ::ApplicationController
|
||||
rescue_from SeemsRateable::Errors::AlreadyRatedError do |exception|
|
||||
render :json => {:error => true}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
require_dependency "seems_rateable/application_controller"
|
||||
|
||||
module SeemsRateable
|
||||
class RatingsController < ApplicationController
|
||||
def create
|
||||
raise Errors::NoCurrentUserInstanceError unless current_user
|
||||
obj = params[:kls].classify.constantize.find(params[:idBox])
|
||||
obj.rate(params[:rate].to_i, current_user.id, params[:dimension])
|
||||
|
||||
render :json => true
|
||||
|
||||
rescue Errors::NoCurrentUserInstanceError
|
||||
render :json => {:error => 'you must be login.'}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +1,5 @@
|
|||
module SeemsRateable
|
||||
class CachedRating < ActiveRecord::Base
|
||||
belongs_to :cacheable, :polymorphic => true
|
||||
belongs_to :cacheable, :polymorphic => true
|
||||
end
|
||||
end
|
|
@ -0,0 +1,6 @@
|
|||
module SeemsRateable
|
||||
class Rate < ActiveRecord::Base
|
||||
belongs_to :rater, :class_name => SeemsRateable::Engine.config.owner_class
|
||||
belongs_to :rateable, :polymorphic => true
|
||||
end
|
||||
end
|
|
@ -0,0 +1,42 @@
|
|||
require 'rails/generators/migration'
|
||||
require 'fileutils'
|
||||
|
||||
module SeemsRateable
|
||||
module Generators
|
||||
class InstallGenerator < ::Rails::Generators::Base
|
||||
include Rails::Generators::Migration
|
||||
source_root File.expand_path('../templates', __FILE__)
|
||||
|
||||
def self.next_migration_number(path)
|
||||
unless @prev_migration_nr
|
||||
@prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
||||
else
|
||||
@prev_migration_nr += 1
|
||||
end
|
||||
@prev_migration_nr.to_s
|
||||
end
|
||||
|
||||
def routegen
|
||||
route("seems_rateable")
|
||||
end
|
||||
|
||||
desc "generating migration files"
|
||||
def copy_migrations
|
||||
migration_template "rates_migration.rb", "db/migrate/create_seems_rateable_rates.rb"
|
||||
migration_template "cached_ratings_migration.rb", "db/migrate/create_seems_rateable_cached_ratings.rb"
|
||||
end
|
||||
|
||||
desc "generating initializer"
|
||||
def copy_initializer
|
||||
template "initializer.rb", "config/initializers/seems_rateable.rb"
|
||||
end
|
||||
|
||||
desc "generating javascript files"
|
||||
def copy_javascript_asset
|
||||
Dir.mkdir "app/assets/javascripts/rateable" unless File.directory?("app/assets/javascripts/rateable")
|
||||
copy_file "rateable.js.erb", "app/assets/javascripts/rateable/rateable.js.erb" unless File.exists?("app/assets/javascripts/rateable/rateable.js.erb")
|
||||
copy_file "jRating.js.erb", "app/assets/javascripts/rateable/jRating.js.erb" unless File.exists?("app/assets/javascripts/rateable/jRating.js.erb")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,17 @@
|
|||
class CreateSeemsRateableCachedRatings < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :seems_rateable_cached_ratings do |t|
|
||||
t.belongs_to :cacheable, :polymorphic => true
|
||||
t.float :avg, :null => false
|
||||
t.integer :cnt, :null => false
|
||||
t.string :dimension
|
||||
t.integer :cacheable_id, :limit => 8
|
||||
t.string :cacheable_type
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :cached_ratings
|
||||
end
|
||||
end
|
|
@ -12,9 +12,9 @@
|
|||
$.fn.jRating = function(op) {
|
||||
var defaults = {
|
||||
/** String vars **/
|
||||
bigStarsPath : '<%= image_path "seems_rateable/stars.png" %>', // path of the icon stars.png
|
||||
smallStarsPath : '<%= image_path "seems_rateable/small.png" %>', // path of the icon small.png
|
||||
path : '<%= SeemsRateable::Engine.routes.url_helpers.ratings_path %>',
|
||||
bigStarsPath : 'images/seems_rateable/stars.png', // path of the icon stars.png
|
||||
smallStarsPath : 'images/seems_rateable/small.png', // path of the icon small.png
|
||||
path : '/ratings',
|
||||
type : 'big', // can be set to 'small' or 'big'
|
||||
|
||||
/** Boolean vars **/
|
|
@ -11,7 +11,7 @@ $(document).ready(function(){
|
|||
//showRateInfo:false, //Rate info panel, set true to display
|
||||
//rateInfosX : 45, //In pixel - Absolute left position of the information box during mousemove.
|
||||
//rateInfosY : 5, //In pixel - Absolute top position of the information box during mousemove.
|
||||
path : '<%= SeemsRateable::Engine.routes.url_helpers.ratings_path %>',
|
||||
path : '/ratings',
|
||||
onSuccess : function(element, rate){
|
||||
//something like ->
|
||||
//alert('success');
|
|
@ -1,8 +1,10 @@
|
|||
begin
|
||||
require 'rails'
|
||||
require 'rails'
|
||||
rescue LoadError
|
||||
end
|
||||
|
||||
require "jquery-rails"
|
||||
|
||||
require "seems_rateable/engine"
|
||||
require "seems_rateable/errors"
|
||||
require "seems_rateable/helpers"
|
|
@ -0,0 +1,16 @@
|
|||
module SeemsRateable
|
||||
class Engine < ::Rails::Engine
|
||||
isolate_namespace SeemsRateable
|
||||
|
||||
config.generators do |g|
|
||||
g.test_framework :rspec, :fixture => false
|
||||
g.fixture_replacement :factory_girl, :dir => 'spec/factories'
|
||||
end
|
||||
|
||||
initializer :seems_rateable do
|
||||
ActiveRecord::Base.send :include, SeemsRateable::Model
|
||||
ActionView::Base.send :include, SeemsRateable::Helpers
|
||||
ActionDispatch::Routing::Mapper.send :include, SeemsRateable::Routes
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
module SeemsRateable
|
||||
module Errors
|
||||
class InvalidRateableObjectError < StandardError
|
||||
def to_s
|
||||
"Stated object is not rateable. Add 'seems_rateable' to your object's class model."
|
||||
end
|
||||
end
|
||||
|
||||
class NoCurrentUserInstanceError < StandardError
|
||||
def to_s
|
||||
"User instance current_user is not available."
|
||||
end
|
||||
end
|
||||
|
||||
class AlreadyRatedError < StandardError
|
||||
def to_s
|
||||
"User has already rated an object."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
module SeemsRateable
|
||||
module Helpers
|
||||
def rating_for(obj, opts={})
|
||||
raise Errors::InvalidRateableObjectError unless obj.class.respond_to?(:rateable?)
|
||||
|
||||
options = {
|
||||
:dimension => nil,
|
||||
:static => false,
|
||||
:class => 'rateable',
|
||||
:id => nil
|
||||
}.update(opts)
|
||||
|
||||
content_tag :div, "", "data-average" => obj.average(options[:dimension]) ? obj.average(options[:dimension]).avg : 0, :id => options[:id],
|
||||
:class => "#{options[:class]}#{jdisabled?(options[:static])}",
|
||||
"data-id" => obj.id, "data-kls" => obj.class.name, "data-dimension" => options[:dimension]
|
||||
end
|
||||
|
||||
def seems_rateable_stylesheet
|
||||
stylesheet_link_tag "seems_rateable/application", media: "all", "data-turbolinks-track" => true
|
||||
end
|
||||
|
||||
private
|
||||
def jdisabled?(option)
|
||||
" jDisabled" if option || !current_user
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,91 @@
|
|||
require 'active_support/concern'
|
||||
|
||||
module SeemsRateable
|
||||
module Model
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def rate(stars, user_id, dimension=nil)
|
||||
if !has_rated?(user_id, dimension)
|
||||
self.rates.create do |r|
|
||||
r.stars = stars
|
||||
r.rater_id = user_id
|
||||
r.dimension = dimension
|
||||
end
|
||||
update_overall_average_rating(stars, dimension)
|
||||
elsif has_rated?(user_id, dimension) && can_update?
|
||||
update_users_rating(stars, user_id, dimension)
|
||||
else
|
||||
raise Errors::AlreadyRatedError
|
||||
end
|
||||
end
|
||||
|
||||
def update_overall_average_rating(stars, dimension=nil)
|
||||
r = average(dimension)
|
||||
if r.nil?
|
||||
self.rate_averages.create do |r|
|
||||
r.avg = stars
|
||||
r.dimension = dimension
|
||||
r.cnt = 1
|
||||
end
|
||||
else
|
||||
r.avg = (r.avg * r.cnt + stars) / (r.cnt+1)
|
||||
r.cnt += 1
|
||||
r.save!
|
||||
r
|
||||
end
|
||||
end
|
||||
|
||||
def update_users_rating(stars, user_id, dimension=nil)
|
||||
obj = rates(dimension).where(:rater_id => user_id).first
|
||||
current_record = average(dimension)
|
||||
current_record.avg = (current_record.avg*current_record.cnt - obj.stars + stars) / (current_record.cnt)
|
||||
current_record.save!
|
||||
obj.stars = stars
|
||||
obj.save!
|
||||
end
|
||||
|
||||
|
||||
def average(dimension=nil)
|
||||
rate_averages.where(dimension: dimension).first
|
||||
end
|
||||
|
||||
def rates(dimension=nil)
|
||||
rates_all.where(dimension: dimension)
|
||||
end
|
||||
|
||||
def raters(dimension=nil)
|
||||
raters_all.where('seems_rateable_rates.dimension = ?', dimension)
|
||||
end
|
||||
|
||||
def has_rated?(user_id, dimension=nil)
|
||||
record = self.rates(dimension).where(:rater_id => user_id)
|
||||
record.empty? ? false : true
|
||||
end
|
||||
|
||||
def can_update?
|
||||
self.class.can_update?
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def seems_rateable(opts={})
|
||||
has_many :rates_all, :as => :rateable, :class_name => SeemsRateable::Rate, :dependent => :destroy
|
||||
has_many :raters_all, :through => :rates_all, :class_name => SeemsRateable::Engine.config.owner_class, :source => :rater
|
||||
has_many :rate_averages, :as => :cacheable, :class_name => SeemsRateable::CachedRating, :dependent => :destroy
|
||||
|
||||
self.class_variable_set(:@@permission, opts[:allow_update] ? true : false)
|
||||
|
||||
def self.can_update?
|
||||
self.class_variable_get(:@@permission)
|
||||
end
|
||||
|
||||
def self.rateable?
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def seems_rateable_rater
|
||||
has_many :ratings_given, :class_name => SeemsRateable::Rate, :foreign_key => :rater_id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,3 +1,3 @@
|
|||
module SeemsRateable
|
||||
VERSION = "1.0.9"
|
||||
VERSION = "1.0.13"
|
||||
end
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 52 KiB |
|
@ -14,7 +14,7 @@
|
|||
/** String vars **/
|
||||
bigStarsPath : '/images/seems_rateable/stars.png', // path of the icon stars.png
|
||||
smallStarsPath : '/images/seems_rateable/small.png', // path of the icon small.png
|
||||
path : '/ratings',
|
||||
path : '/rateable/ratings',
|
||||
type : 'big', // can be set to 'small' or 'big'
|
||||
|
||||
/** Boolean vars **/
|
||||
|
|
|
@ -11,7 +11,7 @@ $(document).ready(function(){
|
|||
//showRateInfo:false, //Rate info panel, set true to display
|
||||
//rateInfosX : 45, //In pixel - Absolute left position of the information box during mousemove.
|
||||
//rateInfosY : 5, //In pixel - Absolute top position of the information box during mousemove.
|
||||
path : '/ratings',
|
||||
path : '/rateable/ratings',
|
||||
onSuccess : function(element, rate){
|
||||
//something like ->
|
||||
//alert('success');
|
||||
|
|