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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d0a4953c8a4a24dfab614a8831bb8b39cda81d4a0b2d7e3ea8f2bb5d3d8eccc4
4
- data.tar.gz: 6f1655c4167aef595d7c36fcd0fbde9e72376bd1fec2dafc38e6dc508f4f0417
3
+ metadata.gz: de7f652f9f341a639c08c1f535e9bae3d07527ba5efc09599accf18895472607
4
+ data.tar.gz: f2792a296afbf39f20de772bf8d735ae778415f7214f1280dccde2dac58015e6
5
5
  SHA512:
6
- metadata.gz: bd0b0f97527283426bdaf8f5d25cf033053f0636958578621c84f5c8fc0c01f70528f1d759213ac0cddbc3327d5b06951b231d18cce3e987c612697dabb90c89
7
- data.tar.gz: deff30290527973e4dee79d4584c7ffd5090a80737da57d1efe48e8fcdd89d0e11d220c8b5c81b55f313f2d3ced81b097ab454c67065b6db458629e18924c236
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) && perform_action(**options)
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
- define_callbacks :commit
10
- end
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?(:run_callbacks) ? callback.run_callbacks(:commit) : callback.call
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
@@ -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|
@@ -10,6 +10,8 @@ module Granite
10
10
 
11
11
  alias_method :only_run_validations!, :run_validations!
12
12
  protected :only_run_validations!
13
+
14
+ assign_data :sync_attributes
13
15
  end
14
16
 
15
17
  module ClassMethods
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.action_class.name.underscore}##{projector.projector_name} declared in routes?", 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
- [action_class.name.underscore, projector_name]
46
+ [action_name, projector_name]
47
47
  end
48
48
 
49
49
  def url_options
@@ -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(&block)
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(&block)
33
+ def setup_controller
34
34
  define_method :setup_controller_request_and_response do
35
- @controller ||= instance_eval(&block).controller_class.new
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 }
@@ -1,3 +1,3 @@
1
1
  module Granite
2
- VERSION = '0.15.1'.freeze
2
+ VERSION = '0.16.0'.freeze
3
3
  end
data/lib/granite.rb CHANGED
@@ -5,7 +5,6 @@ require 'ruby2_keywords'
5
5
  require 'granite/version'
6
6
  require 'granite/config'
7
7
  require 'granite/context'
8
- require 'granite/util'
9
8
 
10
9
  module Granite
11
10
  def self.config
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.15.1
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-02 00:00:00.000000000 Z
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
@@ -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
@@ -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