granite 0.15.1 → 0.16.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/lib/granite/action/performing.rb +3 -1
- data/lib/granite/action/transaction.rb +2 -14
- data/lib/granite/action/transaction_manager.rb +1 -1
- data/lib/granite/action.rb +7 -1
- data/lib/granite/assign_data.rb +2 -0
- data/lib/granite/base.rb +1 -4
- data/lib/granite/projector/helpers.rb +2 -2
- data/lib/granite/projector.rb +5 -1
- data/lib/granite/rspec/projector_helpers.rb +11 -5
- data/lib/granite/version.rb +1 -1
- data/lib/granite.rb +0 -1
- metadata +2 -8
- data/lib/granite/action/types/collection.rb +0 -21
- data/lib/granite/action/types.rb +0 -1
- data/lib/granite/represents/attribute.rb +0 -105
- data/lib/granite/represents/reflection.rb +0 -24
- data/lib/granite/represents.rb +0 -21
- data/lib/granite/util.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de7f652f9f341a639c08c1f535e9bae3d07527ba5efc09599accf18895472607
|
4
|
+
data.tar.gz: f2792a296afbf39f20de772bf8d735ae778415f7214f1280dccde2dac58015e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 209c96c7464851ab67c3cc21c3b8b241c9874de746640924c322cb48a237e7c8f91a483e84d438247910103138215fe2cf5bdebe9855ae6633c5f180dc142b17
|
7
|
+
data.tar.gz: 8a27c93316cfdfbd050033567ff99ffeabe9cf73725810a73ed3c7ae76bfafde321c6b3e4f6b85bf7bb151517d61d36fd42fa084bf173c29bf784d44e7c5bd74
|
@@ -42,7 +42,9 @@ module Granite
|
|
42
42
|
# @return [Object] result of execute_perform! method execution or false in case of errors
|
43
43
|
def perform(context: nil, **options)
|
44
44
|
transaction do
|
45
|
-
valid?(context)
|
45
|
+
fail Rollback unless valid?(context)
|
46
|
+
|
47
|
+
perform_action(**options)
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
@@ -6,20 +6,8 @@ module Granite
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
included do
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
delegate :transaction, to: :'Granite::Action::TransactionManager'
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
# Defines a callback which will be triggered right after transaction committed
|
18
|
-
# Uses the same arguments as `ActiveSupport::Callbacks.set_callback` except for the first two
|
19
|
-
#
|
20
|
-
def after_commit(*args, &block)
|
21
|
-
set_callback :commit, :after, *args, &block
|
22
|
-
end
|
9
|
+
define_model_callbacks :commit, only: :after
|
10
|
+
singleton_class.delegate :transaction, to: :'Granite::Action::TransactionManager'
|
23
11
|
end
|
24
12
|
|
25
13
|
def run_callbacks(event)
|
@@ -62,7 +62,7 @@ module Granite
|
|
62
62
|
collected_errors = []
|
63
63
|
|
64
64
|
callbacks.reverse_each do |callback|
|
65
|
-
callback.respond_to?(:
|
65
|
+
callback.respond_to?(:_run_commit_callbacks) ? callback._run_commit_callbacks : callback.call
|
66
66
|
rescue StandardError => e
|
67
67
|
collected_errors << e
|
68
68
|
end
|
data/lib/granite/action.rb
CHANGED
@@ -3,7 +3,6 @@ require 'active_record/errors'
|
|
3
3
|
require 'active_record/validations'
|
4
4
|
require 'active_support/callbacks'
|
5
5
|
|
6
|
-
require 'granite/action/types'
|
7
6
|
require 'granite/action/error'
|
8
7
|
require 'granite/action/instrumentation'
|
9
8
|
require 'granite/action/performing'
|
@@ -63,6 +62,13 @@ module Granite
|
|
63
62
|
merge_errors(e.action.errors)
|
64
63
|
end
|
65
64
|
|
65
|
+
define_model_callbacks :initialize, only: :after
|
66
|
+
|
67
|
+
def initialize(*)
|
68
|
+
super
|
69
|
+
_run_initialize_callbacks
|
70
|
+
end
|
71
|
+
|
66
72
|
if ActiveModel.version < Gem::Version.new('6.1.0')
|
67
73
|
def merge_errors(other_errors)
|
68
74
|
errors.messages.deep_merge!(other_errors.messages) do |_, this, other|
|
data/lib/granite/assign_data.rb
CHANGED
data/lib/granite/base.rb
CHANGED
@@ -3,7 +3,6 @@ require 'granite/form/model/primary'
|
|
3
3
|
require 'granite/form/model/associations'
|
4
4
|
|
5
5
|
require 'granite/translations'
|
6
|
-
require 'granite/represents'
|
7
6
|
require 'granite/assign_data'
|
8
7
|
|
9
8
|
module Granite
|
@@ -11,8 +10,8 @@ module Granite
|
|
11
10
|
# embeds_many)
|
12
11
|
module Base
|
13
12
|
extend ActiveSupport::Concern
|
13
|
+
extend ActiveModel::Callbacks
|
14
14
|
|
15
|
-
include ActiveSupport::Callbacks
|
16
15
|
include Granite::Form::Model
|
17
16
|
include Granite::Form::Model::Representation
|
18
17
|
include Granite::Form::Model::Dirty
|
@@ -20,8 +19,6 @@ module Granite
|
|
20
19
|
include Granite::Form::Model::Primary
|
21
20
|
include ActiveModel::Validations::Callbacks
|
22
21
|
|
23
|
-
include Granite::Util
|
24
22
|
include Granite::AssignData
|
25
|
-
include Granite::Represents
|
26
23
|
end
|
27
24
|
end
|
@@ -5,7 +5,7 @@ module Granite
|
|
5
5
|
class ActionNotMountedError < Error
|
6
6
|
def initialize(projector)
|
7
7
|
super("Seems like #{projector.class} was not mounted. \
|
8
|
-
Do you have #{projector.
|
8
|
+
Do you have #{projector.action_name}##{projector.projector_name} declared in routes?", projector)
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -43,7 +43,7 @@ Do you have #{projector.action_class.name.underscore}##{projector.projector_name
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def route_id
|
46
|
-
[
|
46
|
+
[action_name, projector_name]
|
47
47
|
end
|
48
48
|
|
49
49
|
def url_options
|
data/lib/granite/projector.rb
CHANGED
@@ -12,7 +12,7 @@ module Granite
|
|
12
12
|
include Translations
|
13
13
|
|
14
14
|
singleton_class.__send__(:attr_accessor, :action_class)
|
15
|
-
delegate :action_class, :projector_name, to: 'self.class'
|
15
|
+
delegate :action_class, :projector_name, :action_name, to: 'self.class'
|
16
16
|
attr_reader :action
|
17
17
|
|
18
18
|
def self.controller_class
|
@@ -31,6 +31,10 @@ module Granite
|
|
31
31
|
@projector_name ||= name.demodulize.remove(/Projector$/).underscore
|
32
32
|
end
|
33
33
|
|
34
|
+
def self.action_name
|
35
|
+
@action_name ||= action_class.name.underscore
|
36
|
+
end
|
37
|
+
|
34
38
|
def initialize(*args)
|
35
39
|
@action = if args.first.is_a?(Granite::Action) # Temporary solutions for backwards compatibility.
|
36
40
|
args.first
|
@@ -1,9 +1,8 @@
|
|
1
1
|
module Granite::ProjectorHelpers
|
2
2
|
extend ActiveSupport::Concern
|
3
|
+
include RSpec::Rails::ControllerExampleGroup
|
3
4
|
|
4
5
|
included do
|
5
|
-
include RSpec::Rails::ControllerExampleGroup
|
6
|
-
include RSpec::Rails::RequestExampleGroup
|
7
6
|
before { Granite::Routing::Declarer.dispatcher.unmemoize_all }
|
8
7
|
end
|
9
8
|
|
@@ -23,16 +22,17 @@ module Granite::ProjectorHelpers
|
|
23
22
|
end
|
24
23
|
|
25
24
|
def projector(&block)
|
26
|
-
setup_controller
|
25
|
+
setup_controller
|
27
26
|
setup_view_context
|
27
|
+
let(:projector_class, &block)
|
28
28
|
let(:projector) { controller.projector }
|
29
29
|
end
|
30
30
|
|
31
31
|
private
|
32
32
|
|
33
|
-
def setup_controller
|
33
|
+
def setup_controller
|
34
34
|
define_method :setup_controller_request_and_response do
|
35
|
-
@controller ||=
|
35
|
+
@controller ||= projector_class.controller_class.new
|
36
36
|
super()
|
37
37
|
end
|
38
38
|
end
|
@@ -42,6 +42,12 @@ module Granite::ProjectorHelpers
|
|
42
42
|
after { Granite.view_context = nil }
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
# Overrides ActionController::TestCase::Behavior#process to include granite_action and granite_projector
|
47
|
+
def process(action, **options)
|
48
|
+
projector_params = {granite_action: projector_class.action_name, granite_projector: projector_class.projector_name}
|
49
|
+
super(action, **options, params: projector_params.reverse_merge(options[:params] || {}))
|
50
|
+
end
|
45
51
|
end
|
46
52
|
|
47
53
|
RSpec.configuration.define_derived_metadata(file_path: %r{spec/apq/projectors/}) { |metadata| metadata[:type] ||= :granite_projector }
|
data/lib/granite/version.rb
CHANGED
data/lib/granite.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: granite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Toptal Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-01-
|
11
|
+
date: 2023-01-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -369,8 +369,6 @@ files:
|
|
369
369
|
- lib/granite/action/transaction_manager.rb
|
370
370
|
- lib/granite/action/transaction_manager/transactions_stack.rb
|
371
371
|
- lib/granite/action/translations.rb
|
372
|
-
- lib/granite/action/types.rb
|
373
|
-
- lib/granite/action/types/collection.rb
|
374
372
|
- lib/granite/assign_data.rb
|
375
373
|
- lib/granite/base.rb
|
376
374
|
- lib/granite/config.rb
|
@@ -386,9 +384,6 @@ files:
|
|
386
384
|
- lib/granite/projector/helpers.rb
|
387
385
|
- lib/granite/projector/translations.rb
|
388
386
|
- lib/granite/rails.rb
|
389
|
-
- lib/granite/represents.rb
|
390
|
-
- lib/granite/represents/attribute.rb
|
391
|
-
- lib/granite/represents/reflection.rb
|
392
387
|
- lib/granite/routing.rb
|
393
388
|
- lib/granite/routing/cache.rb
|
394
389
|
- lib/granite/routing/caching.rb
|
@@ -404,7 +399,6 @@ files:
|
|
404
399
|
- lib/granite/rspec/raise_validation_error.rb
|
405
400
|
- lib/granite/rspec/satisfy_preconditions.rb
|
406
401
|
- lib/granite/translations.rb
|
407
|
-
- lib/granite/util.rb
|
408
402
|
- lib/granite/version.rb
|
409
403
|
- lib/rubocop-granite.rb
|
410
404
|
- lib/rubocop/granite.rb
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module Granite
|
2
|
-
class Action
|
3
|
-
module Types
|
4
|
-
class Collection
|
5
|
-
attr_reader :subtype_definition
|
6
|
-
|
7
|
-
def initialize(subtype_definition)
|
8
|
-
@subtype_definition = subtype_definition
|
9
|
-
end
|
10
|
-
|
11
|
-
def ensure_type(value)
|
12
|
-
if value.respond_to? :transform_values
|
13
|
-
value.transform_values { |v| subtype_definition.ensure_type(v) }
|
14
|
-
elsif value.respond_to?(:map)
|
15
|
-
value.map { |v| subtype_definition.ensure_type(v) }
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
data/lib/granite/action/types.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'granite/action/types/collection'
|
@@ -1,105 +0,0 @@
|
|
1
|
-
module Granite
|
2
|
-
module Represents
|
3
|
-
class Attribute < Granite::Form::Model::Attributes::Attribute
|
4
|
-
types = {}
|
5
|
-
types[ActiveRecord::Enum::EnumType] = String if defined?(ActiveRecord)
|
6
|
-
TYPES = types.freeze
|
7
|
-
GRANITE_COLLECTION_TYPES = [
|
8
|
-
Granite::Form::Model::Attributes::ReferenceMany,
|
9
|
-
Granite::Form::Model::Attributes::Collection,
|
10
|
-
Granite::Form::Model::Attributes::Dictionary
|
11
|
-
].freeze
|
12
|
-
delegate :writer, :reader, :reader_before_type_cast, to: :reflection
|
13
|
-
|
14
|
-
def initialize(*_args)
|
15
|
-
super
|
16
|
-
|
17
|
-
set_default_value
|
18
|
-
set_default_value_before_type_cast
|
19
|
-
end
|
20
|
-
|
21
|
-
def sync
|
22
|
-
reference.public_send(writer, read) if reference.respond_to?(writer)
|
23
|
-
end
|
24
|
-
|
25
|
-
def type_definition
|
26
|
-
@type_definition ||= if reflection.options[:type].present?
|
27
|
-
build_type_definition(reflection.options[:type])
|
28
|
-
else
|
29
|
-
granite_form_type_definition || active_record_type_definition || super
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def changed?
|
34
|
-
if reflection.options.key?(:default)
|
35
|
-
reference.public_send(reader) != read
|
36
|
-
else
|
37
|
-
owner.public_send("#{name}_changed?")
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def reference
|
44
|
-
owner.__send__(reflection.reference)
|
45
|
-
end
|
46
|
-
|
47
|
-
def set_default_value
|
48
|
-
return unless reference.respond_to?(reader)
|
49
|
-
|
50
|
-
variable_cache(:value) do
|
51
|
-
normalize(enumerize(type_definition.ensure_type(defaultize(reference.public_send(reader)))))
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def set_default_value_before_type_cast
|
56
|
-
return unless reference.respond_to?(reader_before_type_cast)
|
57
|
-
|
58
|
-
variable_cache(:value_before_type_cast) do
|
59
|
-
defaultize(reference.public_send(reader_before_type_cast))
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def granite_form_type_definition
|
64
|
-
return nil unless reference.is_a?(Granite::Form::Model)
|
65
|
-
|
66
|
-
reference_attribute = reference.attribute(name)
|
67
|
-
|
68
|
-
return nil if reference_attribute.nil?
|
69
|
-
|
70
|
-
type_definition = build_type_definition(reference_attribute.type)
|
71
|
-
if GRANITE_COLLECTION_TYPES.any? { |klass| reference_attribute.is_a? klass }
|
72
|
-
Granite::Action::Types::Collection.new(type_definition)
|
73
|
-
else
|
74
|
-
type_definition
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def active_record_type_definition
|
79
|
-
return nil unless reference.respond_to?(:type_for_attribute)
|
80
|
-
|
81
|
-
attribute_type = reference.type_for_attribute(attribute_name.to_s)
|
82
|
-
|
83
|
-
if TYPES.key?(attribute_type.class)
|
84
|
-
build_type_definition(TYPES[attribute_type.class])
|
85
|
-
elsif attribute_type.respond_to?(:subtype)
|
86
|
-
Granite::Action::Types::Collection.new(convert_active_model_type_to_definition(attribute_type.subtype))
|
87
|
-
else
|
88
|
-
convert_active_model_type_to_definition(attribute_type)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def attribute_name
|
93
|
-
return name if ActiveModel.version >= Gem::Version.new('6.1.0')
|
94
|
-
|
95
|
-
reference.class.attribute_aliases[name.to_s] || name
|
96
|
-
end
|
97
|
-
|
98
|
-
def convert_active_model_type_to_definition(attribute_type)
|
99
|
-
type = attribute_type.try(:value_class) ||
|
100
|
-
Form::Model::Associations::PersistenceAdapters::ActiveRecord::TYPES[attribute_type.type&.to_sym]
|
101
|
-
build_type_definition(type) if type
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'granite/represents/attribute'
|
2
|
-
|
3
|
-
module Granite
|
4
|
-
module Represents
|
5
|
-
class Reflection < Granite::Form::Model::Attributes::Reflections::Represents
|
6
|
-
class << self
|
7
|
-
def build(target, generated_methods, name, *args, &block)
|
8
|
-
options = args.last
|
9
|
-
|
10
|
-
reference = target.reflect_on_association(options[:of]) if target.respond_to?(:reflect_on_association)
|
11
|
-
reference ||= target.reflect_on_attribute(options[:of]) if target.respond_to?(:reflect_on_attribute)
|
12
|
-
|
13
|
-
target.validates_presence_of(reference.name) if reference
|
14
|
-
|
15
|
-
super(target, generated_methods, name, *args, &block)
|
16
|
-
end
|
17
|
-
|
18
|
-
def attribute_class
|
19
|
-
@attribute_class ||= Granite::Represents::Attribute
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/lib/granite/represents.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'granite/represents/reflection'
|
2
|
-
|
3
|
-
module Granite
|
4
|
-
module Represents
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
module ClassMethods
|
8
|
-
private
|
9
|
-
|
10
|
-
def represents(*fields, &block)
|
11
|
-
options = fields.extract_options!.symbolize_keys
|
12
|
-
|
13
|
-
fields.each do |field|
|
14
|
-
add_attribute Granite::Represents::Reflection, field, options, &block
|
15
|
-
|
16
|
-
assign_data { attribute(field).sync if attribute(field).changed? }
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
data/lib/granite/util.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
module Granite
|
2
|
-
module Util
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
# Evaluates value and returns result based on what was passed:
|
6
|
-
# - if Proc was passed, then executes it in context of self
|
7
|
-
# - if Symbol was passed, then calls a method with that name and returns result
|
8
|
-
# - otherwise just returns the value itself
|
9
|
-
# @param value [Object] value to evaluate
|
10
|
-
# @return [Object] result of evaluation
|
11
|
-
def evaluate(value)
|
12
|
-
case value
|
13
|
-
when Proc
|
14
|
-
evaluate_proc(value)
|
15
|
-
when Symbol
|
16
|
-
evaluate_symbol(value)
|
17
|
-
else
|
18
|
-
value
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Evaluates `if` or `unless` conditions present in the supplied
|
23
|
-
# `options` being it a symbol or callable.
|
24
|
-
#
|
25
|
-
# @param [Hash] options The method options to evaluate.
|
26
|
-
# @option options :if method name or callable
|
27
|
-
# @option options :unless method name or callable
|
28
|
-
# @return [Boolean] whether conditions are satisfied
|
29
|
-
def conditions_satisfied?(**options)
|
30
|
-
fail ArgumentError, 'You cannot specify both if and unless' if options.key?(:if) && options.key?(:unless)
|
31
|
-
|
32
|
-
if options.key?(:if)
|
33
|
-
evaluate(options[:if])
|
34
|
-
elsif options.key?(:unless)
|
35
|
-
!evaluate(options[:unless])
|
36
|
-
else
|
37
|
-
true
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def evaluate_proc(value)
|
44
|
-
instance_exec(&value)
|
45
|
-
end
|
46
|
-
|
47
|
-
def evaluate_symbol(value)
|
48
|
-
__send__(value)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|