activecrew 0.1.4

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a45d0ac6c7ba04c2eee3d07464b4a33eb8929527
4
+ data.tar.gz: d451a7a7ada0b52d1cab74db53f5545f0b48f1bc
5
+ SHA512:
6
+ metadata.gz: fdea905f162d86ff05391ed80582cbfaa5c092f2a2741847a65f0dc73273d63bfb61f987f614cba8b43d0466374ec0ebbffe09ea56d0939723a29669bcf51af7
7
+ data.tar.gz: 487f78c9e5cc76199a3f0841ad956f4c38aaa7170cc2a6cda9aed1e0dc6ccbd656e66dcd437afe897ab71201fa3e1b45c7f57c6f4c215ab9c8dedf983ffac01c
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /.idea
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.1
4
+ before_install: gem install bundler -v 1.13.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in activecommand.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Max Kazarin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,41 @@
1
+ # ActiveCrew
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/activecrew.svg)](https://badge.fury.io/rb/activecrew)
4
+ [![Code Climate](https://codeclimate.com/github/maxkazar/activecrew/badges/gpa.svg)](https://codeclimate.com/github/maxkazar/activecrew)
5
+ [![Build Status](https://travis-ci.org/maxkazar/activecrew.svg)](https://travis-ci.org/maxkazar/activecrew)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'activecrew'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install activecrew
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/maxkazar/activecrew.
36
+
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'active_crew/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'activecrew'
8
+ spec.version = ActiveCrew::VERSION
9
+ spec.authors = ['Max Kazarin']
10
+ spec.email = ['maxkazargm@gmail.com']
11
+
12
+ spec.summary = %q{Steroid command pattern.}
13
+ spec.description = %q{Steroid command pattern.}
14
+ spec.homepage = 'https://github.com/maxkazar/activecrew'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_development_dependency 'bundler', '~> 1.10'
21
+ spec.add_development_dependency 'rake', '~> 10.0'
22
+ spec.add_development_dependency 'rspec'
23
+ spec.add_development_dependency 'actionpack', '~> 4.0'
24
+
25
+ spec.add_dependency 'activesupport', '~> 4.0'
26
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "activecrew"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,46 @@
1
+ require 'rubygems'
2
+
3
+ require 'active_support/all'
4
+ require 'active_crew/version'
5
+ require 'active_crew/configuration'
6
+ require 'active_crew/concerns/authorizable'
7
+ require 'active_crew/concerns/chainable'
8
+ require 'active_crew/concerns/commandable'
9
+ require 'active_crew/concerns/combinable'
10
+ require 'active_crew/concerns/respondable'
11
+ require 'active_crew/concerns/measurable'
12
+ require 'active_crew/concerns/validatable'
13
+ require 'active_crew/base'
14
+ require 'active_crew/backends'
15
+ require 'active_crew/responders'
16
+
17
+ require 'active_crew/extender' if defined? ActionController
18
+
19
+ module ActiveCrew
20
+ class << self
21
+ # Getter for shared global objects
22
+ attr_reader :configuration
23
+
24
+ # Returns the global [Configuration](ActiveCrew/Configuration) object.
25
+ #
26
+ # @example
27
+ # ActiveCrew.configuration.responder = :pusher
28
+ def configuration
29
+ @configuration ||= ActiveCrew::Configuration.new
30
+ end
31
+
32
+ # Yields the global configuration to a block.
33
+ # @yield [Configuration] global configuration
34
+ #
35
+ # @example
36
+ # ActiveCrew.configure do |config|
37
+ # config.responder = :fayer
38
+ # end
39
+ def configure
40
+ yield configuration if block_given?
41
+
42
+ Backends.create
43
+ Responders.create
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,45 @@
1
+ module ActiveCrew
2
+ module Backends
3
+ autoload :InlineBackend, 'active_crew/backends/inline_backend'
4
+ autoload :SidekiqBackend, 'active_crew/backends/sidekiq_backend'
5
+
6
+ class << self
7
+ attr_reader :default
8
+
9
+ def create
10
+ @default = "ActiveCrew::Backends::#{backend.to_s.classify}Backend".constantize
11
+ rescue NameError
12
+ raise ArgumentError, "Unsupported backend #{backend} for active command."
13
+ end
14
+
15
+ def enqueue(name, invoker, *args)
16
+ default.enqueue name, serialize(invoker), *args
17
+ end
18
+
19
+ def dequeue(name, invoker, *args)
20
+ command = create_command name, deserialize(invoker), *args
21
+ command.execute if command.can_execute?
22
+ end
23
+
24
+ private
25
+
26
+ def backend
27
+ ActiveCrew.configuration.backend
28
+ end
29
+
30
+ def serialize(invoker)
31
+ [invoker.class.name, invoker.id.to_s]
32
+ end
33
+
34
+ def deserialize(invoker)
35
+ invoker[0].constantize.find invoker[1]
36
+ end
37
+
38
+ def create_command(name, invoker, *args)
39
+ "#{name.classify}Command".constantize.new invoker, *args
40
+ rescue NameError
41
+ raise ArgumentError, "Unsupported command #{name} for active command."
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,19 @@
1
+ module ActiveCrew
2
+ module Backends
3
+ class InlineBackend
4
+ class Queue
5
+ def size
6
+ 0
7
+ end
8
+ end
9
+
10
+ def self.enqueue(*args)
11
+ ActiveCrew::Backends.dequeue *args
12
+ end
13
+
14
+ def self.queue(command_name)
15
+ Queue.new
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ module ActiveCrew
2
+ module Backends
3
+ class SidekiqBackend
4
+ include Sidekiq::Worker
5
+
6
+ class << self
7
+ def enqueue(*args)
8
+ Sidekiq::Client.push 'class' => self,
9
+ 'queue' => queue_name(args.first),
10
+ 'args' => args
11
+ end
12
+
13
+ def queue_name(command_name)
14
+ command_name[/^(.*)\/[^\/]*$/, 1].underscore.gsub(/\//, '_')
15
+ end
16
+
17
+ def queue(command_name)
18
+ Sidekiq::Queue.new queue_name command_name
19
+ end
20
+ end
21
+
22
+ def perform(*args)
23
+ ActiveCrew::Backends.dequeue *args
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,50 @@
1
+ module ActiveCrew
2
+
3
+ # Sidekiq Command class. Implements command pattern for Sidekiq.
4
+ # Helps to deconstruct application into micro services with command interface.
5
+ #
6
+ # Command class file structure with two micro services (mailer and users):
7
+ #
8
+ # app
9
+ # commands
10
+ # mailer
11
+ # deliver_command.rb
12
+ # users
13
+ # create_command.rb
14
+ #
15
+ # Command queues will be the following:
16
+ #
17
+ # mailer
18
+ # users
19
+ #
20
+ class Base
21
+ prepend Chainable
22
+ prepend Combinable
23
+ prepend Validatable
24
+ prepend Measurable
25
+ prepend Respondable
26
+ prepend Authorizable
27
+
28
+ include Commandable
29
+
30
+ attr_reader :invoker, :options, :context
31
+
32
+ def initialize(invoker, context = {})
33
+ @invoker = invoker
34
+ # Should only symbolize key for
35
+ @context = ActiveSupport::HashWithIndifferentAccess.new context
36
+ @options = @context[:options] || {}
37
+ end
38
+
39
+ def name
40
+ @name ||= self.class.name.underscore.gsub(/_command/, '')
41
+ end
42
+
43
+ def execute
44
+ perform
45
+ end
46
+
47
+ def perform
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,17 @@
1
+ module ActiveCrew
2
+ class AuthorizationError < Exception; end
3
+
4
+ module Authorizable
5
+ extend ActiveSupport::Concern
6
+
7
+ def execute
8
+ raise AuthorizationError unless can_execute?
9
+
10
+ super
11
+ end
12
+
13
+ def can_execute?
14
+ invoker.can? name, options
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ module ActiveCrew
2
+ module Chainable
3
+ def chain
4
+ @chain ||= @context[:chain] || []
5
+ end
6
+
7
+ def commands(*args)
8
+ options = args.extract_options!
9
+ add_to_chain args
10
+ execute_chain options
11
+ end
12
+
13
+ def execute
14
+ super
15
+ execute_chain
16
+ end
17
+
18
+ private
19
+
20
+ def add_to_chain(commands)
21
+ chain.concat commands
22
+ end
23
+
24
+ def execute_chain(options = nil)
25
+ return unless chain.present?
26
+
27
+ name = chain.shift
28
+ if name.is_a? Array
29
+ name.each { |name| command name, options }
30
+ else
31
+ command name, options, chain: chain
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ module ActiveCrew
2
+ # Combinable behavior helps to combine command executions into one command execution
3
+ module Combinable
4
+ def execute
5
+ super
6
+ execute_combine_commands
7
+ end
8
+
9
+ def combine_command(name, options = {})
10
+ combine_command_options = combine_commands[name] ||= {}
11
+ options.each do |key, value|
12
+ combine_command_value = combine_command_options[key] ||= []
13
+ combine_command_value << value unless combine_command_value.include? value
14
+ end
15
+ end
16
+
17
+ def combine_commands
18
+ @combine_commands ||= {}
19
+ end
20
+
21
+ private
22
+
23
+ def execute_combine_commands
24
+ combine_commands.each { |name, options| command name, options }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ module ActiveCrew
2
+ module Commandable
3
+ def command(name, options = {}, context = {})
4
+ Backends.enqueue name, invoker, @context.merge(options: options).merge(context)
5
+ end
6
+
7
+ def backend
8
+ Backends.default
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ module ActiveCrew
2
+ class MeasurerError < Exception; end
3
+
4
+ module Measurable
5
+ extend ActiveSupport::Concern
6
+
7
+ private
8
+
9
+ def execute
10
+ started_at = Time.current
11
+
12
+ super
13
+
14
+ measurer.measure self, Time.current - started_at if measurer
15
+ end
16
+
17
+ def has_measurer?
18
+ measurer.present?
19
+ end
20
+
21
+ def measurer
22
+ return @measurer if defined? @measurer
23
+
24
+ measurer_name = ActiveCrew.configuration.measurer
25
+ @measurer = measurer_name && measurer_name.to_s.classify.constantize
26
+ rescue NameError
27
+ raise MeasurerError, "Unsupported measurer #{measurer_name} for active command."
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,21 @@
1
+ module ActiveCrew
2
+ class CommandError < Exception; end
3
+
4
+ module Respondable
5
+ def respond_with(model)
6
+ Responders.respond_with name, invoker, context, model
7
+ end
8
+
9
+ def respond_fail(*args)
10
+ fail CommandError, I18n.t(*args)
11
+ end
12
+
13
+ def execute
14
+ super
15
+ rescue Interrupt
16
+ raise
17
+ rescue CommandError
18
+ respond_with $ERROR_INFO
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ module ActiveCrew
2
+ module Validatable
3
+ extend ActiveSupport::Concern
4
+
5
+ def validate!
6
+
7
+ end
8
+
9
+ def execute
10
+ validate!
11
+
12
+ super
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ module ActiveCrew
2
+ class Configuration
3
+ attr_accessor :responder, :backend, :measurer
4
+
5
+ def initialize
6
+ @responder = :inline
7
+ @backend = :inline
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module ActiveCrew
2
+ module Extender
3
+ def command(name, options)
4
+ context = { options: options }
5
+
6
+ ActiveCrew::Responders.init context, request
7
+ ActiveCrew::Backends.enqueue name, current_user, context
8
+ end
9
+ end
10
+ end
11
+
12
+ ActionController::Base.include ActiveCrew::Extender
@@ -0,0 +1,30 @@
1
+ module ActiveCrew
2
+ module Responders
3
+ autoload :InlineResponder, 'active_crew/responders/inline_responder'
4
+ autoload :FayeResponder, 'active_crew/responders/faye_responder'
5
+
6
+ class << self
7
+ attr_reader :default
8
+
9
+ def create
10
+ @default = "ActiveCrew::Responders::#{responder.to_s.classify}Responder".constantize
11
+ rescue NameError
12
+ raise ArgumentError, "Unsupported responder #{responder} for active command."
13
+ end
14
+
15
+ def init(context, request)
16
+ default.init(context, request) if default.respond_to? :init
17
+ end
18
+
19
+ def respond_with(name, invoker, context, model)
20
+ default.respond name, invoker, context, model
21
+ end
22
+
23
+ private
24
+
25
+ def responder
26
+ ActiveCrew.configuration.responder
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,109 @@
1
+ module ActiveCrew
2
+ module Responders
3
+ # FayeResponderError class.
4
+ class FayeResponderError < Exception; end
5
+
6
+ # FayeConnectionError class.
7
+ class FayeConnectionError < Exception; end
8
+
9
+ # ActiveCrew Faye responder.
10
+ module FayeResponder
11
+ module_function
12
+
13
+ MAX_RETRIES = 5
14
+
15
+ def init(context, request)
16
+ context[:session] = request.headers['x-session-token']
17
+ end
18
+
19
+ # Respond with faye
20
+ def respond(name, invoker, context, model)
21
+ request channel: channel(invoker),
22
+ data: payload(name, invoker, context, model),
23
+ ext: { publish_key: config[:publish_key] }
24
+ end
25
+
26
+ def request(message)
27
+ retries = 0
28
+
29
+ begin
30
+ validate RestClient.post url, message.to_json, header
31
+ rescue FayeResponderError
32
+ retries += 1
33
+ raise FayeConnectionError $ERROR_INFO unless retries < MAX_RETRIES
34
+
35
+ retry
36
+ rescue FayeConnectionError
37
+ Rails.logger.fatal $ERROR_INFO.message
38
+ end
39
+ end
40
+
41
+ # @return Invoker channel name
42
+ def channel(invoker)
43
+ "/#{invoker.class.to_s.underscore}/#{invoker.id}"
44
+ end
45
+
46
+ # @return Faye request payload
47
+ def payload(name, invoker, context, model)
48
+ {
49
+ invoker: serialize_invoker(invoker),
50
+ session: context[:session],
51
+ command: name,
52
+ status: status(model),
53
+ response: serialize(model)
54
+ }
55
+ end
56
+
57
+ def serialize_invoker(invoker)
58
+ serialize invoker, serializer: "#{invoker.class}::InvokerSerializer".constantize
59
+ end
60
+
61
+ # Serialize payload
62
+ def serialize(model, options = {})
63
+ return { base: model.message } if model.is_a? CommandError
64
+
65
+ if model.is_a?(Array) || model.errors.empty?
66
+ ActiveModelSerializers::SerializableResource.new(model, options).serializable_hash
67
+ else
68
+ ActiveModelSerializers::SerializableResource.new(model.errors, options.merge(root: 'errors')).serializable_hash[:errors]
69
+ end
70
+ end
71
+
72
+ def status(model)
73
+ model.is_a?(Array) || !model.is_a?(CommandError) && model.valid? ? :success : :failure
74
+ end
75
+
76
+ # @return Faye request header
77
+ def header
78
+ {
79
+ 'Content-Type' => 'application/json',
80
+ 'Pragma' => 'no-cache',
81
+ 'X-Requested-With' => 'XMLHttpRequest'
82
+ }
83
+ end
84
+
85
+ # Validate faye response
86
+ def validate(response)
87
+ fail FayeResponderError, response.code unless response.code == 200
88
+
89
+ response = JSON.parse(response)[0].symbolize_keys
90
+ fail FayeResponderError, response[:error] unless response[:successful]
91
+ end
92
+
93
+ def url
94
+ "http://#{config[:host]}/faye"
95
+ end
96
+
97
+ def config
98
+ return @config if defined? @config
99
+
100
+ @config = YAML.load(ERB.new(File.new(config_path).read).result)[Rails.env]
101
+ @config = (@config || {}).symbolize_keys
102
+ end
103
+
104
+ def config_path
105
+ File.join(Rails.root, 'config', 'faye.yml')
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,9 @@
1
+ module ActiveCrew
2
+ module Responders
3
+ module InlineResponder
4
+ def self.respond(*, model)
5
+ model
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveCrew
2
+ VERSION = '0.1.4'
3
+ end
@@ -0,0 +1 @@
1
+ require 'active_crew'
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activecrew
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - Max Kazarin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-11-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.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
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
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
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: actionpack
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '4.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '4.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: activesupport
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '4.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '4.0'
83
+ description: Steroid command pattern.
84
+ email:
85
+ - maxkazargm@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".travis.yml"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - activecrew.gemspec
97
+ - bin/console
98
+ - bin/setup
99
+ - lib/active_crew.rb
100
+ - lib/active_crew/backends.rb
101
+ - lib/active_crew/backends/inline_backend.rb
102
+ - lib/active_crew/backends/sidekiq_backend.rb
103
+ - lib/active_crew/base.rb
104
+ - lib/active_crew/concerns/authorizable.rb
105
+ - lib/active_crew/concerns/chainable.rb
106
+ - lib/active_crew/concerns/combinable.rb
107
+ - lib/active_crew/concerns/commandable.rb
108
+ - lib/active_crew/concerns/measurable.rb
109
+ - lib/active_crew/concerns/respondable.rb
110
+ - lib/active_crew/concerns/validatable.rb
111
+ - lib/active_crew/configuration.rb
112
+ - lib/active_crew/extender.rb
113
+ - lib/active_crew/responders.rb
114
+ - lib/active_crew/responders/faye_responder.rb
115
+ - lib/active_crew/responders/inline_responder.rb
116
+ - lib/active_crew/version.rb
117
+ - lib/activecrew.rb
118
+ homepage: https://github.com/maxkazar/activecrew
119
+ licenses:
120
+ - MIT
121
+ metadata: {}
122
+ post_install_message:
123
+ rdoc_options: []
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ requirements: []
137
+ rubyforge_project:
138
+ rubygems_version: 2.6.7
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: Steroid command pattern.
142
+ test_files: []