state-handler 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.
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color -fd
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pulse-meter.gemspec
4
+ gemspec
@@ -0,0 +1,28 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ state-handler (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.3)
10
+ rake (0.9.2.2)
11
+ rspec (2.10.0)
12
+ rspec-core (~> 2.10.0)
13
+ rspec-expectations (~> 2.10.0)
14
+ rspec-mocks (~> 2.10.0)
15
+ rspec-core (2.10.0)
16
+ rspec-expectations (2.10.0)
17
+ diff-lcs (~> 1.1.3)
18
+ rspec-mocks (2.10.1)
19
+ timecop (0.3.5)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ rake
26
+ rspec
27
+ state-handler!
28
+ timecop
data/README ADDED
File without changes
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '../lib/'))
3
+
4
+ require 'ostruct'
5
+ require 'state-handler'
6
+
7
+ class ResponseHandler
8
+ include StateHandler::Mixing
9
+
10
+ code 200 => :success
11
+ code 404 => :not_found
12
+ code 401 => :unauthorized
13
+
14
+ match /5\d\d/ => :error
15
+ end
16
+
17
+ response = OpenStruct.new(:code => 500)
18
+ ResponseHandler.new(response) do |r|
19
+ r.at :not_found, :unauthorized do
20
+ puts 'Another response handled'
21
+ end
22
+
23
+ r.success { puts 'Request executed' }
24
+ r.error { puts 'Request failed' }
25
+ end
@@ -0,0 +1,7 @@
1
+ require 'state-handler/version'
2
+ require 'state-handler/mixing'
3
+
4
+ module StateHandler
5
+ class UnexpectedState < Exception
6
+ end
7
+ end
@@ -0,0 +1,92 @@
1
+ module StateHandler
2
+ module Mixing
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ base.class_attribute :mapping, :patterns
6
+ base.mapping, base.patterns = {}, {}
7
+ end
8
+
9
+ attr_reader :response
10
+
11
+ def initialize(response, &block)
12
+ raise ArgumentError unless response.respond_to?(:code)
13
+ @response, @blocks = response, {}
14
+ exec(&block) if block_given?
15
+ end
16
+
17
+ def exec(&block)
18
+ # map blocks
19
+ yield(self)
20
+
21
+ if state
22
+ @blocks[state].call
23
+ else
24
+ self.class.patterns.each do |s, regex|
25
+ @blocks[s].call if @response.code.to_s =~ regex
26
+ end
27
+ end
28
+ end
29
+
30
+ def at(*args, &block)
31
+ args.each { |s| @blocks[s.to_sym] = block }
32
+ end
33
+
34
+ def state
35
+ self.class.mapping.keys.each.find { |state| find_mapped(state) }
36
+ end
37
+
38
+ def find_mapped(state)
39
+ if self.class.mapping[state].kind_of?(Array)
40
+ self.class.mapping[state].include?(@response.code.to_i)
41
+ else
42
+ self.class.mapping[state] == @response.code.to_i
43
+ end
44
+ end
45
+
46
+ def method_missing(name, &block)
47
+ state = name.to_s.gsub(/\?/, '').to_sym
48
+
49
+ if name.to_s.end_with?('?')
50
+ raise StateHandler::UnexpectedState, "Got: #{state.inspect}" unless self.class.mapping[state]
51
+ find_mapped(state)
52
+ elsif block_given?
53
+ @blocks[state] = block
54
+ end
55
+ end
56
+
57
+ module ClassMethods
58
+ def class_attribute(*attrs)
59
+ attrs.each do |name|
60
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
61
+ def self.#{name}() nil end
62
+ def self.#{name}?() !!#{name} end
63
+
64
+ def self.#{name}=(val)
65
+ singleton_class.class_eval do
66
+ define_method(:#{name}) { val }
67
+ end
68
+ val
69
+ end
70
+ RUBY
71
+ end
72
+ end
73
+
74
+ def map(&block)
75
+ class_eval(&block)
76
+ end
77
+
78
+ def match(regexp)
79
+ self.patterns[regexp.values.first] = regexp.keys.first
80
+ end
81
+
82
+ def code(*codes, &block)
83
+ if codes.first.kind_of?(Hash)
84
+ self.mapping[codes.first.values.first] = codes.first.keys.first
85
+ elsif block_given?
86
+ self.mapping[yield] = codes
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+
@@ -0,0 +1,3 @@
1
+ module StateHandler
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ describe StateHandler::Mixing do
4
+ before do
5
+ class DummyResponse
6
+ include StateHandler::Mixing
7
+
8
+ map do
9
+ code 200 => :enabled
10
+ code 400 => :false
11
+
12
+ match /5\d\d/ => :error
13
+
14
+ code 401, 402 do
15
+ :bad_params
16
+ end
17
+ end
18
+ end
19
+ class DuplicateDeclarationResponse
20
+ include StateHandler::Mixing
21
+
22
+ map do
23
+ code 200 => :fuck_up
24
+ end
25
+ end
26
+ end
27
+ subject {
28
+ DuplicateDeclarationResponse.new(response_struct)
29
+ DummyResponse.new(response_struct)
30
+ }
31
+
32
+ describe "#exec" do
33
+ let(:response_struct) { OpenStruct.new(:code => 401) }
34
+ class ExecException < Exception
35
+ end
36
+
37
+ it "should call block from 'at' notation with multiply states" do
38
+ expect {
39
+ subject.exec do |r|
40
+ r.at :bad_params, :success, :fake do
41
+ raise ExecException
42
+ end
43
+ r.test { raise ArgumentError }
44
+ end
45
+ }.should raise_error(ExecException)
46
+ end
47
+
48
+ describe "#match" do
49
+ let(:response_struct) { OpenStruct.new(:code => 500) }
50
+ it "should call matched block" do
51
+ expect {
52
+ subject.exec do |r|
53
+ r.bad_params do
54
+ raise ExecException
55
+ end
56
+
57
+ r.error do
58
+ raise ArgumentError
59
+ end
60
+ end
61
+ }.should raise_error(ArgumentError)
62
+ end
63
+ end
64
+
65
+ let(:response_struct) { OpenStruct.new(:code => 401) }
66
+ it "should call block" do
67
+ expect {
68
+ subject.exec do |r|
69
+ r.bad_params do
70
+ raise ExecException
71
+ end
72
+
73
+ r.success do
74
+ raise ArgumentError
75
+ end
76
+ end
77
+ }.should raise_error(ExecException)
78
+ end
79
+ end
80
+
81
+ describe "#codes" do
82
+ let(:response_struct) { OpenStruct.new(:code => 401) }
83
+
84
+ its(:bad_params?) { should be_true }
85
+ end
86
+
87
+ describe "#code" do
88
+ let(:response_struct) { OpenStruct.new(:code => 200) }
89
+
90
+ its(:enabled?) { should be_true }
91
+ its(:false?) { should be_false }
92
+ its(:state) { should == :enabled }
93
+
94
+ it "should raise UnexpectedState error" do
95
+ expect { subject.disabled? }.should raise_error(StateHandler::UnexpectedState)
96
+ end
97
+ end
98
+ end
99
+
100
+
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ $:.unshift File.expand_path('../../lib/', __FILE__)
4
+
5
+ ROOT = File.expand_path('../..', __FILE__)
6
+
7
+ require 'state-handler'
8
+
9
+ Bundler.require(:default, :test, :development)
10
+
11
+ Dir['spec/support/**/*.rb'].each{|f| require File.join(ROOT, f) }
12
+ Dir['spec/shared_examples/**/*.rb'].each{|f| require File.join(ROOT,f)}
13
+ Dir['spec/shared_context/**/*.rb'].each{|f| require File.join(ROOT,f)}
14
+
15
+ RSpec.configure do |config|
16
+ config.filter_run :focus => true
17
+ config.run_all_when_everything_filtered = true
18
+ end
19
+
20
+
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/state-handler/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.author = "Maxim Filipovich"
6
+ gem.email = "fatumka@gmail.com"
7
+ gem.description = %q{State handler per object params}
8
+ gem.summary = %q{State handler per object params}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "state-handler"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = StateHandler::VERSION
17
+
18
+ gem.add_development_dependency('rake')
19
+ gem.add_development_dependency('rspec')
20
+ gem.add_development_dependency('timecop')
21
+ end
22
+
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: state-handler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Maxim Filipovich
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-14 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &70106966478060 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70106966478060
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &70106966477640 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70106966477640
36
+ - !ruby/object:Gem::Dependency
37
+ name: timecop
38
+ requirement: &70106966477220 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70106966477220
47
+ description: State handler per object params
48
+ email: fatumka@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .rspec
54
+ - Gemfile
55
+ - Gemfile.lock
56
+ - README
57
+ - examples/response.rb
58
+ - lib/state-handler.rb
59
+ - lib/state-handler/mixing.rb
60
+ - lib/state-handler/version.rb
61
+ - spec/lib/state-handler/mixing_spec.rb
62
+ - spec/spec_helper.rb
63
+ - state-handler.gemspec
64
+ homepage: ''
65
+ licenses: []
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 1.8.10
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: State handler per object params
88
+ test_files:
89
+ - spec/lib/state-handler/mixing_spec.rb
90
+ - spec/spec_helper.rb