GithubHelp home page GithubHelp logo

merit's Introduction

Merit

Merit adds reputation behavior to Rails apps in the form of Badges, Points, and Rankings.

Coverage Status Code Climate

Table of Contents

Installation

  1. Add gem 'merit' to your Gemfile
  2. Run rails g merit:install. This creates several migrations.
  3. Run rails g merit MODEL_NAME (e.g. user). This creates a migration and adds has_merit to MODEL_NAME.
  4. Run rake db:migrate
  5. Define badges in config/initializers/merit.rb
  6. Configure reputation rules for your application in app/models/merit/*

Badges

Creating Badges

Create badges in config/initializers/merit.rb

Merit::Badge.create! takes a hash describing the badge:

  • :id integer (required)
  • :name this is how you reference the badge (required)
  • :level (optional)
  • :description (optional)
  • :custom_fields hash of anything else you want associated with the badge (optional)

Example

# config/initializers/merit.rb

Rails.application.reloader.to_prepare do
  Merit::Badge.create!(
    id: 1,
    name: "year-member",
    description: "Active member for a year",
    custom_fields: { difficulty: :silver }
  )
end

Defining Rules

Badges can be automatically given to any resource in your application based on rules and conditions you create. Badges can also have levels, and be permanent or temporary (A temporary badge is revoked when the conditions of the badge are no longer met).

Badge rules / conditions are defined in app/models/merit/badge_rules.rb initialize block by calling grant_on with the following parameters:

  • 'controller#action' a string similar to Rails routes (required)
  • :badge_id or :badge these correspond to the :id or :name of the badge respectively
  • :level corresponds to the :level of the badge
  • :to the object's field to give the badge to. It needs a variable named @model in the associated controller action, like @post for posts_controller.rb or @comment for comments_controller.rb.
    • Can be a method name, which called over the target object should retrieve the object to badge. If it's :user for example, merit will internally call @model.user to find who to badge.
    • Can be :itself, in which case it badges the target object itself (@model).
    • Is :action_user by default, which means current_user.
  • :model_name define the model's name if it's different from the controller's (e.g. the User model for the RegistrationsController).
  • :multiple whether or not the badge may be granted multiple times. false by default.
  • :temporary whether or not the badge should be revoked if the condition no longer holds. false -badges are kept for ever- by default.
  • &block can be one of the following:
    • empty / not included: always grant the badge
    • a block which evaluates to boolean. It recieves the target object as parameter (e.g. @post if you're working with a PostsController action).
    • a block with a hash composed of methods to run on the target object and expected method return values

Examples

# app/models/merit/badge_rules.rb
grant_on 'comments#vote', badge_id: 5, to: :user do |comment|
  comment.votes.count == 5
end

grant_on ['users#create', 'users#update'], badge: 'autobiographer', temporary: true do |user|
  user.name? && user.email?
end

If your controller is under a namespace other than root (example: Api::ModelController) then for merit to find your object automatically you must specify the model class and not forget that your action is of the form namespace/models#action.

See an example of a Post model that belongs to user:

grant_on 'api/posts#create', badge: 'first-post', model_name: 'Post', to: :user do |post|
  post.user.posts.count >= 1
end

Other Actions

# Check granted badges
current_user.badges # Returns an array of badges

# Grant or remove manually
current_user.add_badge(badge.id)
current_user.rm_badge(badge.id)
# Get related entries of a given badge
Merit::Badge.find(1).users

Displaying Badges

Meritable models have a badges method which returns an array of associated badges:

<ul>
  <% current_user.badges.each do |badge| %>
    <li><%= badge.name %></li>
  <% end %>
</ul>

Points

Defining Rules

Points are given to "meritable" resources on actions-triggered, either to the action user or to the method(s) defined in the :to option. Define rules on app/models/merit/point_rules.rb:

score accepts:

  • score
    • Integer
    • Proc, or any object that accepts call which takes one argument, where the target object is passed in and the return value is used as the score.
  • :on action as string or array of strings (like controller#action, similar to Rails routes)
  • :to method(s) to send to the target object (who should be scored?)
  • :model_name (optional) to specify the model name if it cannot be guessed from the controller. (e.g. model_name: 'User' for RegistrationsController, or model_name: 'Comment' for Api::CommentsController)
  • :category (optional) to categorize earned points. default is used by default.
  • &block
    • empty (always scores)
    • a block which evaluates to boolean (recieves target object as parameter)

Examples

# app/models/merit/point_rules.rb
score 10, to: :post_creator, on: 'comments#create', category: 'comment_activity' do |comment|
  comment.title.present?
end

score 20, on: [
  'comments#create',
  'photos#create'
]

score 15, on: 'reviews#create', to: [:reviewer, :reviewed]

proc = lambda { |photo| PhotoPointsCalculator.calculate_score_for(photo) }
score proc, on: 'photos#create'

Other Actions

# Score manually
current_user.add_points(20, category: 'Optional category')
current_user.subtract_points(10, category: 'Optional category')
# Query awarded points since a given date
score_points = current_user.score_points(category: 'Optional category')
score_points.where("created_at > '#{1.month.ago}'").sum(:num_points)

Displaying Points

Meritable models have a points method which returns an integer:

<%= current_user.points(category: 'Optional category') %>

If category left empty, it will return the sum of points for every category.

<%= current_user.points %>

Rankings

A common ranking use case is 5 stars. They are not given at specified actions like badges, a cron job should be defined to test if ranks are to be granted.

Defining Rules

Define rules on app/models/merit/rank_rules.rb:

set_rank accepts:

  • :level ranking level (greater is better, Lexicographical order)
  • :to model or scope to check if new rankings apply
  • :level_name attribute name (default is empty and results in 'level' attribute, if set it's appended like 'level_#{level_name}')

Check for rules on a rake task executed in background like:

task cron: :environment do
  Merit::RankRules.new.check_rank_rules
end

Examples

set_rank level: 2, to: Committer.active do |committer|
  committer.branches > 1 && committer.followers >= 10
end

set_rank level: 3, to: Committer.active do |committer|
  committer.branches > 2 && committer.followers >= 20
end

Displaying Rankings

<%= current_user.level %>

How merit finds the target object

Merit fetches the rule’s target object (the parameter it receives) from its :model_name option, or from the controller’s instance variable.

To read it from the controller merit searches for the instance variable named after the singularized controller name. For example, a rule like:

grant_on 'comments#update', badge_id: 1 do |target_object|
  # target_object would be better named comment in this sample
end

Would make merit try to find the @comment instance variable in the CommentsController#update action. If the rule had the :model_name option specified:

grant_on 'comments#update', badge_id: 1, model_name: "Article" do |target_object|
  # target_object would be better named article in this sample
end

Merit would fetch the Article object from the database, found by the :id param sent in that update action.

If none of these methods find the target, Merit will log a no target_obj warning, with a comment to check the configuration for the rule.

Getting Notifications

You can get observers notified any time merit automatically changes reputation in your application.

It needs to implement the update method, which receives as parameter the following hash:

  • description, describes what happened. For example: "granted 5 points", "granted just-registered badge", "removed autobiographer badge".
  • sash_id, who saw it's reputation changed.
  • granted_at, date and time when the reputation change took effect.

Example code (add your observer to app/models or app/observers):

# reputation_change_observer.rb
class ReputationChangeObserver
  def update(changed_data)
    description = changed_data[:description]

    # If user is your meritable model, you can query for it doing:
    user = User.where(sash_id: changed_data[:sash_id]).first

    # When did it happened:
    datetime = changed_data[:granted_at]
  end
end
# In `config/initializers/merit.rb`
config.add_observer 'ReputationChangeObserver'

NOTE: Observers won’t get notified if you grant reputation with direct calls to add_badge or add_point.

I18n

Merit uses default messages with I18n for notify alerts. To customize your app, you can set up your locale file:

en:
  merit:
    granted_badge: "granted %{badge_name} badge"
    granted_points: "granted %{points} points"
    removed_badge: "removed %{badge_name} badge"

Uninstalling Merit

  1. Run rails d merit:install
  2. Run rails d merit MODEL_NAME (e.g. user)
  3. Run rails g merit:remove MODEL_NAME (e.g. user)
  4. Run rake db:migrate
  5. Remove merit from your Gemfile

merit's People

Contributors

adamnbowen avatar adrienpoly avatar amhol avatar bgreg avatar billychan avatar bluciam avatar caseyjenks avatar chendo avatar cristianoliveira avatar dankimio avatar dzcar avatar emoreth avatar huacnlee avatar iurifq avatar jamesjefferies avatar jasonbw avatar klinskyc avatar marcinsklodowski avatar markborcherding avatar mauriciopasquier avatar parndt avatar petergoldstein avatar polopi avatar potomak avatar ramontayag avatar ross-hunter avatar tachyons avatar tomgi avatar tute avatar yakschuss avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

merit's Issues

Conditional Point Rules

I can't seem to get conditional point rules to work. Here's an example of what I'm trying to do:

module Merit
  class PointRules
    include Merit::PointRulesMethods

    def initialize
      score 10, :on => 'quick_pick_results#create'

      score 5, :on => 'messages#create' do |message|
        message.commentable.user.id != current_user.id
      end

    end
  end
end

According to the docs, the block should be executed before awarding the points, but the points are awarded every time even if the bool should evaluate to false. Also, is there a better way to debug this than to simply try it in the app and keep checking the user's points?

Point Targets

Can you clarify point granting? For example, in the point rules you can set

:to => [:reviewer, :reviewed]

Where is the reviewer or reviewed defined? I want to grant points to a user when someone likes one of their activities. I have a likes#create action, and want to grant points to like.target.

undefined method `X' for Merit::Action:Class

I award points to the user whenever they create a new post, defined in point_rules.rb. This works perfectly, UNTIL I edit my code base in any way (be it in my controller or model). Even something like adding a simple debug "puts" statement. Once I edit my code and save, the creation of a post no longer works. Instead, it spits the following error:

undefined method `attr_accessible' for Merit::Action:Class

I'll paste the full stack trace at the bottom.

From now on, every time I try to create a post, this error will be thrown (even though the post itself will be created and saved to my db). This will keep happening until I restart my server (WEBrick). Once I restart, it will work fine until I save a change to my code again.

It's a weird bug and I'm wondering if you've ever seen this behavior before. Why would the simple act of editing my code cause this error to trigger?

Thanks for creating this awesome plugin!

Full stack trace:

NoMethodError (undefined method `attr_accessible' for Merit::Action:Class):
  merit (1.2.1) app/models/merit/action.rb:17:in `<class:Action>'
  merit (1.2.1) app/models/merit/action.rb:16:in `<module:Merit>'
  merit (1.2.1) app/models/merit/action.rb:15:in `<top (required)>'
  activesupport (3.2.9) lib/active_support/dependencies.rb:469:in `load'
  activesupport (3.2.9) lib/active_support/dependencies.rb:469:in `block in load_file'
  activesupport (3.2.9) lib/active_support/dependencies.rb:639:in `new_constants_in'
  activesupport (3.2.9) lib/active_support/dependencies.rb:468:in `load_file'
  activesupport (3.2.9) lib/active_support/dependencies.rb:353:in `require_or_load'
  activesupport (3.2.9) lib/active_support/dependencies.rb:502:in `load_missing_constant'
  activesupport (3.2.9) lib/active_support/dependencies.rb:192:in `block in const_missing'
  activesupport (3.2.9) lib/active_support/dependencies.rb:190:in `each'
  activesupport (3.2.9) lib/active_support/dependencies.rb:190:in `const_missing'
  merit (1.2.1) lib/merit/controller_extensions.rb:10:in `block in included'
  activesupport (3.2.9) lib/active_support/callbacks.rb:438:in `_run__4546742332083351921__process_action__1787335679728838539__callbacks'
  activesupport (3.2.9) lib/active_support/callbacks.rb:405:in `__run_callback'
  activesupport (3.2.9) lib/active_support/callbacks.rb:385:in `_run_process_action_callbacks'
  activesupport (3.2.9) lib/active_support/callbacks.rb:81:in `run_callbacks'
  actionpack (3.2.9) lib/abstract_controller/callbacks.rb:17:in `process_action'
  actionpack (3.2.9) lib/action_controller/metal/rescue.rb:29:in `process_action'
  actionpack (3.2.9) lib/action_controller/metal/instrumentation.rb:30:in `block in process_action'
  activesupport (3.2.9) lib/active_support/notifications.rb:123:in `block in instrument'
  activesupport (3.2.9) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
  activesupport (3.2.9) lib/active_support/notifications.rb:123:in `instrument'
  actionpack (3.2.9) lib/action_controller/metal/instrumentation.rb:29:in `process_action'
  actionpack (3.2.9) lib/action_controller/metal/params_wrapper.rb:207:in `process_action'
  activerecord (3.2.9) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
  actionpack (3.2.9) lib/abstract_controller/base.rb:121:in `process'
  actionpack (3.2.9) lib/abstract_controller/rendering.rb:45:in `process'
  actionpack (3.2.9) lib/action_controller/metal.rb:203:in `dispatch'
  actionpack (3.2.9) lib/action_controller/metal/rack_delegation.rb:14:in `dispatch'
  actionpack (3.2.9) lib/action_controller/metal.rb:246:in `block in action'
  actionpack (3.2.9) lib/action_dispatch/routing/route_set.rb:73:in `call'
  actionpack (3.2.9) lib/action_dispatch/routing/route_set.rb:73:in `dispatch'
  actionpack (3.2.9) lib/action_dispatch/routing/route_set.rb:36:in `call'
  journey (1.0.4) lib/journey/router.rb:68:in `block in call'
  journey (1.0.4) lib/journey/router.rb:56:in `each'
  journey (1.0.4) lib/journey/router.rb:56:in `call'
  actionpack (3.2.9) lib/action_dispatch/routing/route_set.rb:601:in `call'
  actionpack (3.2.9) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
  rack (1.4.1) lib/rack/etag.rb:23:in `call'
  rack (1.4.1) lib/rack/conditionalget.rb:35:in `call'
  actionpack (3.2.9) lib/action_dispatch/middleware/head.rb:14:in `call'
  actionpack (3.2.9) lib/action_dispatch/middleware/params_parser.rb:21:in `call'
  actionpack (3.2.9) lib/action_dispatch/middleware/flash.rb:242:in `call'
  rack (1.4.1) lib/rack/session/abstract/id.rb:205:in `context'
  rack (1.4.1) lib/rack/session/abstract/id.rb:200:in `call'
  actionpack (3.2.9) lib/action_dispatch/middleware/cookies.rb:341:in `call'
  activerecord (3.2.9) lib/active_record/query_cache.rb:64:in `call'
  activerecord (3.2.9) lib/active_record/connection_adapters/abstract/connection_pool.rb:479:in `call'
  actionpack (3.2.9) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
  activesupport (3.2.9) lib/active_support/callbacks.rb:405:in `_run__1657812875356723072__call__869556589823818199__callbacks'
  activesupport (3.2.9) lib/active_support/callbacks.rb:405:in `__run_callback'
  activesupport (3.2.9) lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
  activesupport (3.2.9) lib/active_support/callbacks.rb:81:in `run_callbacks'
  actionpack (3.2.9) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
  actionpack (3.2.9) lib/action_dispatch/middleware/reloader.rb:65:in `call'
  actionpack (3.2.9) lib/action_dispatch/middleware/remote_ip.rb:31:in `call'
  actionpack (3.2.9) lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call'
  actionpack (3.2.9) lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
  railties (3.2.9) lib/rails/rack/logger.rb:32:in `call_app'
  railties (3.2.9) lib/rails/rack/logger.rb:16:in `block in call'
  activesupport (3.2.9) lib/active_support/tagged_logging.rb:22:in `tagged'
  railties (3.2.9) lib/rails/rack/logger.rb:16:in `call'
  actionpack (3.2.9) lib/action_dispatch/middleware/request_id.rb:22:in `call'
  rack (1.4.1) lib/rack/methodoverride.rb:21:in `call'
  rack (1.4.1) lib/rack/runtime.rb:17:in `call'
  activesupport (3.2.9) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
  rack (1.4.1) lib/rack/lock.rb:15:in `call'
  actionpack (3.2.9) lib/action_dispatch/middleware/static.rb:62:in `call'
  railties (3.2.9) lib/rails/engine.rb:479:in `call'
  railties (3.2.9) lib/rails/application.rb:223:in `call'
  rack (1.4.1) lib/rack/content_length.rb:14:in `call'
  railties (3.2.9) lib/rails/rack/log_tailer.rb:17:in `call'
  rack (1.4.1) lib/rack/handler/webrick.rb:59:in `service'
  /Users/jon/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/webrick/httpserver.rb:138:in `service'
  /Users/jon/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/webrick/httpserver.rb:94:in `run'
  /Users/jon/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'

What's the advantage of using Ambry for Badges?

I want to discuss use of Ambry plugin for Badges domain model. Can you explain what's the advantage of using it? Why don't you use ActiveModel like with Sashes, BadgesSashes and MeritActions? I don't like having dependency of special plugin for one domain class. Would you please explain me your solution? Thanks in advance.

Undefined method `create` for Merit::Action:Class

Here's my badge rule:

grant_on 'users#update', :badge => 'Autobiographer', :temporary => true, :model_name => 'User' do |user|
   user.bio.split.size > 50
end

And when users#update is run, it's throwing the undefined method error on Merit::Action.create:

def log_merit_action
    Merit::Action.create(

Also, here's the badge in question:

Badge.create!({
  :id => 5,
  :name => 'Autobiographer',
  :description => "Write a lengthy bio"
})

Other badges I've got are working fine...so not sure why this one isn't.

FWIW, I'm using Devise.

Score to "follower" and "followed" users

Maybe it is a too easy and stupid question but I am not able to score to the follower and the followed in the same score action, it does not work.

On points_rules.rb:

score 10, :on => 'relationships#create', :to => [:follower, :followed]

Relationship model (relationship.rb):

 class Relationship < ActiveRecord::Base
  attr_accessible :followed_id

  belongs_to :follower, :class_name => "User"
  belongs_to :followed, :class_name => "User"

  validates :follower_id, :presence => true
  validates :followed_id, :presence => true
 end

Relationships_controller.rb:

def create
 @user = User.find(params[:relationship][:followed_id])
 current_user.follow!(@user)

 respond_to do |format|
  format.html { redirect_to @user }
  format.js
 end
end

What am I doing wrong?

The output in the log server is:

[merit] No object found, maybe you need a '@relationship' variable in 'relationships_controller'?
[merit] No object found, maybe you need a '@relationship' variable in 'relationships_controller'?
[merit] No object found, maybe you need a '@relationship' variable in 'relationships_controller'?
...
[merit] NoMethodError on 'nil.follower' (called from Merit::Action#other_target)
...
NoMethodError (undefined method add_points' for nil:NilClass): /Users/tetokiko/.rvm/gems/ruby-1.9.3-p327/gems/merit-1.1.2/lib/merit/judge.rb:23:inapply_points'
/Users/tetokiko/.rvm/gems/ruby-1.9.3-p327/gems/merit-1.1.2/app/models/merit/action.rb:52:in block in check_rules' /Users/tetokiko/.rvm/gems/ruby-1.9.3-p327/gems/merit-1.1.2/app/models/merit/action.rb:50:ineach'
/Users/tetokiko/.rvm/gems/ruby-1.9.3-p327/gems/merit-1.1.2/app/models/merit/action.rb:50:in `check_rules'
...

Thank you for this great gem, which is being so helpful for me.

Different amount of Points for target_object's

The following is not possible atm:

score 10, on: [ 'vote#create'], to: [:voter] 
score 5, on: [ 'vote#create'], to: [:poller] 

That would be a very desirable behaviour for me, and I hope for others too?

Manually grant a badge?

I'm adding merit to a 7+ year old community, so a lot of our users will have already met the requirements for many of the badges.

I figured I'd just create a rake task to do a one-off run through all our data and retroactively grant badges.

But how do I manually grant a badge?

how to check if current user id is nil / user is not logged in..

Hi. I get this error whenever a user is not logged in when posting a question.

[merit] no sash found on Rule#grant_or_delete_badge for action #<MeritAction id: 6, user_id: nil, action_method: "next", action_value: nil, had_errors: false, target_model: "situations", target_id: 5, processed: false, log: nil, created_at: "2013-01-24 07:23:54", updated_at: "2013-01-24 07:23:54">
[merit] no sash found on Rule#grant_or_delete_badge for action #<MeritAction id: 6, user_id: nil, action_method: "next", action_value: nil, had_errors: false, target_model: "situations", target_id: 5, processed: false, log: nil, created_at: "2013-01-24 07:23:54", updated_at: "2013-01-24 07:23:54">
[merit] no User found with id 
[merit] no sash found on Rule#grant_points

Different Types of Badges

My project needed different types of badges like Foursquare's: Foursquare, Expertise and Partner badges. Some would have levels, some would not. It's probably a matter of adding a field called type to the Badge model.

Is there a better way of adding fields to the model other than having them coded into the gem? Not too sure about the ambry gem but could it be possible to extend the Badge class and just add the fields there?

Error while trying to set_notified!

I implemented the ActiveRecord::Observer as recomended bu i am getting the error:

Mysql2::Error: Unknown column 'badges_sashes.' in 'where clause': UPDATE badges_sashes SET notified_user = 1 WHERE badges_sashes.`` IS NULL

when calling

badge_sash.set_notified!

Am I overlooking anything??

ActiveRecord::DangerousAttributeError: points

Just recently upgraded to Rails 3.2.8 and now I'm getting this error message whenever I try and do anything with my user model:

  User Load (1.2ms)  SELECT "users".* FROM "users" LIMIT 1
ActiveRecord::DangerousAttributeError: points is defined by ActiveRecord
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/attribute_methods.rb:91:in `instance_method_already_implemented?'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/attribute_methods.rb:263:in `block in define_attribute_method'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/attribute_methods.rb:260:in `each'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/attribute_methods.rb:260:in `define_attribute_method'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/attribute_methods.rb:256:in `block in define_attribute_methods'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/attribute_methods.rb:256:in `each'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.8/lib/active_model/attribute_methods.rb:256:in `define_attribute_methods'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/attribute_methods.rb:66:in `block in define_attribute_methods'
    from <internal:prelude>:10:in `synchronize'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/attribute_methods.rb:63:in `define_attribute_methods'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/attribute_methods.rb:168:in `respond_to?'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/recommendable-2.0.1/lib/recommendable/rater.rb:94:in `respond_to?'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:398:in `__run_callback'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:385:in `_run_find_callbacks'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:81:in `run_callbacks'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/base.rb:523:in `init_with'
... 3 levels...
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/querying.rb:38:in `block in find_by_sql'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/explain.rb:40:in `logging_query_plan'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/querying.rb:37:in `find_by_sql'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/relation.rb:171:in `exec_queries'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/relation.rb:160:in `block in to_a'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/explain.rb:40:in `logging_query_plan'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/relation.rb:159:in `to_a'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/relation/finder_methods.rb:378:in `find_first'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/relation/finder_methods.rb:122:in `first'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/querying.rb:5:in `first'
    from (irb):6
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/commands/console.rb:47:in `start'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/commands/console.rb:8:in `start'
    from /home/cyle/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.8/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'1.9.3p194 :007 


NoMethodError: undefined method `sash'

Hi there,
I've been having a few problems getting Merit set up and running correctly, I hope you can help, heres what I've done so far:

Rails 3.2.6
Merit 0.8.0

Add gem 'merit' to your Gemfile
Run rails g merit:install
Run rails g merit User
rake db:migrate

then in models/merit/badge_rules.rb >

grant_on 'reviews#create', :badge => 'novice', :to => :user do |review|
  review.user.reviews.count == 2
end

and initializers/merit.rb

Badge.create!({
  :id => 2,
  :name => 'novice',
  :level => '1',
  :description => 'Second Review',
  :image => 'http://testapp.s3.amazonaws.com/badges/badge-newby.png'
})

However in when trying to grant a badge manually in my console I get

1.9.2p290 :002 > Badge.find(2).grant_to(current_user)
NoMethodError: undefined method `sash' for #<User:0x007f9ab70de658>
    from /Users/gdjones/.rvm/gems/ruby-1.9.2-p290@2ndcrack/gems/activemodel-3.2.6/lib/active_model/attribute_methods.rb:407:in `method_missing'
    from /Users/gdjones/.rvm/gems/ruby-1.9.2-p290@2ndcrack/gems/activerecord-3.2.6/lib/active_record/attribute_methods.rb:149:in `method_missing'
    from /Users/gdjones/.rvm/gems/ruby-1.9.2-p290@2ndcrack/gems/merit-0.8.0/lib/merit/model_additions.rb:28:in `create_sash_if_none'
    from /Users/gdjones/.rvm/gems/ruby-1.9.2-p290@2ndcrack/gems/merit-0.8.0/app/models/badge.rb:28:in `grant_to'
    from (irb):2
    from /Users/gdjones/.rvm/gems/ruby-1.9.2-p290@2ndcrack/gems/railties-3.2.6/lib/rails/commands/console.rb:47:in `start'
    from /Users/gdjones/.rvm/gems/ruby-1.9.2-p290@2ndcrack/gems/railties-3.2.6/lib/rails/commands/console.rb:8:in `start'
    from /Users/gdjones/.rvm/gems/ruby-1.9.2-p290@2ndcrack/gems/railties-3.2.6/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

Have you seen this error before? Is there anything obvious that I'm doing wrong? Any thoughts would be most appreciated.

Creating Point Rules Outside of Controllers

Is there any interest from anyone else in creating point rules that are observable on the model rather than on controller actions"? We have a large use for creating points off events other than controller actions, such as cron jobs, Twitter streams, etc.

I was thinking of adding model callbacks to the points DSL and using observables to assign the points. Something like this:

point 25, :on => Tweet => :retweet, :to => :retweeted

Then notify_observers :retweet in the Tweet model.

Just spitballing some ideas with exactly what the DSL would be. I'm not sure if there is any interest in this, or if our case is unique.

Issue with devise and badges.

Using the following badge rule with devise.

grant_on ['registrations#create', 'registrations#update'], :badge => 'autobiographer', :model_name => 'User', :temporary => true do |user|
  user.name.present? && user.username.present?
end

The badge does not grant, and throws an error.

undefined method `delete_from' for nil:NilClass
  merit (0.7.1) lib/merit/rule.rb:43:in `grant_or_delete_badge'
  merit (0.7.1) app/models/merit_action.rb:14:in `block in check_rules'
  merit (0.7.1) app/models/merit_action.rb:13:in `each'
  merit (0.7.1) app/models/merit_action.rb:13:in `check_rules'
  merit (0.7.1) lib/merit/rules_badge.rb:57:in `block in check_new_actions'
  activerecord (3.2.3) lib/active_record/relation/delegation.rb:6:in `each'
  activerecord (3.2.3) lib/active_record/relation/delegation.rb:6:in `each'
  merit (0.7.1) lib/merit/rules_badge.rb:56:in `check_new_actions'

Installation failure

I get a PG error when running rails g merit:install

$ rails g merit:install
/Users/rod/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter.rb:1153:in `async_exec': PG::Error: ERROR:  relation "merit_actions" does not exist (ActiveRecord::StatementInvalid)
LINE 5:              WHERE a.attrelid = '"merit_actions"'::regclass

Support for controller namespace(s)

Hi!

First of all - thank you for this fine gem, I'm going to use it on my upcoming application :). But - it appears I've found a small bug (or maybe support for it wasn't ever intended?) when it comes for using multiple controllers of the same name under different namespace (eg. for frontend and backed).

Let's say I have a badge rule binded to users#update, but I also have Admin::UsersController also with update action. You can guess what happens - it blows in you face (so to speak).

In merit/lib/merit/controller_extensions.rb you have this after_filter that checks defined rules:

def rules_defined?
  action = "#{controller_name}\##{action_name}"
  AppBadgeRules[action].present? || AppPointRules[action].present?
end

What you should use is controller_path that returns full path (with namespace) and you should be fine... But apparently you won't because it goes deeper to Merit::Action class, as you save action_method and target_model without distinguishing the controller namespace.

I thought I could be able to make a quick fix for this, but I don't think it will be so quick and I don't want to break something else by accident. I hope I didn't mixed up anything :).

Best regards!

Leaderboards?

Is there an easy way to get a leaderboards over a specific time period? For example, the people with the top points in the past week.

Implement notifications for users with new badges

@starmandell suggests adding notifications for new badges for users. Notes for building it (no time these days):

We could add a BadgesSash#notified_at datetime attribute, check in the after_filter if there's a current_user, and do a test like:

new_badges = BadgesSash.where(sash_id: current_user.sash_id, notified_at: nil)

Set flashs there (or whatever), and of course update the notified_at attribute.

Currently there's only a yet undocumented BadgesSash#notified_user boolean attribute, to be used internally on each application (sending emails from an observer, for instance).


Previous solution would be wrong, since many badges may be granted per MeritAction. We would need a Merit::Notification model.

PointRules define need more feature

In sometimes may need not feature in PointRules define
For example, I need give user 30 points when him filled all field of user profiles:

Need like this:

module Merit
  class PointRules
    include Merit::PointRulesMethods

    def initialize
      # give user 30 points when fill in bio, twitter and github profiles
      score 30, :on => 'users#update', :if => Proc.new { user.bio.length > 20 and !user.twitter.blank? and !user.github.blank? }
    end
  end
end

grant_on non-standard route and model

Hi, I'm currently testing out merit and I have a couple of quirks. I'm trying to grant a badge to an Account (has many users) when users update their Profile (belongs to account). It looks like this:

grant_on "profiles#update", :badge => "complete_profile", :model_name => "Account", :to => :account do |account|
  account.profile.complete
end

This doesn't grant the badge to the Account though. I also added the correct configuration.

On my logs I can see that it's executing on case 0 on /lib/merit/rule.rb.

case block.arity
when 1 # Expects target object
  if target_obj.present?
    block.call(target_obj)
  else
     Rails.logger.warn "[merit] no target_obj found on Rule#applies?"
     false
   end
when 0
  block.call
end

Thanks for this gem! Any help on this would be appreciated.

No object found, maybe you need a '@photo' variable in 'photos_controller'?

I have the following rule that should be run when photos#complete gets loaded (which happens after a user has uploaded a few photos)...

grant_on 'photos#complete', :badge => 'Snapshooter', :temporary => false, :model_name => 'Photo' do |photo|
   photo.user.photos.count > 0
end

But in my logs I'm see: No object found, maybe you need a '@photo' variable in 'photos_controller'?

photos#complete doesn't have a @photo variable, but it does have @photos:

def complete
   @photos = Photo.active.where(:user_id => current_user.id).since(5.minutes.ago)
   redirect_to new_photo_path if @photos.blank?
end

So, what am I doing wrong here?

ActionView::Template::Error (points is defined by ActiveRecord)

Before adding the merit gem, I had a model with the points attribute (my Question model).

Now that gives this problem when trying to use a question in a rails form:

ActionView::Template::Error (points is defined by ActiveRecord)

And if I try to create a new Question:

irb(main):005:0* Question.new
ActiveRecord::DangerousAttributeError: points is defined by ActiveRecord
        from /usr/lib/ruby/gems/1.9.1/gems/activerecord-3.1.3/lib/active_record/attribute_methods.rb:38:in `instance_method_already_implemented?'
        from /usr/lib/ruby/gems/1.9.1/gems/activemodel-3.1.3/lib/active_model/attribute_methods.rb:287:in `block in define_attribute_method'
        from /usr/lib/ruby/gems/1.9.1/gems/activemodel-3.1.3/lib/active_model/attribute_methods.rb:286:in `each'
        from /usr/lib/ruby/gems/1.9.1/gems/activemodel-3.1.3/lib/active_model/attribute_methods.rb:286:in `define_attribute_method'
        from /usr/lib/ruby/gems/1.9.1/gems/activemodel-3.1.3/lib/active_model/attribute_methods.rb:282:in `block in define_attribute_methods'
        from /usr/lib/ruby/gems/1.9.1/gems/activemodel-3.1.3/lib/active_model/attribute_methods.rb:282:in `each'
        from /usr/lib/ruby/gems/1.9.1/gems/activemodel-3.1.3/lib/active_model/attribute_methods.rb:282:in `define_attribute_methods'
        from /usr/lib/ruby/gems/1.9.1/gems/activerecord-3.1.3/lib/active_record/attribute_methods.rb:14:in `define_attribute_methods'
        from /usr/lib/ruby/gems/1.9.1/gems/activerecord-3.1.3/lib/active_record/attribute_methods.rb:65:in `respond_to?'
        from /usr/lib/ruby/gems/1.9.1/gems/activerecord-3.1.3/lib/active_record/attribute_methods/read.rb:103:in `read_attribute'
        from /usr/lib/ruby/gems/1.9.1/gems/activerecord-3.1.3/lib/active_record/base.rb:1780:in `attribute_for_inspect'
        from /usr/lib/ruby/gems/1.9.1/gems/activerecord-3.1.3/lib/active_record/base.rb:1897:in `block in inspect'
        from /usr/lib/ruby/gems/1.9.1/gems/activerecord-3.1.3/lib/active_record/base.rb:1895:in `collect'
        from /usr/lib/ruby/gems/1.9.1/gems/activerecord-3.1.3/lib/active_record/base.rb:1895:in `inspect'
        from /usr/lib/ruby/gems/1.9.1/gems/railties-3.1.3/lib/rails/commands/console.rb:45:in `start'
        from /usr/lib/ruby/gems/1.9.1/gems/railties-3.1.3/lib/rails/commands/console.rb:8:in `start'
        from /usr/lib/ruby/gems/1.9.1/gems/railties-3.1.3/lib/rails/commands.rb:40:in `<top (required)>'
        from script/rails:6:in `require'
        from script/rails:6:in `<main>'irb(main):006:0> 

Is there a way to avoid this problem without renaming the "points" attribute of my models?

Greetings,

EDIT: Adding the gem 'safe_attributes' to the Gemfile fixes the problem (obtained from http://stackoverflow.com/questions/7718651/activerecorddangerousattributeerror)

EDIT 2: After adding the safe_attributes gem, there is still a problem when trying to save something over the points attribute:

NameError (undefined local variable or method `sash' for #<Question:0x00000003b9b308>):
  app/controllers/admin/games_controller.rb:96:in `block (2 levels) in create'
  app/controllers/admin/games_controller.rb:92:in `each'
  app/controllers/admin/games_controller.rb:92:in `block in create'
  app/controllers/admin/games_controller.rb:69:in `create'

EDIT 3: Adding to the Question model:

  def points
    self[:points]
  end 
  def sash
    self.points
  end 

Seems to fix it. I will continue testing this, maybe more problems can arise from this.

Various Point questions

  1. Can you get a user's points for a specific time period?
  2. Can you retrieve all a user's points, including metadata including what they got the points for, created_at, etc.

uninitialized constant Ambry::Model (NameError)

getting this after installation

/Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/activesupport-3.2.2/lib/active_support/dependencies.rb:363:in `rescue in require_or_load': uninitialized constant Ambry::Model (NameError)
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/activesupport-3.2.2/lib/active_support/dependencies.rb:343:in `require_or_load'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/activesupport-3.2.2/lib/active_support/dependencies.rb:313:in `depend_on'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/activesupport-3.2.2/lib/active_support/dependencies.rb:225:in `require_dependency'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/engine.rb:439:in `block (2 levels) in eager_load!'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/engine.rb:438:in `each'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/engine.rb:438:in `block in eager_load!'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/engine.rb:436:in `each'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/engine.rb:436:in `eager_load!'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/application/railties.rb:8:in `each'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/application/railties.rb:8:in `all'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/engine.rb:434:in `eager_load!'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/application/finisher.rb:53:in `block in <module:Finisher>'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/initializable.rb:30:in `instance_exec'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/initializable.rb:30:in `run'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/initializable.rb:55:in `block in run_initializers'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/initializable.rb:54:in `each'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/initializable.rb:54:in `run_initializers'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/application.rb:136:in `initialize!'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/railties-3.2.2/lib/rails/railtie/configurable.rb:30:in `method_missing'
    from /Users/jonpauldavies/Dropbox/sourcecode/Rails/codesonic/config/environment.rb:5:in `<top (required)>'
    from /Users/jonpauldavies/Dropbox/sourcecode/Rails/codesonic/spec/spec_helper.rb:8:in `require'
    from /Users/jonpauldavies/Dropbox/sourcecode/Rails/codesonic/spec/spec_helper.rb:8:in `block in <top (required)>'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/spork-1.0.0rc2/lib/spork.rb:24:in `prefork'
    from /Users/jonpauldavies/Dropbox/sourcecode/Rails/codesonic/spec/spec_helper.rb:6:in `<top (required)>'
    from /Users/jonpauldavies/Dropbox/sourcecode/Rails/codesonic/spec/models/user_spec.rb:23:in `require'
    from /Users/jonpauldavies/Dropbox/sourcecode/Rails/codesonic/spec/models/user_spec.rb:23:in `<top (required)>'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/rspec-core-2.8.0/lib/rspec/core/configuration.rb:698:in `load'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/rspec-core-2.8.0/lib/rspec/core/configuration.rb:698:in `block in load_spec_files'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/rspec-core-2.8.0/lib/rspec/core/configuration.rb:698:in `map'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/rspec-core-2.8.0/lib/rspec/core/configuration.rb:698:in `load_spec_files'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/rspec-core-2.8.0/lib/rspec/core/command_line.rb:22:in `run'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/rspec-core-2.8.0/lib/rspec/core/runner.rb:80:in `run_in_process'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/rspec-core-2.8.0/lib/rspec/core/runner.rb:69:in `run'
    from /Users/jonpauldavies/.rvm/gems/ruby-1.9.2-p318@codesonic/gems/rspec-core-2.8.0/lib/rspec/core/runner.rb:10:in `block in autorun'

badge rules not being called

hello, im sorry but im kinda new to this. i was wondering do i need to explicitly call a badge rule in my controller actions? i have something like...

    grant_on 'lessons#create', :badge => 'lesson-stronghold', :to => :itself do |lesson|
        lesson.user.lessons.count == 3
    end

in my badge_rules.rb. however, on a lesson create, this never gets called. ive followed the installation rules but still no luck. do i need run 'rails g merit MODEL_NAME' on my lesson model as well? i ran it for my user. the code above is to grant a badge to the user when he creates 3 lesson plans.

are there any tutorials for this gem = )
thank you!

set_rank

why set_rank doesn't work? I set set_rank :level => 4, :to => User do |user|
user.name.length > 1 but the level still is 0

reducing points

is it possible to reduce the points for inappropriate action

User Points Ranking

I want to be able to get a User's points rank of an aggregate points level, as well as a more granular level, and I'm wondering if this is possible. In particular I was wondering:

(1) Is there a built in way to get a User's points rank? I see how you can show the users with the most points (leaderboard) or show a user's points, but I can't find how to get a specific User's rank in terms of points, for example for showing this user is ranked x for points on the Users#show page

(2) I was also wondering if there was a recommended approach, if I wanted to be able to subtotal points (and calculate a points ranking) on a more granular level. For example, if I give Users points for Photos#create, but I want to be able to see how many points the User has per photo_category_id (if Photo has_one photo_category_id).

Thank you!

Accessing the whole table from models/merit/badge_rules.rb

Is there any way to access to the whole content of a table from /models/merit/badge_rules.rb?

Example:

  grant_on 'comments#create', :badge => 'commenter_number_100'  do |comment|
       comment.user.comments.count == 100 
      #this way i only see in the comments of one user, i need to know the whole amount of comments
  end

Is there a way to access from there to something like this (this does not work):
Comments.all.count == 100
#This works in Views for example.

PG::Error: Error: Value too long for type character varying(255)

My log column does overflow. I'm using merit 0.10.0.

The full error message (sorry its in german):
A ActiveRecord::StatementInvalid occurred in votes#create:

PG::Error: FEHLER:  Wert zu lang für Typ character varying(255)
: UPDATE "merit_actions" SET "log" =     points_granted:2|points_granted:2|points_granted:2|points_granted:2|points_granted:2|points_granted:2|points_granted:2|points_granted:2|points_granted:2|points_granted:2|points_granted:2|points_granted:2|points_granted:2|points_granted:2|points_granted:2|points_granted:2|', "updated_at" = '2013-01-28 12:58:33.161453' WHERE "merit_actions"."id" = 3703
activerecord (3.2.11) lib/active_record/connection_adapters/postgresql_adapter.rb:1153:in `async_exec'

tests fail as PG::Error: ERROR: relation "merit_actions" does not exist

hello. playing around with merit. simple, does the job, like it.

everything in the app looks fine but I got an error while testing.
I guess there something missing in my test_helper but I couldn't find any clue in the docs nor the code.

 Error: test_should_update_user(UsersControllerTest)
   ActiveRecord::StatementInvalid: PG::Error: ERROR:  relation "merit_actions" does not exist
   LINE 4:              WHERE a.attrelid = '"merit_actions"'::regclass
                                           ^
   :             SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
                 FROM pg_attribute a LEFT JOIN pg_attrdef d
                  ON a.attrelid = d.adrelid AND a.attnum = d.adnum
                WHERE a.attrelid = '"merit_actions"'::regclass
                  AND a.attnum > 0 AND NOT a.attisdropped
                ORDER BY a.attnum
 test/functional/users_controller_test.rb:43:in `block in <class:UsersControllerTest>'
     40:   end
      41: 
      42:   test "should update user" do
=> 43:     put :update, :id => @user.to_param, :user => @user.attributes
      44:     # assert_redirected_to user_path(assigns(:user))
      45:     assert_redirected_to user_settings_path
      46:   end

the test is simply:

  test "should update user" do
    put :update, :id => @user.to_param, :user => @user.attributes
    # assert_redirected_to user_path(assigns(:user))
    assert_redirected_to user_settings_path
  end

undefined method `badge_ids' for nil:NilClass

i followed the instruction
in app/views/users/index.html.erb

All users

<<% @users.each do |user| %>





    <td><%= link_to 'Destroy', "#{user.id}", method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>

<% end %>

Name badges points level
<%= user.name %> <%= user.show_badges %> <%= user.points %> <%= user.level %>

but NoMethodError in Users#index

Showing /Users/freshlhy/rails_projects/first_app/app/views/users/index.html.erb where line #14 raised:

undefined method `badge_ids' for nil:NilClass
Extracted source (around line #14):

11: <<% @users.each do |user| %>
12:
13: <%= user.name %>
14: <%= user.show_badges %>
15: <%= user.points %>
16: <%= user.level %>
17:

Translation missing error

I get a weird error

Congratulations! You've just earned 'translation missing: en.badges.rookie.name' badge.

After issuing a badge titled 'rookie' to a new user when they sign up. Anyone one knows what this could mean? Also, how do you actually access all the badges a user has? Doing something like

u = User.first
u.badges

Doesn't quite seem to work.

Cheers

Unicorn Error

When I push up to production my unicorn will not start. I get the following error -undefined method `setup' for Merit:Module (NoMethodError)

undefined method `scores'

Hi there, Merit has been working well for me for many months but recently I've been seeing errors when creating and viewing user badges, I've tried dropping the related tables and recreating but nothing has changed, is this something to do with the rails 3.2.9 upgrade (which I did around that time) or the gem update to 1.0.1?

Have you come across this before? Any ideas whats causing it? I found this while searching github tomatoes-app/tomatoes#63 made me think that maybe its related to a recent gem update? Thanks

1.9.3p125 :002 > Badge.find(3).grant_to(current_user, :allow_multiple => true)
(0.3ms)  BEGIN
SQL (29.6ms)  INSERT INTO "sashes" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"  [["created_at", Sat, 17    Nov 2012 15:35:21 UTC +00:00], ["updated_at", Sat, 17 Nov 2012 15:35:21 UTC +00:00]]
(0.6ms)  COMMIT
NoMethodError: undefined method `scores' for nil:NilClass
from /Users/gdjones/.rvm/gems/ruby-1.9.3-p125@edge/gems/merit-1.0.1/lib/merit/model_additions.rb:48:in `create_sash_and_scores'
from /Users/gdjones/.rvm/gems/ruby-1.9.3-p125@edge/gems/merit-1.0.1/app/models/badge.rb:56:in `sash_from'
from /Users/gdjones/.rvm/gems/ruby-1.9.3-p125@edge/gems/merit-1.0.1/app/models/badge.rb:31:in `grant_to'

UPDATE: Seems to work if I add a :score => '0' to the Badge.create in the initializers/merit.rb, you may wish to close this ticket if you don't feel that there is any issue with this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.