simple_interaction 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: 902b964d4821ea5d1e0857412061e40a895abb29
4
+ data.tar.gz: 3e5adefafafd26b0d589f95d7c7ac19254f05aa2
5
+ SHA512:
6
+ metadata.gz: 1369a2a7d08fb56833109cb523b117fdc5a3ce9bb6bfd5da6394154fd21f1a95c4556fa7fa7a77523ece4e5327a99ef8d981c92d2bb1d2f239f9b80484d5ba58
7
+ data.tar.gz: 1886ddbf0a775163c6d2bf838f047515c9cef69819608dd7fa28374f8de19de18ec69013740935f5d6314f829a7470d811f31e00ecf058e48816d19e024887a3
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in interaction.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ # FIX: Our test suite isn't ready to run in random order yet
8
+ gem 'minitest', '< 5.3.4'
9
+
10
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Jose Boza
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,62 @@
1
+ # Interaction
2
+
3
+ Interactions are meant to keep controllers and models or any other business logic slim (YAY).
4
+ Keep intention of class clear when using interactions, for example:
5
+ To create a user, a class should be name Users::Create.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'interaction'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install interaction
22
+
23
+ ## Usage
24
+
25
+ ```
26
+ class Klass
27
+ include Interaction
28
+
29
+ fail_with 'ErrorClass'
30
+ requires :param1, :param2
31
+
32
+ private
33
+
34
+ def run
35
+ method
36
+ rescue => e
37
+ @error = e.message
38
+ end
39
+
40
+ def method
41
+ param1 / param2
42
+ end
43
+
44
+ end
45
+
46
+ interaction = Klass.run(param1: 2, param2: 1)
47
+ interaction.success? #=> true
48
+ interaction.error #=> nil
49
+ interaction.result #=> 2
50
+
51
+ Klass.run!(param1: 1, param2: 0) #=> raises Klass::ErrorClass
52
+ Klass.run!(param1: 1, param2: 2) #=> 2
53
+
54
+ ```
55
+
56
+ ## Contributing
57
+
58
+ 1. Fork it ( https://github.com/[my-github-username]/interaction/fork )
59
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
60
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
61
+ 4. Push to the branch (`git push origin my-new-feature`)
62
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ task default: :test
6
+
7
+ Rake::TestTask.new(:test) do |test|
8
+ test.libs << "test" # here is the test_helper
9
+ test.pattern = "test/**/*_test.rb"
10
+ end
data/bin/rake ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake', 'rake')
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'interaction/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "simple_interaction"
8
+ spec.version = Interaction::VERSION
9
+ spec.authors = ["Jose Boza"]
10
+ spec.email = ["jaboza@gmail.com"]
11
+ spec.summary = %q{Keep your code clean with simple interactions}
12
+ spec.description = %q{}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ end
@@ -0,0 +1,3 @@
1
+ module Interaction
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,122 @@
1
+ require "interaction/version"
2
+
3
+ module Interaction
4
+
5
+ # = Interactions
6
+ #
7
+ # Interactions are meant to keep controllers and models slim (YAY).
8
+ # Keep intention of class clear when using interactions
9
+ # for example to create a user a class should be name Users::Create.
10
+ #
11
+ #
12
+ # example of usage:
13
+ #
14
+ # class Klass
15
+ # include Interaction
16
+ #
17
+ # requires :param1, :param2
18
+ #
19
+ # private
20
+ #
21
+ # def run
22
+ # method
23
+ # end
24
+ #
25
+ # def method
26
+ # param1 * param2
27
+ # end
28
+ #
29
+ # end
30
+ #
31
+ # Klass.run(param1: param1, param2: param2)
32
+
33
+ class InteractionError< StandardError;end
34
+ class RequirementsNotMet < InteractionError;end
35
+ class NotImplemented < InteractionError;end
36
+
37
+ module ClassMethods
38
+
39
+ attr_accessor :accessors
40
+
41
+ def accessors
42
+ @accessors ||= []
43
+ end
44
+
45
+ def error_class
46
+ @error_class ||= InteractionError
47
+ end
48
+
49
+ # class method to make sure parameters are required for the interaction to work.
50
+ def requires(*attrs)
51
+ set_accessors(attrs)
52
+ end
53
+
54
+ def fail_with(klass)
55
+ @error_class = self.const_set(klass, Class.new(InteractionError))
56
+ end
57
+
58
+ # checks if requirements are met from the requires params
59
+ # creates an instance of the interaction
60
+ # calls run on the instance
61
+ def run(**options)
62
+ @options = options
63
+ fail RequirementsNotMet.new("#{self} requires the following parameters #{accessors}") unless requirements_met?
64
+ new(@options).__send__(:run)
65
+ end
66
+
67
+ def run!(**options)
68
+ interaction = run(options)
69
+ raise error_class.new(interaction.error) unless interaction.success?
70
+ interaction.result
71
+ end
72
+
73
+ private
74
+
75
+ def requirements_met?
76
+ return true if accessors.empty?
77
+ return false unless @options.kind_of?(Hash)
78
+ accessors.each do |accessor|
79
+ break false unless @options.has_key?(accessor)
80
+ end
81
+ end
82
+
83
+ def set_accessors(attrs)
84
+ attr_accessor *attrs
85
+ accessors.unshift(*attrs)
86
+ end
87
+
88
+ end
89
+
90
+ module InstanceMethods
91
+
92
+ attr_accessor :error, :result, :error_class
93
+
94
+ def success?
95
+ error.nil?
96
+ end
97
+
98
+ private
99
+
100
+ # initializes instance and sets the instance variable for each attr_accessor from the required parameters
101
+ def initialize(**opts)
102
+
103
+ opts.select { |option, _| self.class.accessors.include?(option) }.each do |accessor, value|
104
+ __send__("#{accessor}=", value)
105
+ end
106
+ end
107
+
108
+ # run method should be overwritten on every class where interaction is included
109
+ def run
110
+ fail NotImplemented.new("`run` instance method must be implemented in class #{self.class}") unless defined?(super)
111
+ interaction_run = super
112
+ @result = interaction_run if success?
113
+ self
114
+ end
115
+
116
+ end
117
+
118
+ def self.included(receiver)
119
+ receiver.extend ClassMethods
120
+ receiver.send :prepend, InstanceMethods
121
+ end
122
+ end
@@ -0,0 +1,73 @@
1
+ require 'minitest/autorun'
2
+ require 'interaction'
3
+
4
+ class Interactor
5
+ include Interaction
6
+
7
+ fail_with 'InteractorExp'
8
+
9
+ requires :param
10
+
11
+ def run
12
+ @error = "only strings please" if param =~ /\d{1,}/
13
+ "This is the result for #{param}"
14
+ end
15
+
16
+ end
17
+
18
+ class InteractorNotImplemented
19
+ include Interaction
20
+ end
21
+
22
+ module Interaction
23
+ class InteractionTest < ::Minitest::Test
24
+
25
+ def test_private_run
26
+ assert Interactor.private_method_defined?(:run), 'instance method run should be private'
27
+ end
28
+
29
+ def test_error_class
30
+ assert_equal Interactor::InteractorExp, Interactor.error_class
31
+ end
32
+
33
+ def test_error_class_not_defined
34
+ assert_equal Interaction::InteractionError, InteractorNotImplemented.error_class
35
+ end
36
+
37
+ def test_should_require_params
38
+ assert_raises RequirementsNotMet do
39
+ Interactor.run
40
+ end
41
+ end
42
+
43
+ def test_result
44
+ assert_equal "This is the result for awesome interaction", Interactor.run(param: 'awesome interaction').result
45
+ end
46
+
47
+ def test_success
48
+ assert Interactor.run(param: 'awesome interaction').success?, 'Interactor didn\'t finish successfuly'
49
+ end
50
+
51
+ def test_run_with_bang
52
+ assert_equal "This is the result for awesome interaction", Interactor.run!(param: 'awesome interaction')
53
+ end
54
+
55
+ def test_error
56
+ interaction = Interactor.run(param: '1')
57
+ refute interaction.success?, 'Interactor didn\'t finish with an error'
58
+ assert_match interaction.error, "only strings please"
59
+ end
60
+
61
+ def test_error_with_bang
62
+ exception = assert_raises(Interactor::InteractorExp) { Interactor.run!(param: '1') }
63
+ assert_equal "only strings please", exception.message
64
+ end
65
+
66
+ def test_not_implemented
67
+ assert_raises(Interaction::NotImplemented) { InteractorNotImplemented.run(param: '1') }
68
+ end
69
+
70
+ end
71
+ end
72
+
73
+
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_interaction
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jose Boza
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: ''
42
+ email:
43
+ - jaboza@gmail.com
44
+ executables:
45
+ - rake
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - bin/rake
55
+ - interaction.gemspec
56
+ - lib/interaction.rb
57
+ - lib/interaction/version.rb
58
+ - test/interaction_test.rb
59
+ homepage: ''
60
+ licenses:
61
+ - MIT
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.2.2
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Keep your code clean with simple interactions
83
+ test_files:
84
+ - test/interaction_test.rb