auxiliary_rails 0.2.0 → 0.3.0
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 +4 -4
- data/.gitlab-ci.yml +26 -0
- data/.rubocop.yml +11 -2
- data/.rubocop_todo.yml +13 -9
- data/.yardopts +5 -0
- data/CHANGELOG.md +19 -2
- data/CONTRIBUTING.md +0 -6
- data/Gemfile.lock +20 -16
- data/README.md +204 -3
- data/auxiliary_rails.gemspec +7 -5
- data/bin/rubocop +3 -0
- data/lib/auxiliary_rails.rb +5 -3
- data/lib/auxiliary_rails/application/command.rb +56 -0
- data/lib/auxiliary_rails/application/error.rb +10 -0
- data/lib/auxiliary_rails/application/form.rb +30 -0
- data/lib/auxiliary_rails/application/query.rb +78 -0
- data/lib/auxiliary_rails/cli.rb +19 -5
- data/lib/auxiliary_rails/concerns/performable.rb +141 -0
- data/lib/auxiliary_rails/version.rb +1 -1
- data/lib/generators/auxiliary_rails/install_commands_generator.rb +5 -0
- data/lib/generators/auxiliary_rails/install_generator.rb +0 -1
- data/lib/generators/auxiliary_rails/templates/application_error_template.rb +1 -1
- data/lib/generators/auxiliary_rails/templates/commands/application_command_template.rb +1 -1
- data/lib/generators/auxiliary_rails/templates/commands/command_template.rb +2 -2
- data/lib/generators/auxiliary_rails/templates/commands/commands.en_template.yml +5 -0
- data/templates/rails/elementary.rb +45 -9
- metadata +43 -11
- data/lib/auxiliary_rails/abstract_command.rb +0 -95
- data/lib/auxiliary_rails/abstract_error.rb +0 -7
- data/lib/generators/auxiliary_rails/install_rubocop_generator.rb +0 -29
- data/lib/generators/auxiliary_rails/templates/rubocop/rubocop_auxiliary_rails_template.yml +0 -65
- data/lib/generators/auxiliary_rails/templates/rubocop/rubocop_template.yml +0 -11
data/auxiliary_rails.gemspec
CHANGED
@@ -18,14 +18,14 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.license = 'MIT'
|
19
19
|
|
20
20
|
if spec.respond_to?(:metadata)
|
21
|
-
spec.metadata['homepage_uri'] =
|
22
|
-
spec.metadata['source_code_uri'] =
|
23
|
-
spec.metadata['changelog_uri'] =
|
21
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
22
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
23
|
+
spec.metadata['changelog_uri'] = "#{spec.homepage}/releases"
|
24
24
|
else
|
25
25
|
raise 'RubyGems 2.0 or newer is required'
|
26
26
|
end
|
27
27
|
|
28
|
-
spec.files
|
28
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
29
29
|
`git ls-files -z`.split("\x0").reject do |f|
|
30
30
|
f.match(%r{^(test|spec|features)/})
|
31
31
|
end
|
@@ -38,10 +38,12 @@ Gem::Specification.new do |spec|
|
|
38
38
|
spec.add_development_dependency 'rails', '>= 5.2', '< 7'
|
39
39
|
spec.add_development_dependency 'rake'
|
40
40
|
spec.add_development_dependency 'rspec', '~> 3.8'
|
41
|
-
spec.add_development_dependency 'rubocop'
|
41
|
+
spec.add_development_dependency 'rubocop', '0.79'
|
42
42
|
spec.add_development_dependency 'rubocop-performance'
|
43
43
|
spec.add_development_dependency 'rubocop-rspec'
|
44
44
|
|
45
|
+
spec.add_runtime_dependency 'dry-core'
|
46
|
+
spec.add_runtime_dependency 'dry-initializer'
|
45
47
|
spec.add_runtime_dependency 'dry-initializer-rails'
|
46
48
|
spec.add_runtime_dependency 'thor'
|
47
49
|
end
|
data/bin/rubocop
ADDED
data/lib/auxiliary_rails.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
require 'auxiliary_rails/
|
2
|
-
require 'auxiliary_rails/
|
3
|
-
require 'auxiliary_rails/
|
1
|
+
require 'auxiliary_rails/application/command'
|
2
|
+
require 'auxiliary_rails/application/form'
|
3
|
+
require 'auxiliary_rails/application/error'
|
4
|
+
require 'auxiliary_rails/application/query'
|
5
|
+
require 'auxiliary_rails/railtie'
|
4
6
|
require 'auxiliary_rails/version'
|
5
7
|
|
6
8
|
module AuxiliaryRails
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
require 'auxiliary_rails/concerns/performable'
|
3
|
+
require 'dry-initializer-rails'
|
4
|
+
|
5
|
+
module AuxiliaryRails
|
6
|
+
module Application
|
7
|
+
# @abstract
|
8
|
+
class Command
|
9
|
+
extend Dry::Initializer
|
10
|
+
include AuxiliaryRails::Concerns::Performable
|
11
|
+
|
12
|
+
class << self
|
13
|
+
# @!method param(name, options = {})
|
14
|
+
# Defines param using <tt>Dry::Initializer</tt> format.
|
15
|
+
#
|
16
|
+
# @see Dry::Initializer
|
17
|
+
# @see https://dry-rb.org/gems/dry-initializer/3.0/params-and-options/
|
18
|
+
#
|
19
|
+
# @param name [Symbol]
|
20
|
+
# @param options [Hash]
|
21
|
+
|
22
|
+
# @!method option(name, options = {})
|
23
|
+
# Defines option using <tt>Dry::Initializer</tt> format.
|
24
|
+
|
25
|
+
# @see Dry::Initializer
|
26
|
+
# @see https://dry-rb.org/gems/dry-initializer/3.0/params-and-options/
|
27
|
+
#
|
28
|
+
# @param name [Symbol]
|
29
|
+
# @param options [Hash]
|
30
|
+
|
31
|
+
# Initializes command with <tt>args</tt> and runs <tt>#call</tt> method.
|
32
|
+
#
|
33
|
+
# @return [self]
|
34
|
+
def call(*args)
|
35
|
+
new(*args).call
|
36
|
+
end
|
37
|
+
|
38
|
+
# Defines `scope` for <tt>ActiveModel::Translation</tt>
|
39
|
+
#
|
40
|
+
# @return [Symbol]
|
41
|
+
def i18n_scope
|
42
|
+
:commands
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
# Shortcut reader for attributes defined by <tt>Dry::Initializer</tt>
|
49
|
+
#
|
50
|
+
# @return [Hash]
|
51
|
+
def arguments
|
52
|
+
self.class.dry_initializer.attributes(self)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
module AuxiliaryRails
|
4
|
+
module Application
|
5
|
+
# @abstract
|
6
|
+
class Form
|
7
|
+
include ActiveModel::Model
|
8
|
+
include ActiveModel::Attributes
|
9
|
+
include ActiveModel::AttributeAssignment
|
10
|
+
include AuxiliaryRails::Concerns::Performable
|
11
|
+
|
12
|
+
class << self
|
13
|
+
# Defines `scope` for <tt>ActiveModel::Translation</tt>
|
14
|
+
#
|
15
|
+
# @return [Symbol]
|
16
|
+
def i18n_scope
|
17
|
+
:forms
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Indicates object persistence.
|
22
|
+
#
|
23
|
+
# In case of form as performable object that means that form
|
24
|
+
# was executed with success.
|
25
|
+
def persisted?
|
26
|
+
performable_status == true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'dry/core/class_attributes'
|
2
|
+
require 'dry-initializer'
|
3
|
+
|
4
|
+
module AuxiliaryRails
|
5
|
+
module Application
|
6
|
+
class Query
|
7
|
+
extend Dry::Core::ClassAttributes
|
8
|
+
extend Dry::Initializer
|
9
|
+
|
10
|
+
defines :default_relation
|
11
|
+
|
12
|
+
option :relation, default: proc { nil }
|
13
|
+
|
14
|
+
def self.call(*args)
|
15
|
+
new(*args).call
|
16
|
+
end
|
17
|
+
|
18
|
+
def call
|
19
|
+
ensure_proper_relation_types!
|
20
|
+
|
21
|
+
perform
|
22
|
+
|
23
|
+
query
|
24
|
+
end
|
25
|
+
|
26
|
+
def perform
|
27
|
+
raise NotImplementedError
|
28
|
+
end
|
29
|
+
|
30
|
+
def method_missing(method_name, *args, &block)
|
31
|
+
super unless query.respond_to?(method_name)
|
32
|
+
|
33
|
+
query.send(method_name, *args, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def respond_to_missing?(method_name, include_private = false)
|
37
|
+
query.respond_to?(method_name) || super
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# rubocop:disable Metrics/AbcSize, Style/GuardClause
|
43
|
+
def ensure_proper_relation_types!
|
44
|
+
if self.class.default_relation.nil?
|
45
|
+
error!('Undefined `default_relation`')
|
46
|
+
end
|
47
|
+
if !queriable_object?(self.class.default_relation)
|
48
|
+
error!('Invalid class of `default_relation`')
|
49
|
+
end
|
50
|
+
if !relation.nil? && !queriable_object?(relation)
|
51
|
+
error!('Invalid class of `relation` option')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
# rubocop:enable Metrics/AbcSize, Style/GuardClause
|
55
|
+
|
56
|
+
def error!(message = nil)
|
57
|
+
raise error_class,
|
58
|
+
"`#{self.class}` #{message || 'Query raised an error.'}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def error_class
|
62
|
+
AuxiliaryRails::Application::Error
|
63
|
+
end
|
64
|
+
|
65
|
+
def queriable_object?(object)
|
66
|
+
object.is_a?(ActiveRecord::Relation)
|
67
|
+
end
|
68
|
+
|
69
|
+
def query(scoped_query = nil)
|
70
|
+
@query ||= (relation || self.class.default_relation)
|
71
|
+
|
72
|
+
@query = scoped_query unless scoped_query.nil?
|
73
|
+
|
74
|
+
@query
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/auxiliary_rails/cli.rb
CHANGED
@@ -6,6 +6,10 @@ module AuxiliaryRails
|
|
6
6
|
|
7
7
|
TEMPLATES_DIR =
|
8
8
|
File.expand_path("#{__dir__}/../../templates/")
|
9
|
+
REPOSITORY_URL =
|
10
|
+
'https://raw.githubusercontent.com/ergoserv/' \
|
11
|
+
'auxiliary_rails/develop/templates'
|
12
|
+
.freeze
|
9
13
|
|
10
14
|
desc 'new APP_PATH', 'Create Rails application from template'
|
11
15
|
long_desc <<-LONGDESC
|
@@ -17,20 +21,30 @@ module AuxiliaryRails
|
|
17
21
|
option :database,
|
18
22
|
default: 'postgresql',
|
19
23
|
type: :string
|
20
|
-
option :
|
24
|
+
option :template,
|
21
25
|
default: 'elementary',
|
22
26
|
type: :string
|
27
|
+
option :develop,
|
28
|
+
default: false,
|
29
|
+
type: :boolean
|
23
30
|
def new(app_path)
|
24
31
|
run "rails new #{app_path} " \
|
25
|
-
'--skip-action-cable --skip-coffee --skip-test ' \
|
26
32
|
"--database=#{options[:database]} " \
|
27
|
-
"--template=#{rails_template_path(options[:
|
33
|
+
"--template=#{rails_template_path(options[:template])}" \
|
34
|
+
'--skip-action-cable ' \
|
35
|
+
'--skip-coffee ' \
|
36
|
+
'--skip-test ' \
|
37
|
+
'--skip-webpack-install'
|
28
38
|
end
|
29
39
|
|
30
40
|
private
|
31
41
|
|
32
|
-
def rails_template_path(
|
33
|
-
|
42
|
+
def rails_template_path(template)
|
43
|
+
if options[:develop] == true
|
44
|
+
"#{REPOSITORY_URL}/rails/#{template}.rb"
|
45
|
+
else
|
46
|
+
"#{TEMPLATES_DIR}/rails/#{template}.rb"
|
47
|
+
end
|
34
48
|
end
|
35
49
|
end
|
36
50
|
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module AuxiliaryRails
|
4
|
+
module Concerns
|
5
|
+
module Performable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
include ActiveModel::Validations
|
8
|
+
|
9
|
+
class_methods do
|
10
|
+
def call(*args)
|
11
|
+
new(*args).call
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(options = {})
|
16
|
+
ensure_empty_status!
|
17
|
+
|
18
|
+
if options[:validate!] == true
|
19
|
+
validate!
|
20
|
+
elsif options[:validate] != false && invalid?
|
21
|
+
return failure!(:validation_failed)
|
22
|
+
end
|
23
|
+
|
24
|
+
perform
|
25
|
+
|
26
|
+
ensure_execution!
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
# Describes business logic.
|
31
|
+
#
|
32
|
+
# Method <b>should always</b> return <tt>success!</tt>
|
33
|
+
# or <tt>failure!</tt> methods in order pro provide further
|
34
|
+
# correct method chaining.
|
35
|
+
#
|
36
|
+
# @abstract
|
37
|
+
# @return [self]
|
38
|
+
def perform
|
39
|
+
raise NotImplementedError
|
40
|
+
end
|
41
|
+
|
42
|
+
def failure?
|
43
|
+
status?(:failure)
|
44
|
+
end
|
45
|
+
|
46
|
+
def status?(value)
|
47
|
+
ensure_execution!
|
48
|
+
|
49
|
+
performable_status == value&.to_sym
|
50
|
+
end
|
51
|
+
|
52
|
+
def success?
|
53
|
+
status?(:success)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Provides ability to execude block of the code depending on
|
57
|
+
# command execution status
|
58
|
+
#
|
59
|
+
# @param status [Symol] Desired command status
|
60
|
+
# @param &_block Code to be executed if status matches
|
61
|
+
# @return [self]
|
62
|
+
def on(status, &_block)
|
63
|
+
ensure_execution!
|
64
|
+
|
65
|
+
return self unless status?(status)
|
66
|
+
|
67
|
+
yield(self) if block_given?
|
68
|
+
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
# Shortcut for <tt>ActiveRecord::Base.transaction</tt>
|
73
|
+
def transaction(&block)
|
74
|
+
ActiveRecord::Base.transaction(&block) if block_given?
|
75
|
+
end
|
76
|
+
|
77
|
+
protected
|
78
|
+
|
79
|
+
attr_accessor :performable_status
|
80
|
+
|
81
|
+
# @raise [AuxiliaryRails::Application::Error]
|
82
|
+
# Error happens if command contains any errors.
|
83
|
+
# @return [nil]
|
84
|
+
def ensure_empty_errors!
|
85
|
+
return if errors.empty?
|
86
|
+
|
87
|
+
error!("`#{self.class}` contains errors.")
|
88
|
+
end
|
89
|
+
|
90
|
+
def ensure_empty_status!
|
91
|
+
return if performable_status.nil?
|
92
|
+
|
93
|
+
error!("`#{self.class}` was already executed.")
|
94
|
+
end
|
95
|
+
|
96
|
+
def ensure_execution!
|
97
|
+
return if performable_status.present?
|
98
|
+
|
99
|
+
error!("`#{self.class}` was not executed yet.")
|
100
|
+
end
|
101
|
+
|
102
|
+
def error!(message = nil)
|
103
|
+
message ||= "`#{self.class}` raised error."
|
104
|
+
raise error_class, message
|
105
|
+
end
|
106
|
+
|
107
|
+
if defined?(ApplicationError)
|
108
|
+
def error_class
|
109
|
+
ApplicationError
|
110
|
+
end
|
111
|
+
else
|
112
|
+
def error_class
|
113
|
+
AuxiliaryRails::Application::Error
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Sets command's status to <tt>failure</tt>.
|
118
|
+
#
|
119
|
+
# @return [self]
|
120
|
+
def failure!(message = nil, options = {})
|
121
|
+
ensure_empty_status!
|
122
|
+
|
123
|
+
errors.add(:base, message, options) if message.present?
|
124
|
+
|
125
|
+
self.performable_status = :failure
|
126
|
+
self
|
127
|
+
end
|
128
|
+
|
129
|
+
# Sets command's status to <tt>success</tt>.
|
130
|
+
#
|
131
|
+
# @return [self]
|
132
|
+
def success!
|
133
|
+
ensure_empty_errors!
|
134
|
+
ensure_empty_status!
|
135
|
+
|
136
|
+
self.performable_status = :success
|
137
|
+
self
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|