merit 0.7.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +5 -0
- data/Gemfile.lock +13 -2
- data/README.md +72 -53
- data/TESTING.txt +7 -2
- data/lib/generators/merit/templates/merit.rb +1 -1
- data/lib/merit.rb +2 -1
- data/lib/merit/controller_extensions.rb +2 -2
- data/lib/merit/model_additions.rb +9 -2
- data/lib/merit/models/mongo_mapper/merit_action.rb +1 -0
- data/lib/merit/models/mongoid/merit_action.rb +13 -0
- data/lib/merit/models/mongoid/sash.rb +14 -0
- data/lib/merit/rule.rb +4 -2
- data/lib/merit/rules_rank.rb +7 -2
- data/merit.gemspec +5 -2
- data/test/dummy-mongoid/Rakefile +7 -0
- data/test/dummy-mongoid/app/controllers/application_controller.rb +7 -0
- data/test/dummy-mongoid/app/controllers/comments_controller.rb +90 -0
- data/test/dummy-mongoid/app/controllers/registrations_controller.rb +15 -0
- data/test/dummy-mongoid/app/controllers/users_controller.rb +67 -0
- data/test/dummy-mongoid/app/helpers/application_helper.rb +2 -0
- data/test/dummy-mongoid/app/models/comment.rb +17 -0
- data/test/dummy-mongoid/app/models/merit/badge_rules.rb +49 -0
- data/test/dummy-mongoid/app/models/merit/point_rules.rb +20 -0
- data/test/dummy-mongoid/app/models/merit/rank_rules.rb +24 -0
- data/test/dummy-mongoid/app/models/user.rb +30 -0
- data/test/dummy-mongoid/app/views/comments/_form.html.erb +29 -0
- data/test/dummy-mongoid/app/views/comments/edit.html.erb +6 -0
- data/test/dummy-mongoid/app/views/comments/index.html.erb +35 -0
- data/test/dummy-mongoid/app/views/comments/new.html.erb +5 -0
- data/test/dummy-mongoid/app/views/comments/show.html.erb +23 -0
- data/test/dummy-mongoid/app/views/layouts/application.html.erb +24 -0
- data/test/dummy-mongoid/app/views/users/_form.html.erb +22 -0
- data/test/dummy-mongoid/app/views/users/edit.html.erb +6 -0
- data/test/dummy-mongoid/app/views/users/index.html.erb +26 -0
- data/test/dummy-mongoid/app/views/users/new.html.erb +5 -0
- data/test/dummy-mongoid/app/views/users/show.html.erb +18 -0
- data/test/dummy-mongoid/config.ru +4 -0
- data/test/dummy-mongoid/config/application.rb +22 -0
- data/test/dummy-mongoid/config/boot.rb +10 -0
- data/test/dummy-mongoid/config/environment.rb +5 -0
- data/test/dummy-mongoid/config/environments/development.rb +25 -0
- data/test/dummy-mongoid/config/environments/production.rb +49 -0
- data/test/dummy-mongoid/config/environments/test.rb +35 -0
- data/test/dummy-mongoid/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy-mongoid/config/initializers/inflections.rb +10 -0
- data/test/dummy-mongoid/config/initializers/merit.rb +37 -0
- data/test/dummy-mongoid/config/initializers/mime_types.rb +5 -0
- data/test/dummy-mongoid/config/initializers/secret_token.rb +7 -0
- data/test/dummy-mongoid/config/initializers/session_store.rb +8 -0
- data/test/dummy-mongoid/config/locales/en.yml +5 -0
- data/test/dummy-mongoid/config/mongoid.yml +14 -0
- data/test/dummy-mongoid/config/routes.rb +9 -0
- data/test/dummy-mongoid/db/seeds.rb +17 -0
- data/test/dummy-mongoid/public/404.html +26 -0
- data/test/dummy-mongoid/public/422.html +26 -0
- data/test/dummy-mongoid/public/500.html +26 -0
- data/test/dummy-mongoid/public/favicon.ico +0 -0
- data/test/dummy-mongoid/public/javascripts/application.js +2 -0
- data/test/dummy-mongoid/public/javascripts/controls.js +965 -0
- data/test/dummy-mongoid/public/javascripts/dragdrop.js +974 -0
- data/test/dummy-mongoid/public/javascripts/effects.js +1123 -0
- data/test/dummy-mongoid/public/javascripts/prototype.js +6001 -0
- data/test/dummy-mongoid/public/javascripts/rails.js +191 -0
- data/test/dummy-mongoid/public/stylesheets/.gitkeep +0 -0
- data/test/dummy-mongoid/public/stylesheets/scaffold.css +56 -0
- data/test/dummy-mongoid/script/rails +6 -0
- data/test/dummy/config/initializers/merit.rb +1 -1
- data/test/integration/navigation_test.rb +1 -1
- data/test/merit_unit_test.rb +3 -0
- data/test/test_helper.rb +20 -3
- metadata +92 -16
@@ -0,0 +1,90 @@
|
|
1
|
+
class CommentsController < ApplicationController
|
2
|
+
# GET /comments
|
3
|
+
# GET /comments.xml
|
4
|
+
def index
|
5
|
+
@comments = Comment.all
|
6
|
+
|
7
|
+
respond_to do |format|
|
8
|
+
format.html # index.html.erb
|
9
|
+
format.xml { render :xml => @comments }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# GET /comments/1
|
14
|
+
# GET /comments/1.xml
|
15
|
+
def show
|
16
|
+
@comment = Comment.find(params[:id])
|
17
|
+
|
18
|
+
respond_to do |format|
|
19
|
+
format.html # show.html.erb
|
20
|
+
format.xml { render :xml => @comment }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# GET /comments/new
|
25
|
+
# GET /comments/new.xml
|
26
|
+
def new
|
27
|
+
@comment = Comment.new
|
28
|
+
|
29
|
+
respond_to do |format|
|
30
|
+
format.html # new.html.erb
|
31
|
+
format.xml { render :xml => @comment }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# GET /comments/1/edit
|
36
|
+
def edit
|
37
|
+
@comment = Comment.find(params[:id])
|
38
|
+
end
|
39
|
+
|
40
|
+
def vote
|
41
|
+
@comment = Comment.find(params[:id])
|
42
|
+
@comment.votes += params[:value].to_i
|
43
|
+
@comment.save
|
44
|
+
redirect_to(comments_url, :notice => 'Vote added!')
|
45
|
+
end
|
46
|
+
|
47
|
+
# POST /comments
|
48
|
+
# POST /comments.xml
|
49
|
+
def create
|
50
|
+
@comment = Comment.new(params[:comment])
|
51
|
+
|
52
|
+
respond_to do |format|
|
53
|
+
if @comment.save
|
54
|
+
format.html { redirect_to(@comment, :notice => 'Comment was successfully created.') }
|
55
|
+
format.xml { render :xml => @comment, :status => :created, :location => @comment }
|
56
|
+
else
|
57
|
+
format.html { render "new" }
|
58
|
+
format.xml { render :xml => @comment.errors, :status => :unprocessable_entity }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# PUT /comments/1
|
64
|
+
# PUT /comments/1.xml
|
65
|
+
def update
|
66
|
+
@comment = Comment.find(params[:id])
|
67
|
+
|
68
|
+
respond_to do |format|
|
69
|
+
if @comment.update_attributes(params[:comment])
|
70
|
+
format.html { redirect_to(@comment, :notice => 'Comment was successfully updated.') }
|
71
|
+
format.xml { head :ok }
|
72
|
+
else
|
73
|
+
format.html { render "edit" }
|
74
|
+
format.xml { render :xml => @comment.errors, :status => :unprocessable_entity }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# DELETE /comments/1
|
80
|
+
# DELETE /comments/1.xml
|
81
|
+
def destroy
|
82
|
+
@comment = Comment.find(params[:id])
|
83
|
+
@comment.destroy
|
84
|
+
|
85
|
+
respond_to do |format|
|
86
|
+
format.html { redirect_to(comments_url) }
|
87
|
+
format.xml { head :ok }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class RegistrationsController < ApplicationController
|
2
|
+
def update
|
3
|
+
@user = User.find(params[:id])
|
4
|
+
|
5
|
+
respond_to do |format|
|
6
|
+
if @user.update_attributes(params[:user])
|
7
|
+
format.html { redirect_to(@user, :notice => 'User was successfully updated.') }
|
8
|
+
format.xml { head :ok }
|
9
|
+
else
|
10
|
+
format.html { render "edit" }
|
11
|
+
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
class UsersController < ApplicationController
|
2
|
+
# GET /users
|
3
|
+
# GET /users.xml
|
4
|
+
def index
|
5
|
+
@users = User.all
|
6
|
+
|
7
|
+
respond_to do |format|
|
8
|
+
format.html # index.html.erb
|
9
|
+
format.xml { render :xml => @users }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# GET /users/1
|
14
|
+
# GET /users/1.xml
|
15
|
+
def show
|
16
|
+
@user = User.find(params[:id])
|
17
|
+
|
18
|
+
respond_to do |format|
|
19
|
+
format.html # show.html.erb
|
20
|
+
format.xml { render :xml => @user }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# GET /users/new
|
25
|
+
# GET /users/new.xml
|
26
|
+
def new
|
27
|
+
@user = User.new
|
28
|
+
|
29
|
+
respond_to do |format|
|
30
|
+
format.html # new.html.erb
|
31
|
+
format.xml { render :xml => @user }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# GET /users/1/edit
|
36
|
+
def edit
|
37
|
+
@user = User.find(params[:id])
|
38
|
+
end
|
39
|
+
|
40
|
+
# POST /users
|
41
|
+
# POST /users.xml
|
42
|
+
def create
|
43
|
+
@user = User.new(params[:user])
|
44
|
+
|
45
|
+
respond_to do |format|
|
46
|
+
if @user.save
|
47
|
+
format.html { redirect_to(@user, :notice => 'User was successfully created.') }
|
48
|
+
format.xml { render :xml => @user, :status => :created, :location => @user }
|
49
|
+
else
|
50
|
+
format.html { render "new" }
|
51
|
+
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# DELETE /users/1
|
57
|
+
# DELETE /users/1.xml
|
58
|
+
def destroy
|
59
|
+
@user = User.find(params[:id])
|
60
|
+
@user.destroy
|
61
|
+
|
62
|
+
respond_to do |format|
|
63
|
+
format.html { redirect_to(users_url) }
|
64
|
+
format.xml { head :ok }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Comment
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Timestamps
|
4
|
+
belongs_to :user
|
5
|
+
|
6
|
+
field :name
|
7
|
+
field :comment
|
8
|
+
field :votes, :type => Integer, :default => 0
|
9
|
+
|
10
|
+
attr_accessible :name, :comment, :user_id, :votes
|
11
|
+
|
12
|
+
validates :name, :comment, :user_id, :presence => true
|
13
|
+
|
14
|
+
def self.find_by_id(id)
|
15
|
+
where(:_id => id).first
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# +grant_on+ accepts:
|
2
|
+
# * Nothing (always grants)
|
3
|
+
# * A block which evaluates to boolean (recieves the object as parameter)
|
4
|
+
# * A block with a hash composed of methods to run on the target object with
|
5
|
+
# expected values (+:votes => 5+ for instance).
|
6
|
+
#
|
7
|
+
# +grant_on+ can have a +:to+ method name, which called over the target object
|
8
|
+
# should retrieve the object to badge (could be +:user+, +:self+, +:follower+,
|
9
|
+
# etc). If it's not defined merit will apply the badge to the user who
|
10
|
+
# triggered the action (:action_user by default). If it's :itself, it badges
|
11
|
+
# the created object (new user for instance).
|
12
|
+
#
|
13
|
+
# The :temporary option indicates that if the condition doesn't hold but the
|
14
|
+
# badge is granted, then it's removed. It's false by default (badges are kept
|
15
|
+
# forever).
|
16
|
+
|
17
|
+
module Merit
|
18
|
+
class BadgeRules
|
19
|
+
include Merit::BadgeRulesMethods
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
# If it creates user, grant badge
|
23
|
+
# Should be "current_user" after registration for badge to be granted.
|
24
|
+
# Example rule with block with no parameters
|
25
|
+
grant_on 'users#create', :badge => 'just-registered', :to => :itself do
|
26
|
+
Date.today > 1.year.ago.to_date
|
27
|
+
end
|
28
|
+
|
29
|
+
# Example rule for multiple badge granting
|
30
|
+
grant_on 'users#index', :badge => 'gossip', :multiple => true
|
31
|
+
|
32
|
+
# If it has 10 comments, grant commenter-10 badge
|
33
|
+
grant_on 'comments#create', :badge => 'commenter', :level => 10 do |comment|
|
34
|
+
comment.user.comments.count >= 10
|
35
|
+
end
|
36
|
+
|
37
|
+
# If it has at least 10 votes, grant relevant-commenter badge
|
38
|
+
grant_on 'comments#vote', :badge => 'relevant-commenter', :to => :user do |comment|
|
39
|
+
comment.votes >= 10
|
40
|
+
end
|
41
|
+
|
42
|
+
# Changes his name by one wider than 4 chars (arbitrary ruby code and custom model_name)
|
43
|
+
# This badge is temporary (user may lose it)
|
44
|
+
grant_on 'registrations#update', :badge => 'autobiographer', :temporary => true, :model_name => 'User' do |user|
|
45
|
+
user.name.length > 4
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Points are a simple integer value which are given to "meritable" resources
|
2
|
+
# according to rules in +app/models/merit_point_rules.rb+. They are given on
|
3
|
+
# actions-triggered.
|
4
|
+
|
5
|
+
module Merit
|
6
|
+
class PointRules
|
7
|
+
include Merit::PointRulesMethods
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
score 5, :to => :user, :on => [
|
11
|
+
'comments#vote'
|
12
|
+
]
|
13
|
+
|
14
|
+
score 20, :on => [
|
15
|
+
'comments#create',
|
16
|
+
'registrations#update'
|
17
|
+
]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# 5 stars is a common ranking use case. They are not given at specified
|
2
|
+
# actions like badges, you should define a cron job to test if ranks are to be
|
3
|
+
# granted.
|
4
|
+
#
|
5
|
+
# +set_rank+ accepts:
|
6
|
+
# * :+level+ ranking level (greater is better)
|
7
|
+
# * :+to+ model or scope to check if new rankings apply
|
8
|
+
# * :+level_name+ attribute name (default is empty and results in 'level'
|
9
|
+
# attribute, if set it's appended like 'level_#{level_name}')
|
10
|
+
|
11
|
+
module Merit
|
12
|
+
class RankRules
|
13
|
+
include Merit::RankRulesMethods
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
# i stars for i chars name
|
17
|
+
(1..5).each do |i|
|
18
|
+
set_rank :level => i, :to => User do |user|
|
19
|
+
user.name.length == i
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class User
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Timestamps
|
4
|
+
|
5
|
+
has_merit
|
6
|
+
|
7
|
+
field :name
|
8
|
+
|
9
|
+
has_many :comments
|
10
|
+
|
11
|
+
attr_accessible :name
|
12
|
+
|
13
|
+
def self.find_by_id(id)
|
14
|
+
where(:_id => id).first
|
15
|
+
end
|
16
|
+
|
17
|
+
def show_badges
|
18
|
+
create_sash_if_none
|
19
|
+
badges_uniq = Badge.find_by_id(sash.badge_ids)
|
20
|
+
badges_uniq.collect{|b| "#{b.name.capitalize}#{badge_status(b)}" }.join(', ')
|
21
|
+
end
|
22
|
+
|
23
|
+
def badge_status(badge)
|
24
|
+
status = []
|
25
|
+
count = badges.select{|b| b.name == badge.name }.count
|
26
|
+
status << "level: #{badge.level}" if badge.level
|
27
|
+
status << "x#{count}" if count > 1
|
28
|
+
status.present? ? " (#{status.join(', ')})" : ''
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<%= form_for(@comment) do |f| %>
|
2
|
+
<% if @comment.errors.any? %>
|
3
|
+
<div id="error_explanation">
|
4
|
+
<h2><%= pluralize(@comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
|
5
|
+
|
6
|
+
<ul>
|
7
|
+
<% @comment.errors.full_messages.each do |msg| %>
|
8
|
+
<li><%= msg %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<div class="field">
|
15
|
+
<%= f.label :name %><br />
|
16
|
+
<%= f.text_field :name %>
|
17
|
+
</div>
|
18
|
+
<div class="field">
|
19
|
+
<%= f.label :comment %><br />
|
20
|
+
<%= f.text_area :comment %>
|
21
|
+
</div>
|
22
|
+
<div class="field">
|
23
|
+
<%= f.label :user_id %><br />
|
24
|
+
<%= f.text_field :user_id %>
|
25
|
+
</div>
|
26
|
+
<div class="actions">
|
27
|
+
<%= f.submit %>
|
28
|
+
</div>
|
29
|
+
<% end %>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<h1>Listing comments</h1>
|
2
|
+
|
3
|
+
<table>
|
4
|
+
<tr>
|
5
|
+
<th>Name</th>
|
6
|
+
<th>Comment</th>
|
7
|
+
<th>User</th>
|
8
|
+
<th>Votes</th>
|
9
|
+
<th>Vote up!</th>
|
10
|
+
<th></th>
|
11
|
+
<th></th>
|
12
|
+
<th></th>
|
13
|
+
</tr>
|
14
|
+
|
15
|
+
<% @comments.each do |comment| %>
|
16
|
+
<tr id="c_<%= comment.id %>">
|
17
|
+
<td><%= comment.name %></td>
|
18
|
+
<td><%= comment.comment %></td>
|
19
|
+
<td><%= comment.user_id %></td>
|
20
|
+
<td><%= comment.votes %></td>
|
21
|
+
<td>
|
22
|
+
<% (1..5).each do |i| %>
|
23
|
+
<%= link_to "#{i}", "/comments/#{comment.id}/vote/#{i}" %>
|
24
|
+
<% end %>
|
25
|
+
</td>
|
26
|
+
<td><%= link_to 'Show', comment %></td>
|
27
|
+
<td><%= link_to 'Edit', edit_comment_path(comment) %></td>
|
28
|
+
<td><%= link_to 'Destroy', comment, :confirm => 'Are you sure?', :method => :delete %></td>
|
29
|
+
</tr>
|
30
|
+
<% end %>
|
31
|
+
</table>
|
32
|
+
|
33
|
+
<br />
|
34
|
+
|
35
|
+
<%= link_to 'New Comment', new_comment_path %>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<p>
|
2
|
+
<b>Name:</b>
|
3
|
+
<%= @comment.name %>
|
4
|
+
</p>
|
5
|
+
|
6
|
+
<p>
|
7
|
+
<b>Comment:</b>
|
8
|
+
<%= @comment.comment %>
|
9
|
+
</p>
|
10
|
+
|
11
|
+
<p>
|
12
|
+
<b>User:</b>
|
13
|
+
<%= @comment.user_id %>
|
14
|
+
</p>
|
15
|
+
|
16
|
+
<p>
|
17
|
+
<b>Vote:</b>
|
18
|
+
<%= @comment.votes %>
|
19
|
+
</p>
|
20
|
+
|
21
|
+
|
22
|
+
<%= link_to 'Edit', edit_comment_path(@comment) %> |
|
23
|
+
<%= link_to 'Back', comments_path %>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<title>Merit Dummy app</title>
|
6
|
+
<%= stylesheet_link_tag :all %>
|
7
|
+
<%= javascript_include_tag :all %>
|
8
|
+
<%= csrf_meta_tag %>
|
9
|
+
</head>
|
10
|
+
<body>
|
11
|
+
<h1><%= link_to 'Dummy app', '/' %></h1>
|
12
|
+
|
13
|
+
<% flash.each do |name, msg| %>
|
14
|
+
<%= content_tag :p, msg, :class => (name == 'error' ? 'error' : 'notice') %>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<%= yield %>
|
18
|
+
|
19
|
+
<ul>
|
20
|
+
<li><%= link_to 'Users', users_url %></li>
|
21
|
+
<li><%= link_to 'Comments', comments_url %></li>
|
22
|
+
</ul>
|
23
|
+
</body>
|
24
|
+
</html>
|