badgeable 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg
2
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in badgeable.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ badgeable (0.1.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ builder (2.1.2)
10
+ cucumber (0.9.2)
11
+ builder (~> 2.1.2)
12
+ diff-lcs (~> 1.1.2)
13
+ gherkin (~> 2.2.5)
14
+ json (~> 1.4.6)
15
+ term-ansicolor (~> 1.0.5)
16
+ diff-lcs (1.1.2)
17
+ factory_girl (1.3.2)
18
+ gherkin (2.2.8)
19
+ json (~> 1.4.6)
20
+ term-ansicolor (~> 1.0.5)
21
+ json (1.4.6)
22
+ rspec (2.0.0.rc)
23
+ rspec-core (= 2.0.0.rc)
24
+ rspec-expectations (= 2.0.0.rc)
25
+ rspec-mocks (= 2.0.0.rc)
26
+ rspec-core (2.0.0.rc)
27
+ rspec-expectations (2.0.0.rc)
28
+ diff-lcs (>= 1.1.2)
29
+ rspec-mocks (2.0.0.rc)
30
+ rspec-core (= 2.0.0.rc)
31
+ rspec-expectations (= 2.0.0.rc)
32
+ term-ansicolor (1.0.5)
33
+
34
+ PLATFORMS
35
+ ruby
36
+
37
+ DEPENDENCIES
38
+ badgeable!
39
+ bundler (>= 1.0.0)
40
+ cucumber
41
+ factory_girl (>= 1.3.2)
42
+ rspec (>= 2.0.0.rc)
data/README.rdoc CHANGED
@@ -15,10 +15,11 @@ and the name constant of the awarding class:
15
15
 
16
16
  class Person
17
17
  include Mongoid::Document
18
- include Badgeable
18
+ include Badgeable::Subject
19
+ embeds_many :nachos
19
20
  end
20
21
 
21
- badge "Big Eater" do
22
+ badge "Nacho Nacho Man" do
22
23
  thing Nacho
23
24
  count 40
24
25
  subject :person
@@ -27,7 +28,28 @@ and the name constant of the awarding class:
27
28
  end
28
29
  end
29
30
 
30
- would award the "Big Eater" badge to each Person who eats 40 spicy nachos.
31
+ would award the "Nacho Nacho Man" badge to each Person who eats 40
32
+ nachos, and the last one was spicy.
33
+
34
+ class Person
35
+ include Mongoid::Document
36
+ include Badgeable::Subject
37
+ references_many :meals
38
+ end
39
+
40
+ badge "Fancy Pants" do
41
+ thing Meal
42
+ subject :person
43
+ count
44
+ Meal.where(:price_cents.gte => 10000).count >= 12
45
+ end
46
+ conditions do |meal|
47
+ meal.restaurant.city != meal.eater.city
48
+ end
49
+ end
50
+
51
+ would award the "Fancy Pants" badge to the diner who has eaten 12
52
+ expensive meals where the awarding meal was out of town.
31
53
 
32
54
  You can also award arbitrary badges using your own business logic by
33
55
  calling #award_badge(badge_name) on any Badgeable instance:
@@ -35,6 +57,16 @@ calling #award_badge(badge_name) on any Badgeable instance:
35
57
  yehuda = Person.create(:name => "Yehuda Katz")
36
58
  yehuda.award_badge("Total Badass")
37
59
 
60
+ == Setup
61
+
62
+ Badge recipient classes should include Badgeable::Subject.
63
+ Extending an awarding class with Badgeable::Award will allow you
64
+ to define badge blocks in the awarding class definition. You may
65
+ also eval a separate file of badge definitions in the context of
66
+ Badgeable::Award.
67
+
68
+ When used with Rails, Badgeable will look for badging definitions
69
+ in Rails.root/lib/badges.rb
38
70
 
39
71
  == Requirements
40
72
 
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/badgeable.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/badgeable/version", __FILE__)
3
+
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "badgeable"
7
+ s.version = Badgeable::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Scott Burton"]
10
+ s.email = ["scottburton11@gmail.com"]
11
+ s.homepage = "http://rubygems.org/gems/badgeable"
12
+ s.summary = "Badgeable is an elegant DSL for awarding badges"
13
+ s.description = "Badgeable provides an elegant DSL for describing and awarding badges to your Ruby objects."
14
+
15
+ s.required_rubygems_version = ">= 1.3.6"
16
+ s.rubyforge_project = "badgeable"
17
+
18
+ s.add_development_dependency "bundler", ">= 1.0.0"
19
+ s.add_development_dependency "rspec", ">= 2.0.0.rc"
20
+ s.add_development_dependency "cucumber"
21
+ s.add_development_dependency "factory_girl", ">= 1.3.2"
22
+
23
+ s.files = `git ls-files`.split("\n")
24
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
25
+ s.require_path = 'lib'
26
+ end
@@ -0,0 +1,9 @@
1
+ Feature: Easily award badges to any Ruby class (given enough effort on your part)
2
+ In order to make somebody feel super awesome about themselves
3
+ A class that extends Badgeable::Award
4
+ Wants to award a badge recipient after they've created a certain number of them
5
+
6
+ Scenario: A restaurant meal awards the "Hog Wild" badge to a regular diner
7
+ Given a Meal awards the "Hog Wild" badge to an Diner after 3 times
8
+ When a diner creates 3 meals
9
+ Then the diner should have the "Hog Wild" badge
@@ -0,0 +1,20 @@
1
+ Given /^a Meal awards the "([^\"]*)" badge to an? Diner after (\d+) times$/ do |badge_name, threshold|
2
+ Meal.class_eval %Q{
3
+ badge "#{badge_name}" do
4
+ count #{threshold}
5
+ subject :diner
6
+ thing Meal
7
+ end
8
+ }
9
+ end
10
+
11
+ When /^a diner creates (\d+) meals$/ do |num|
12
+ @diner = Diner.create
13
+ num.to_i.times do
14
+ @diner.meals.create
15
+ end
16
+ end
17
+
18
+ Then /^the diner should have the "([^\"]*)" badge$/ do |badge_name|
19
+ @diner.should have_badge_named(badge_name)
20
+ end
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__),'..', '..', 'lib'))
3
+
4
+ require 'cucumber'
5
+ require 'rspec/expectations'
6
+ require 'badgeable'
7
+
8
+ Mongoid.configure do |config|
9
+ config.master = Mongo::Connection.new.db("badgeable_test")
10
+ end
11
+
12
+ # factory_girl Factory definitions
13
+ Dir[(File.expand_path(File.dirname(__FILE__), "..") + "spec/factories/**/*.rb").to_s].each {|factory| require factory}
14
+
15
+ Dir[(File.expand_path(File.dirname(__FILE__)) + "test_models/**/*.rb")].each {|model| require model }
16
+
17
+ Before do
18
+ Mongoid.master.collections.select{|c| !c.name.starts_with?("system")}.each(&:drop)
19
+ end
@@ -0,0 +1,5 @@
1
+ class Diner
2
+ include Mongoid::Document
3
+ include Badgeable::Subject
4
+ references_many :meals
5
+ end
@@ -0,0 +1,5 @@
1
+ class Meal
2
+ include Mongoid::Document
3
+ extend Badgeable::Award
4
+ referenced_in :diner, :inverse_of => :meals
5
+ end
@@ -0,0 +1,44 @@
1
+ module Badgeable
2
+ module Award
3
+ # Configure a class to automatically award badges after creation.
4
+ # Assign a badge name and a block with configuration
5
+ # directives.
6
+ #
7
+ # Valid directives:
8
+ #
9
+ # thing (Required) a class constant in this namespace that
10
+ # awards the badge.
11
+ # subject (Optional, default = :user) a symbol that references
12
+ # the object to which the badge is awarded. This should
13
+ # be a related object that includes Badgeable, and will
14
+ # usually have referenced_in :thing, belongs_to :thing etc.
15
+ # count (Optional, default = 1) either an integer threshold value
16
+ # of :things related to :subject, or a block. If a block
17
+ # is given, the created instance of :thing is passed as
18
+ # the first block argument, and the block must return
19
+ # return true for the badge to be awarded.
20
+ # conditions (Optional) provide a block; if your block returns
21
+ # returns true, the badge is awarded. The first block
22
+ # argument is the created instance of :thing. The
23
+ # conditions directive may be called any number of times,
24
+ # and all conditions and the count block must return true.
25
+ # Also note that the conditions and count directives are
26
+ # evaluated separately.
27
+ #
28
+ # See README for usage examples
29
+ #
30
+ def badge(name, &block)
31
+ config = Badgeable::Config.new
32
+ config.instance_eval(&block)
33
+ method_name = name.titleize.gsub(/\s/, "").underscore
34
+ config.klass.class_eval do
35
+ set_callback :create, :after, "award_#{method_name}_badge".to_sym
36
+ define_method "award_#{method_name}_badge".to_sym, Proc.new {
37
+ if config.conditions_array.all? {|p| p.call(self) }
38
+ self.send(config.subject_name).award_badge(name)
39
+ end
40
+ }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,42 +1,10 @@
1
1
  module Badgeable
2
2
  class Config
3
- # Configure a class to automatically award badges after creation.
4
- # Assign a badge name and a block with configuration
5
- # directives.
6
- #
7
- # Valid directives:
8
- #
9
- # thing (Required) a class constant in this namespace that
10
- # awards the badge.
11
- # subject (Optional, default = :user) a symbol that references
12
- # the object to which the badge is awarded. This should
13
- # be a related object that includes Badgeable, and will
14
- # usually have referenced_in :thing, belongs_to :thing etc.
15
- # count (Optional, default = 1) either an integer threshold value
16
- # of :things related to :subject, or a block. If a block
17
- # is given, the created instance of :thing is passed as
18
- # the first block argument, and the block must return
19
- # return true for the badge to be awarded.
20
- # conditions (Optional) provide a block; if your block returns
21
- # returns true, the badge is awarded. Works in
22
- # conjunction with #count
23
- #
24
- # See README for usage examples
25
- #
26
- def self.badge(name, &block)
27
- config = new
28
- config.instance_eval(&block)
29
- method_name = name.titleize.gsub(/\s/, "").underscore
30
- config.klass.class_eval do
31
- set_callback :create, :after, "award_#{method_name}_badge".to_sym
32
- define_method "award_#{method_name}_badge".to_sym, Proc.new {
33
- if config.conditions_array.all? {|p| p.call(self) }
34
- self.send(config.subject_name).award_badge(name)
35
- end
36
- }
37
- end
3
+
4
+ class << self
5
+ attr_accessor :badge_definitions
38
6
  end
39
-
7
+
40
8
  attr_reader :threshold, :klass, :conditions_array, :subject_name
41
9
 
42
10
  def initialize
@@ -71,8 +39,6 @@ module Badgeable
71
39
  @conditions_array << Proc.new {|instance|
72
40
  block.call(instance)
73
41
  }
74
- end
75
-
76
-
42
+ end
77
43
  end
78
44
  end
@@ -0,0 +1,5 @@
1
+ module Badgeable
2
+ class Dsl
3
+ extend Badgeable::Award
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ module Badgeable
2
+ class Railtie < ::Rails::Railtie
3
+ initializer "badgeable.load_badges" do
4
+ Badgeable::Config.badge_definitions = Pathname.new("#{Rails.root}/lib/badges.rb")
5
+ Badgeable::Dsl.class_eval(File.read(Badgeable::Config.badge_definitions))
6
+ end
7
+ end
8
+ end
@@ -14,5 +14,19 @@ module Badgeable
14
14
  def has_badge_named?(name)
15
15
  badges.map(&:name).include?(name)
16
16
  end
17
+
18
+ def self.included(receiver)
19
+ receiver.class_eval %Q{
20
+ references_many :badges, :stored_as => :array, :class_name => "Badgeable::Badge", :inverse_of => :#{receiver.to_s.tableize}
21
+ }
22
+
23
+ Badgeable::Badge.class_eval %Q{
24
+ references_many :#{receiver.to_s.tableize}, :inverse_of => :badges, :stored_as => :array, :inverse_of => :badges
25
+
26
+ def recipients
27
+ #{receiver}.where(:badge_ids => id)
28
+ end
29
+ }
30
+ end
17
31
  end
18
32
  end
@@ -0,0 +1,3 @@
1
+ module Badgeable
2
+ VERSION = "0.1.1"
3
+ end
data/lib/badgeable.rb CHANGED
@@ -2,27 +2,12 @@ require 'active_support/core_ext'
2
2
  require 'active_support/callbacks'
3
3
  require 'active_support/inflector'
4
4
  require 'mongoid'
5
+ require 'badgeable/award'
5
6
  require 'badgeable/badge'
6
7
  require 'badgeable/config'
8
+ require 'badgeable/dsl'
7
9
  require 'badgeable/subject'
10
+ require 'badgeable/version'
11
+ require 'badgeable/railtie' if defined?(Rails)
8
12
 
9
- module Badgeable
10
-
11
- VERSION = "0.0.1"
12
-
13
- def self.included(receiver)
14
- receiver.class_eval %Q{
15
- references_many :badges, :stored_as => :array, :class_name => "Badgeable::Badge", :inverse_of => :#{receiver.to_s.tableize}
16
- }
17
-
18
- Badgeable::Badge.class_eval %Q{
19
- references_many :#{receiver.to_s.tableize}, :inverse_of => :badges, :stored_as => :array, :inverse_of => :badges
20
-
21
- def recipients
22
- #{receiver}.where(:badge_ids => id)
23
- end
24
- }
25
-
26
- receiver.send :include, Badgeable::Subject
27
- end
28
- end
13
+ module Badgeable; end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: badgeable
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
- - 0
9
7
  - 1
10
- version: 0.0.1
8
+ - 1
9
+ version: 0.1.1
11
10
  platform: ruby
12
11
  authors:
13
12
  - Scott Burton
@@ -15,10 +14,68 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-10-08 00:00:00 -07:00
17
+ date: 2010-10-09 00:00:00 -07:00
19
18
  default_executable:
20
- dependencies: []
21
-
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: bundler
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 0
31
+ - 0
32
+ version: 1.0.0
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 2
45
+ - 0
46
+ - 0
47
+ - rc
48
+ version: 2.0.0.rc
49
+ type: :development
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: cucumber
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ type: :development
63
+ version_requirements: *id003
64
+ - !ruby/object:Gem::Dependency
65
+ name: factory_girl
66
+ prerelease: false
67
+ requirement: &id004 !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ segments:
73
+ - 1
74
+ - 3
75
+ - 2
76
+ version: 1.3.2
77
+ type: :development
78
+ version_requirements: *id004
22
79
  description: Badgeable provides an elegant DSL for describing and awarding badges to your Ruby objects.
23
80
  email:
24
81
  - scottburton11@gmail.com
@@ -29,14 +86,28 @@ extensions: []
29
86
  extra_rdoc_files: []
30
87
 
31
88
  files:
89
+ - .gitignore
90
+ - Gemfile
91
+ - Gemfile.lock
92
+ - LICENSE
93
+ - README.rdoc
94
+ - Rakefile
95
+ - badgeable.gemspec
96
+ - features/award_badges.feature
97
+ - features/step_definitions/badging_steps.rb
98
+ - features/support/env.rb
99
+ - features/support/test_models/diner.rb
100
+ - features/support/test_models/meal.rb
101
+ - lib/badgeable.rb
102
+ - lib/badgeable/award.rb
32
103
  - lib/badgeable/badge.rb
33
104
  - lib/badgeable/config.rb
105
+ - lib/badgeable/dsl.rb
106
+ - lib/badgeable/railtie.rb
34
107
  - lib/badgeable/subject.rb
35
- - lib/badgeable.rb
36
- - LICENSE
37
- - README.rdoc
108
+ - lib/badgeable/version.rb
38
109
  has_rdoc: true
39
- homepage: http://github.com/scottburton11/badgeable
110
+ homepage: http://rubygems.org/gems/badgeable
40
111
  licenses: []
41
112
 
42
113
  post_install_message:
@@ -49,7 +120,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
49
120
  requirements:
50
121
  - - ">="
51
122
  - !ruby/object:Gem::Version
52
- hash: 3
53
123
  segments:
54
124
  - 0
55
125
  version: "0"
@@ -58,7 +128,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
128
  requirements:
59
129
  - - ">="
60
130
  - !ruby/object:Gem::Version
61
- hash: 23
62
131
  segments:
63
132
  - 1
64
133
  - 3
@@ -66,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
135
  version: 1.3.6
67
136
  requirements: []
68
137
 
69
- rubyforge_project:
138
+ rubyforge_project: badgeable
70
139
  rubygems_version: 1.3.7
71
140
  signing_key:
72
141
  specification_version: 3