stateful 0.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 85ae4d99568569f667a41d4b1959cc511f300dea
4
+ data.tar.gz: af2c257fdfcedf21ea5b760537c9d32c004ac74e
5
+ SHA512:
6
+ metadata.gz: 8b714fc19974ee231d8baf208c655f835a6c002fa12c984740f0a14a29449a8b3595b7e7297ecf203dc318f077ec49f7ad8c0be396b818d3b915502f5db59255
7
+ data.tar.gz: 1b6d4c06b40dad7123e6a6f6c946596ca0f1a1665cff1b0e4fd9f7e68012703def03a97c36417584ccfb8e1ac221f48a84233809907e146a6b49dd966bb1d801
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .rspec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in stateful.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 jake hoffner
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # Stateful
2
+
3
+ A simple state machine gem. Works with plain ruby objects and Mongoid. This gem aims
4
+ to keep things simple. It supports the following:
5
+
6
+ - Single state attribute/field per object
7
+ - Simple event model, just use plain ruby methods as your events and use the change_state helper to change the state.
8
+ - Supports virtual/grouped states that can be used to break down top level states into more granular sub-states.
9
+ - Utilizes ActiveSupport::Callbacks
10
+ - Simple hash structure for defining states and their possible transitions. No complicated DSL to learn.
11
+ - ActiveSupport is the only dependency.
12
+ - Very small code footprint.
13
+ - Mongoid support, automatically creates field, validations and scopes for you.
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ gem 'stateful'
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install stateful
28
+
29
+ ## Usage
30
+
31
+ ```ruby
32
+ class Project
33
+ include Stateful
34
+
35
+ attr_reader :published_at
36
+
37
+ stateful default: :new,
38
+ events: [:publish, :unpublish, :approve, :close, :mark_as_duplicate],
39
+ states: {
40
+ active: {
41
+ new: :published,
42
+ published: {
43
+ needs_approval: [:approved, :duplicate],
44
+ approved: :closed
45
+ }
46
+ },
47
+ inactive: {
48
+ closed: nil,
49
+ duplicate: nil
50
+ }
51
+ }
52
+
53
+ def publish
54
+ # change the state to needs_approval and fire publish events. The block will only be
55
+ # called if the state can successfully be changed.
56
+ change_state(:needs_approval, :publish) do
57
+ @published_at = Time.now
58
+ end
59
+ end
60
+
61
+ # use callbacks if you want
62
+ after_publish do |project|
63
+ NotificationService.notify_project_published(project)
64
+ end
65
+
66
+ # define other event methods ...
67
+ end
68
+
69
+ project = Project.new
70
+ project.active? # => true
71
+ project.new? # => true
72
+ project.published? # => false
73
+ ```
74
+
75
+ If you are using with Mongoid a field called state will automatically be created for you.
76
+
77
+ ```ruby
78
+ class Project
79
+ include Mongoid::Document # must be included first
80
+ include Stateful
81
+
82
+ field :published_at, type: Time
83
+
84
+ stateful default: :new,
85
+ events: [:publish, :unpublish, :approve, :close, :mark_as_duplicate],
86
+ states: {
87
+ active: {
88
+ new: :published,
89
+ published: {
90
+ needs_approval: [:approved, :duplicate],
91
+ approved: :closed
92
+ }
93
+ },
94
+ inactive: {
95
+ closed: nil,
96
+ duplicate: nil
97
+ }
98
+ }
99
+
100
+
101
+ # ...
102
+ end
103
+
104
+ # scopes are automatically created for you
105
+ Project.active.count
106
+ Project.published.count
107
+ ```
108
+
109
+ ## Contributing
110
+
111
+ 1. Fork it
112
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
113
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
114
+ 4. Push to the branch (`git push origin my-new-feature`)
115
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,27 @@
1
+ module Stateful
2
+ module Mongoid
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ protected
7
+
8
+ def define_state_attribute(options)
9
+ field :state, type: Symbol, default: options[:default]
10
+ validates_inclusion_of :state,
11
+ in: state_infos.keys,
12
+ message: options.has_key?(:message) ? options[:message] : 'invalid state value',
13
+ allow_nil: !!options[:allow_nil]
14
+
15
+ # configure scopes to query the attribute value
16
+ state_infos.values.each do |info|
17
+ states = info.collect_child_states
18
+ if states.length == 1
19
+ scope info.name, where(state: states.first)
20
+ else
21
+ scope info.name, where(:state.in => states)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,57 @@
1
+ module Stateful
2
+ class StateInfo
3
+ attr_reader :parent, :children, :name, :to_transitions
4
+ def initialize(state_class, parent, name, config)
5
+ @state_class = state_class
6
+ if parent
7
+ @parent = parent
8
+ parent.children << self
9
+ end
10
+
11
+ @name = name
12
+ @to_transitions = []
13
+
14
+ if config.is_a?(Hash)
15
+ @groupConfig = config
16
+ @children = []
17
+ else
18
+ @to_transitions = config ? (config.is_a?(Array) ? config : [config]) : []
19
+ end
20
+ end
21
+
22
+ def is?(state)
23
+ (@name == state or (parent and parent.is?(state)))
24
+ end
25
+
26
+ def is_group?
27
+ !!@groupConfig
28
+ end
29
+
30
+ def can_transition_to?(state)
31
+ state_info = @state_class.state_infos[state]
32
+ if is_group? or state_info.nil? or state_info.is_group?
33
+ false
34
+ else
35
+ to_transitions.include?(state)
36
+ end
37
+ end
38
+
39
+ def collect_child_states
40
+ is_group? ? children.flat_map(&:collect_child_states) : [name]
41
+ end
42
+
43
+ def expand_to_transitions
44
+ if to_transitions.any?
45
+ @to_transitions = to_transitions.flat_map do |to|
46
+ info = @state_class.state_infos[to]
47
+
48
+ if info.is_group?
49
+ info.collect_child_states
50
+ else
51
+ [info.name]
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,3 @@
1
+ module Stateful
2
+ VERSION = "0.0.1"
3
+ end
data/lib/stateful.rb ADDED
@@ -0,0 +1,142 @@
1
+ require "stateful/version"
2
+ require "stateful/state_info"
3
+
4
+ module Stateful
5
+ extend ActiveSupport::Concern
6
+ include ActiveSupport::Callbacks
7
+
8
+ included do
9
+ if defined?(Mongoid)
10
+ require 'mongoid/document'
11
+ include Stateful::Mongoid if included_modules.include?(::Mongoid::Document)
12
+ end
13
+ end
14
+
15
+ module ClassMethods
16
+ def state_infos
17
+ @state_infos ||= {}
18
+ end
19
+
20
+ def stateful(options)
21
+ options[:events] ||= []
22
+
23
+ define_method 'state_events' do
24
+ options[:events]
25
+ end
26
+
27
+ define_method 'state_info' do
28
+ self.class.state_infos[self.state]
29
+ end
30
+
31
+ define_method 'state_valid?' do
32
+ self.class.state_infos.keys.include?(state)
33
+ end
34
+
35
+ define_method 'change_state' do |new_state, options = {}, &block|
36
+ return false if new_state == state
37
+ return false unless state_info.can_transition_to?(new_state)
38
+
39
+ # convert shortcut event name to options hash
40
+ options = {event: options} if options.is_a? Symbol
41
+ options[:persist_methods] = [:persist_state, :save]
42
+
43
+ _change_state(new_state, options, &block)
44
+ end
45
+
46
+ define_method 'change_state!' do |new_state, options = {}, &block|
47
+ return false if new_state == state
48
+ raise "transition from #{state} to #{new_state} not allowed" unless state_info.can_transition_to?(new_state)
49
+
50
+ # convert shortcut event name to options hash
51
+ options = {event: options} if options.is_a? Symbol
52
+ options[:persist_methods] = [:persist_state!, :save!]
53
+ _change_state(new_state, options, &block)
54
+ end
55
+
56
+ define_method '_change_state' do |new_state, options, &block|
57
+ # do a little magic and infer the event name from the method name used to call change_state
58
+ # TODO: decide if this is too magical, for now it has been commented out.
59
+ #unless options[:event]
60
+ # calling_method = caller[1][/`.*'/][1..-2].gsub('!', '').to_sym
61
+ # options[:event] = calling_method if state_events.include? calling_method
62
+ #end
63
+
64
+ if block and block.call == false
65
+ false
66
+ else
67
+ callbacks = [:state_change]
68
+ callbacks << options[:event] if options[:event]
69
+ run_callbacks *callbacks do
70
+ self.state = new_state
71
+ if options[:persist_methods]
72
+ method = options[:persist_methods].find {|m| respond_to?(m)}
73
+ __send__(method) if method
74
+ end
75
+ if respond_to?(:persist_state)
76
+ persist_state
77
+ elsif respond_to?(:save!)
78
+ save!
79
+ end
80
+ end
81
+ true
82
+ end
83
+ end
84
+
85
+ private :_change_state
86
+
87
+ define_method 'can_transition_to?' do |new_state|
88
+ state_info.can_transition_to?(new_state)
89
+ end
90
+
91
+ # init and configure state info
92
+ init_state_info(options[:states])
93
+ state_infos.values.each do |info|
94
+ info.expand_to_transitions
95
+
96
+ define_method "#{info.name}?" do
97
+ info.is?(self.state)
98
+ end
99
+ end
100
+
101
+
102
+ define_state_attribute(options)
103
+
104
+ # define the event callbacks
105
+ events = ([:state_change] + options[:events])
106
+ define_callbacks *events
107
+
108
+ # define callback helpers
109
+ events.each do |event|
110
+ define_singleton_method "before_#{event}" do |method = nil, &block|
111
+ set_callback(event, :before, method ? method : block)
112
+ end
113
+
114
+ define_singleton_method "after_#{event}" do |method = nil, &block|
115
+ set_callback(event, :after, method ? method : block)
116
+ end
117
+ end
118
+ end
119
+
120
+ protected
121
+ def define_state_attribute(options)
122
+ define_method 'state' do
123
+ instance_variable_get(:@state) || options[:default]
124
+ end
125
+
126
+ define_method 'state=' do |val|
127
+ instance_variable_set(:@state, val)
128
+ end
129
+ end
130
+
131
+ private
132
+
133
+ def init_state_info(values, parent = nil)
134
+ values.each do |name, config|
135
+ info = state_infos[name] = Stateful::StateInfo.new(self, parent, name, config)
136
+ init_state_info(config, info) if info.is_group?
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ require 'stateful/mongoid' if defined?(Mongoid)
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require './lib/stateful'
3
+ require 'mongoid'
4
+
5
+
6
+ class Kata
7
+ include Mongoid::Document
8
+ include Stateful
9
+
10
+ stateful default: :draft, events: [:publish, :approve, :retire], states: {
11
+ :draft => :beta,
12
+ beta: {
13
+ :needs_testing => :needs_approval,
14
+ :needs_approval => :approved
15
+ },
16
+ :approved => :retired,
17
+ :retired => nil
18
+ }
19
+ end
20
+
21
+ describe Stateful::Mongoid do
22
+ let(:kata) {Kata.new}
23
+
24
+ it 'should support creating a state field' do
25
+ Kata.fields.keys.include?('state').should be_true
26
+ end
27
+
28
+ it 'should support validating state values' do
29
+ kata.state.should == :draft
30
+ kata.valid?.should be_true
31
+ kata.state = :invalid
32
+ kata.valid?.should be_false
33
+ end
34
+
35
+ it 'should support can_transition_to?' do
36
+ kata.can_transition_to?(:beta).should be_true
37
+ kata.can_transition_to?(:retired).should be_false
38
+ end
39
+
40
+ it 'should create scopes for each state and virtual state' do
41
+ Kata.beta.selector.should == {"state" => {"$in" => [:needs_testing, :needs_approval]}}
42
+ Kata.draft.selector.should == {"state" => :draft}
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ require 'mongoid'
6
+ require 'mongoid/document'
7
+
8
+ #
9
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
10
+ RSpec.configure do |config|
11
+ config.treat_symbols_as_metadata_keys_with_true_values = true
12
+ config.run_all_when_everything_filtered = true
13
+ config.filter_run :focus
14
+
15
+ # Run specs in random order to surface order dependencies. If you find an
16
+ # order dependency and want to debug it, you can fix the order by providing
17
+ # the seed, which is printed after each run.
18
+ # --seed 1234
19
+ config.order = 'random'
20
+
21
+ end
@@ -0,0 +1,158 @@
1
+ require 'spec_helper'
2
+ require './lib/stateful'
3
+
4
+ class Kata
5
+ include Stateful
6
+
7
+ attr_accessor :approved_by, :ready_score, :published_at, :state_changes
8
+
9
+ def initialize
10
+ @ready_score = 0
11
+ @state_changes = 0
12
+ end
13
+
14
+ stateful default: :draft,
15
+ events: [:publish, :unpublish, :approve, :retire],
16
+ states: {
17
+ :draft => :beta,
18
+ published: {
19
+ beta: {
20
+ :needs_feedback => [:draft, :needs_approval],
21
+ :needs_approval => [:draft, :approved]
22
+ },
23
+ :approved => :retired
24
+ },
25
+ :retired => nil
26
+ }
27
+
28
+
29
+ after_state_change do |doc|
30
+ doc.state_changes += 1
31
+ end
32
+
33
+ def vote(ready)
34
+ @ready_score += ready ? 1 : -1
35
+
36
+ # votes only affect state when in beta
37
+ if beta?
38
+ if enough_votes_for_approval? and needs_feedback?
39
+ change_state(:needs_approval)
40
+ elsif not enough_votes_for_approval? and needs_approval?
41
+ change_state(:needs_feedback)
42
+ end
43
+ end
44
+ end
45
+
46
+ def publish
47
+ change_state(enough_votes_for_approval? ? :needs_approval : :needs_feedback) do
48
+ @published_at = Time.now
49
+ end
50
+ end
51
+
52
+ def unpublish
53
+ change_state(:draft)
54
+ end
55
+
56
+ def approve(approved_by)
57
+ change_state(:approved) do
58
+ @approved_by = approved_by
59
+ end
60
+ end
61
+
62
+ def retire
63
+ change_state(:retire)
64
+ end
65
+
66
+ def enough_votes_for_approval?
67
+ ready_score >= 10
68
+ end
69
+ end
70
+
71
+ describe Kata do
72
+ let(:kata) {Kata.new}
73
+
74
+ it 'should support state_infos' do
75
+ Kata.state_infos.should_not be_nil
76
+ end
77
+
78
+ it 'should support default state' do
79
+ kata.state.should == :draft
80
+ end
81
+
82
+ it 'should support state_info' do
83
+ kata.state_info.should_not be_nil
84
+ kata.state_info.name.should == :draft
85
+ end
86
+
87
+ it 'should support simple boolean helper methods' do
88
+ kata.draft?.should be_true
89
+ kata.published?.should be_false
90
+ end
91
+
92
+ context 'change_state' do
93
+ it 'should raise error when an invalid transition state is provided' do
94
+ expect{kata.change_state(:retired)}.to raise_error
95
+ end
96
+
97
+ it 'should raise error when a group state is provided' do
98
+ expect{kata.change_state(:beta)}.to raise_error
99
+ end
100
+
101
+ it 'should return false when state is the same' do
102
+ kata.change_state(:draft).should be_false
103
+ end
104
+
105
+ it 'should support state_valid?' do
106
+ kata.state_valid?.should be_true
107
+ end
108
+
109
+ it 'should change the state when a proper state is provided' do
110
+ kata.change_state(:needs_feedback).should be_true
111
+ kata.state.should == :needs_feedback
112
+ kata.change_state(:needs_approval).should be_true
113
+ kata.state.should == :needs_approval
114
+ kata.change_state(:draft).should be_true
115
+ kata.state.should == :draft
116
+ kata.change_state(:needs_approval).should be_true
117
+ kata.change_state(:approved).should be_true
118
+ kata.state.should == :approved
119
+ end
120
+
121
+ it 'should support calling passed blocks when state is valid' do
122
+ kata.published_at.should be_nil
123
+ kata.publish
124
+ kata.published_at.should_not be_nil
125
+ end
126
+
127
+ it 'should support ingoring passed blocked when state is not valid' do
128
+ kata.approve('test')
129
+ kata.approved?.should be_false
130
+ kata.approved_by.should be_nil
131
+ end
132
+
133
+ it 'should support after callbacks methods' do
134
+ kata.publish
135
+ kata.state_changes.should == 1
136
+ end
137
+ end
138
+
139
+ describe Stateful::StateInfo do
140
+ it 'should support is?' do
141
+ Kata.state_infos[:draft].is?(:draft).should be_true
142
+ Kata.state_infos[:needs_feedback].is?(:published).should be_true
143
+ Kata.state_infos[:needs_feedback].is?(:beta).should be_true
144
+ Kata.state_infos[:approved].is?(:published).should be_true
145
+ Kata.state_infos[:approved].is?(:beta).should be_false
146
+ Kata.state_infos[:retired].is?(:beta).should be_false
147
+ end
148
+
149
+ it 'should support expanded to transitions' do
150
+ Kata.state_infos[:draft].to_transitions.should == [:needs_feedback, :needs_approval]
151
+ Kata.state_infos[:needs_approval].to_transitions.should == [:draft, :approved]
152
+
153
+ Kata.state_infos[:retired].to_transitions.should be_empty
154
+
155
+ p Kata.instance_methods
156
+ end
157
+ end
158
+ end
data/stateful.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'stateful/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "stateful"
8
+ spec.version = Stateful::VERSION
9
+ spec.authors = ["jake hoffner"]
10
+ spec.email = ["jake@codewars.com"]
11
+ spec.description = %q{A simple state machine gem}
12
+ spec.summary = %q{A simple state machine gem. Works with plain ruby objects and Mongoid. This gem aims
13
+ to keep things simple.}
14
+ spec.homepage = ""
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency 'activesupport'
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
+ spec.add_development_dependency "mongoid", "~> 3.0"
27
+
28
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stateful
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - jake hoffner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: mongoid
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ description: A simple state machine gem
84
+ email:
85
+ - jake@codewars.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - .gitignore
91
+ - Gemfile
92
+ - LICENSE.txt
93
+ - README.md
94
+ - Rakefile
95
+ - lib/stateful.rb
96
+ - lib/stateful/mongoid.rb
97
+ - lib/stateful/state_info.rb
98
+ - lib/stateful/version.rb
99
+ - spec/mongoid_spec.rb
100
+ - spec/spec_helper.rb
101
+ - spec/stateful_spec.rb
102
+ - stateful.gemspec
103
+ homepage: ''
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.0.3
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: A simple state machine gem. Works with plain ruby objects and Mongoid. This
127
+ gem aims to keep things simple.
128
+ test_files:
129
+ - spec/mongoid_spec.rb
130
+ - spec/spec_helper.rb
131
+ - spec/stateful_spec.rb