merit 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/Gemfile +5 -0
  2. data/Gemfile.lock +13 -2
  3. data/README.md +72 -53
  4. data/TESTING.txt +7 -2
  5. data/lib/generators/merit/templates/merit.rb +1 -1
  6. data/lib/merit.rb +2 -1
  7. data/lib/merit/controller_extensions.rb +2 -2
  8. data/lib/merit/model_additions.rb +9 -2
  9. data/lib/merit/models/mongo_mapper/merit_action.rb +1 -0
  10. data/lib/merit/models/mongoid/merit_action.rb +13 -0
  11. data/lib/merit/models/mongoid/sash.rb +14 -0
  12. data/lib/merit/rule.rb +4 -2
  13. data/lib/merit/rules_rank.rb +7 -2
  14. data/merit.gemspec +5 -2
  15. data/test/dummy-mongoid/Rakefile +7 -0
  16. data/test/dummy-mongoid/app/controllers/application_controller.rb +7 -0
  17. data/test/dummy-mongoid/app/controllers/comments_controller.rb +90 -0
  18. data/test/dummy-mongoid/app/controllers/registrations_controller.rb +15 -0
  19. data/test/dummy-mongoid/app/controllers/users_controller.rb +67 -0
  20. data/test/dummy-mongoid/app/helpers/application_helper.rb +2 -0
  21. data/test/dummy-mongoid/app/models/comment.rb +17 -0
  22. data/test/dummy-mongoid/app/models/merit/badge_rules.rb +49 -0
  23. data/test/dummy-mongoid/app/models/merit/point_rules.rb +20 -0
  24. data/test/dummy-mongoid/app/models/merit/rank_rules.rb +24 -0
  25. data/test/dummy-mongoid/app/models/user.rb +30 -0
  26. data/test/dummy-mongoid/app/views/comments/_form.html.erb +29 -0
  27. data/test/dummy-mongoid/app/views/comments/edit.html.erb +6 -0
  28. data/test/dummy-mongoid/app/views/comments/index.html.erb +35 -0
  29. data/test/dummy-mongoid/app/views/comments/new.html.erb +5 -0
  30. data/test/dummy-mongoid/app/views/comments/show.html.erb +23 -0
  31. data/test/dummy-mongoid/app/views/layouts/application.html.erb +24 -0
  32. data/test/dummy-mongoid/app/views/users/_form.html.erb +22 -0
  33. data/test/dummy-mongoid/app/views/users/edit.html.erb +6 -0
  34. data/test/dummy-mongoid/app/views/users/index.html.erb +26 -0
  35. data/test/dummy-mongoid/app/views/users/new.html.erb +5 -0
  36. data/test/dummy-mongoid/app/views/users/show.html.erb +18 -0
  37. data/test/dummy-mongoid/config.ru +4 -0
  38. data/test/dummy-mongoid/config/application.rb +22 -0
  39. data/test/dummy-mongoid/config/boot.rb +10 -0
  40. data/test/dummy-mongoid/config/environment.rb +5 -0
  41. data/test/dummy-mongoid/config/environments/development.rb +25 -0
  42. data/test/dummy-mongoid/config/environments/production.rb +49 -0
  43. data/test/dummy-mongoid/config/environments/test.rb +35 -0
  44. data/test/dummy-mongoid/config/initializers/backtrace_silencers.rb +7 -0
  45. data/test/dummy-mongoid/config/initializers/inflections.rb +10 -0
  46. data/test/dummy-mongoid/config/initializers/merit.rb +37 -0
  47. data/test/dummy-mongoid/config/initializers/mime_types.rb +5 -0
  48. data/test/dummy-mongoid/config/initializers/secret_token.rb +7 -0
  49. data/test/dummy-mongoid/config/initializers/session_store.rb +8 -0
  50. data/test/dummy-mongoid/config/locales/en.yml +5 -0
  51. data/test/dummy-mongoid/config/mongoid.yml +14 -0
  52. data/test/dummy-mongoid/config/routes.rb +9 -0
  53. data/test/dummy-mongoid/db/seeds.rb +17 -0
  54. data/test/dummy-mongoid/public/404.html +26 -0
  55. data/test/dummy-mongoid/public/422.html +26 -0
  56. data/test/dummy-mongoid/public/500.html +26 -0
  57. data/test/dummy-mongoid/public/favicon.ico +0 -0
  58. data/test/dummy-mongoid/public/javascripts/application.js +2 -0
  59. data/test/dummy-mongoid/public/javascripts/controls.js +965 -0
  60. data/test/dummy-mongoid/public/javascripts/dragdrop.js +974 -0
  61. data/test/dummy-mongoid/public/javascripts/effects.js +1123 -0
  62. data/test/dummy-mongoid/public/javascripts/prototype.js +6001 -0
  63. data/test/dummy-mongoid/public/javascripts/rails.js +191 -0
  64. data/test/dummy-mongoid/public/stylesheets/.gitkeep +0 -0
  65. data/test/dummy-mongoid/public/stylesheets/scaffold.css +56 -0
  66. data/test/dummy-mongoid/script/rails +6 -0
  67. data/test/dummy/config/initializers/merit.rb +1 -1
  68. data/test/integration/navigation_test.rb +1 -1
  69. data/test/merit_unit_test.rb +3 -0
  70. data/test/test_helper.rb +20 -3
  71. 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,2 @@
1
+ module ApplicationHelper
2
+ 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,6 @@
1
+ <h1>Editing comment</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Show', @comment %> |
6
+ <%= link_to 'Back', comments_path %>
@@ -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,5 @@
1
+ <h1>New comment</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Back', comments_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>