plutonium 0.15.0.pre.rc3 → 0.15.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/app/views/components/form/form_builder.rb +3 -3
  3. data/app/views/components/table/table_component.rb +1 -1
  4. data/app/views/resource/_interactive_action_form.html.erb +1 -0
  5. data/app/views/resource/{interactive_resource_collection_action.html.erb → interactive_bulk_action.html.erb} +1 -1
  6. data/app/views/resource/interactive_record_action.html.erb +1 -0
  7. data/app/views/resource/{interactive_resource_record_action.html.erb → interactive_resource_action.html.erb} +1 -1
  8. data/lib/generators/pu/lib/plutonium_generators/installer.rb +1 -1
  9. data/lib/plutonium/action/base.rb +6 -3
  10. data/lib/plutonium/action/interactive.rb +16 -9
  11. data/lib/plutonium/core/actions/basic_action.rb +2 -2
  12. data/lib/plutonium/core/actions/interactive_action.rb +2 -2
  13. data/lib/plutonium/core/controller.rb +1 -1
  14. data/lib/plutonium/core/fields/inputs/attachment_input.rb +2 -2
  15. data/lib/plutonium/core/fields/inputs/nested_input.rb +2 -2
  16. data/lib/plutonium/definition/base.rb +8 -1
  17. data/lib/plutonium/definition/sorting.rb +15 -0
  18. data/lib/plutonium/interaction/README.md +34 -1
  19. data/lib/plutonium/interaction/base.rb +38 -7
  20. data/lib/plutonium/interaction/concerns/presentable.rb +24 -12
  21. data/lib/plutonium/interaction/outcome.rb +77 -55
  22. data/lib/plutonium/interaction/response/base.rb +3 -1
  23. data/lib/plutonium/interaction/response/failure.rb +18 -0
  24. data/lib/plutonium/interaction/response/file.rb +20 -0
  25. data/lib/plutonium/interaction/response/redirect.rb +1 -11
  26. data/lib/plutonium/interaction/response/render.rb +1 -9
  27. data/lib/plutonium/resource/controllers/authorizable.rb +29 -5
  28. data/lib/plutonium/resource/controllers/interactive_actions.rb +171 -130
  29. data/lib/plutonium/resource/controllers/queryable.rb +2 -2
  30. data/lib/plutonium/resource/interaction.rb +1 -3
  31. data/lib/plutonium/resource/query_object.rb +2 -2
  32. data/lib/plutonium/routing/mapper_extensions.rb +9 -9
  33. data/lib/plutonium/routing/route_set_extensions.rb +1 -1
  34. data/lib/plutonium/ui/action_button.rb +4 -3
  35. data/lib/plutonium/ui/component/methods.rb +1 -0
  36. data/lib/plutonium/ui/display/theme.rb +4 -3
  37. data/lib/plutonium/ui/form/interaction.rb +35 -0
  38. data/lib/plutonium/ui/form/resource.rb +1 -1
  39. data/lib/plutonium/ui/page/interactive_action.rb +23 -0
  40. data/lib/plutonium/ui/table/components/search_bar.rb +1 -1
  41. data/lib/plutonium/ui/table/display_theme.rb +2 -2
  42. data/lib/plutonium/ui/table/resource.rb +11 -5
  43. data/lib/plutonium/version.rb +1 -1
  44. metadata +13 -23
  45. data/app/views/resource/_interactive_resource_action_form.html.erb +0 -45
  46. data/app/views/resource/interactive_resource_recordless_action.html.erb +0 -5
  47. data/gemfiles/rails_7.gemfile.lock +0 -339
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 405c1eab2d9e447c8a04632503a74cd7738a3e538b9f4c81d3f2f5388cc69db3
4
- data.tar.gz: 56abd90667c0ebed5de99983ecda28602d30bce10cfc25f7ea4050db83ae65a1
3
+ metadata.gz: 307fb5dad4c2e8939eeb21880f8c17875addd10250bbdb0e41657ec7318aacb6
4
+ data.tar.gz: 9de4a57e5a7f35f4819c832fef7d0d8370b0ec2ff1f8b546e562c7d330e405c1
5
5
  SHA512:
6
- metadata.gz: facccabb9461dd0948ae6c3ec7ff1cffce5430cf927d628abfc29725faf4155d5acdfe2990f1ecb23255baa5ffd9b8004a4da5cb274a26c50b62c3db921153ac
7
- data.tar.gz: 3a87907c78fbedf64c9fa96d4c206d5880f8984cc6dee212eeb1d1435b8c6a87bb410fbcd3e42aec80177ba29b45a17fd7dd76250755eba94c6454587b54ed79
6
+ metadata.gz: '0391c0561b9d75ab2793f60e80b7084e705c3f4766b83d47c18944c2fd9fe0b0615bbb920e321e2147ac166359ad8038a951d8ddbd2637373bc2ac5ee74bb699'
7
+ data.tar.gz: cd3a020f588252e9517281887c332fec3b491c12802946d7d3f19f597659a6ca6f77a823aaf016c7a0aeb0bc0df3cd430e73e30cfc7ffa28c3cfc1a522219fdc
@@ -2,7 +2,7 @@ require "simple_form"
2
2
 
3
3
  module PlutoniumUi
4
4
  class FormBuilder < SimpleForm::FormBuilder
5
- def input(attribute_name, options = {}, &block)
5
+ def input(attribute_name, options = {}, &)
6
6
  label_class = options.dig(:label_html, :class)
7
7
  if object&.errors&.[](attribute_name).present?
8
8
  # Don't show the hint
@@ -19,13 +19,13 @@ module PlutoniumUi
19
19
  options[:label_html] ||= {}
20
20
  options[:label_html][:class] = label_class
21
21
 
22
- super(attribute_name, options, &block)
22
+ super
23
23
  end
24
24
 
25
25
  def hint(...)
26
26
  return if object.errors[attribute_name].present?
27
27
 
28
- super(...)
28
+ super
29
29
  end
30
30
 
31
31
  def return_to(url)
@@ -9,7 +9,7 @@ module PlutoniumUi
9
9
  #
10
10
  # @param options [Hash] The options for the component.
11
11
  def initialize(...)
12
- super(...)
12
+ super
13
13
  @columns = []
14
14
  end
15
15
 
@@ -0,0 +1 @@
1
+ <%= render @interaction.build_form %>
@@ -1,5 +1,5 @@
1
1
  <%= render_component :breadcrumbs, resource_class:, parent: current_parent, resource: resource_record %>
2
2
 
3
3
  <%= render_component :dyna_frame_content do %>
4
- <%= render "interactive_resource_action_form", interactive_action: current_interactive_action %>
4
+ <%= render "interactive_action_form", interactive_action: current_interactive_action %>
5
5
  <% end %>
@@ -0,0 +1 @@
1
+ <%= render current_definition.interactive_action_page_class.new %>
@@ -1,5 +1,5 @@
1
1
  <%= render_component :breadcrumbs, resource_class:, parent: current_parent, resource: resource_record %>
2
2
 
3
3
  <%= render_component :dyna_frame_content do %>
4
- <%= render "interactive_resource_action_form", interactive_action: current_interactive_action %>
4
+ <%= render "interactive_action_form", interactive_action: current_interactive_action %>
5
5
  <% end %>
@@ -106,7 +106,7 @@ module PlutoniumGenerators
106
106
  end
107
107
 
108
108
  def yes?(statement, color = nil)
109
- !interactive? || super(statement, color)
109
+ !interactive? || super
110
110
  end
111
111
 
112
112
  def interactive?
@@ -16,13 +16,14 @@ module Plutonium
16
16
  # @attr_reader [Symbol, nil] category The category of the action.
17
17
  # @attr_reader [Integer] position The position of the action within its category.
18
18
  class Base
19
- attr_reader :name, :label, :icon, :route_options, :confirmation, :turbo_frame, :color, :category, :position
19
+ attr_reader :name, :label, :description, :icon, :route_options, :confirmation, :turbo, :turbo_frame, :color, :category, :position
20
20
 
21
21
  # Initialize a new action.
22
22
  #
23
23
  # @param [Symbol] name The name of the action.
24
24
  # @param [Hash] options The options for the action.
25
25
  # @option options [String] :label The human-readable label for the action.
26
+ # @option options [String] :description The human-readable description for the action.
26
27
  # @option options [String] :icon The icon associated with the action (e.g., 'fa-edit' for Font Awesome).
27
28
  # @option options [Symbol] :color The color associated with the action (e.g., :primary, :secondary, :success, :warning, :danger).
28
29
  # @option options [String] :confirmation The confirmation message to display before executing the action.
@@ -40,11 +41,13 @@ module Plutonium
40
41
  # @option options [Integer] :position (50) The position of the action in its group. Lower numbers appear first.
41
42
  def initialize(name, **options)
42
43
  @name = name.to_sym
43
- @label = options[:label] || name.to_s.humanize
44
- @icon = options[:icon]
44
+ @label = options[:label] || @name.to_s.titleize
45
+ @description = options[:description]
46
+ @icon = options[:icon] || Phlex::TablerIcons::ChevronRight
45
47
  @color = options[:color]
46
48
  @confirmation = options[:confirmation]
47
49
  @route_options = build_route_options(options[:route_options])
50
+ @turbo = options[:turbo]
48
51
  @turbo_frame = options[:turbo_frame]
49
52
  @bulk_action = options[:bulk_action] || false
50
53
  @collection_record_action = options[:collection_record_action] || false
@@ -15,11 +15,15 @@ module Plutonium
15
15
  # @param [Class] interaction The interaction class for this action
16
16
  # @param [Boolean] immediate Whether the action is executed immediately
17
17
  # @param [Hash] options Additional options for the action
18
- def initialize(name, interaction:, immediate:, **)
18
+ def initialize(name, interaction:, immediate:, **options)
19
19
  @interaction = interaction
20
20
  @immediate = immediate
21
21
 
22
- super(name, **)
22
+ options[:label] ||= interaction.label
23
+ options[:description] ||= interaction.description
24
+ options[:icon] ||= interaction.icon
25
+
26
+ super(name, **options)
23
27
  end
24
28
 
25
29
  # Get the confirmation message for the action
@@ -31,6 +35,8 @@ module Plutonium
31
35
 
32
36
  # Factory for creating Interactive actions
33
37
  class Factory
38
+ # TODO: move these into Plutonium::Action::Interactive
39
+
34
40
  # Create a new Interactive action based on the interaction type
35
41
  #
36
42
  # @param [Symbol] name The name of the action
@@ -50,6 +56,7 @@ module Plutonium
50
56
  interaction: interaction,
51
57
  immediate: immediate,
52
58
  route_options: route_options,
59
+ turbo: interaction.turbo,
53
60
  **action_options,
54
61
  **options
55
62
  )
@@ -69,11 +76,11 @@ module Plutonium
69
76
  # @return [Symbol] The determined action type
70
77
  def self.determine_action_type(attribute_names)
71
78
  if attribute_names.include?(:resource)
72
- :interactive_resource_record_action
79
+ :interactive_record_action
73
80
  elsif attribute_names.include?(:resources)
74
- :interactive_resource_collection_action
81
+ :interactive_collection_action
75
82
  else
76
- :interactive_resource_recordless_action
83
+ :interactive_resource_action
77
84
  end
78
85
  end
79
86
 
@@ -91,10 +98,10 @@ module Plutonium
91
98
  # @return [Hash] The action options
92
99
  def self.determine_action_options(action_type)
93
100
  {
94
- bulk_action: action_type == :interactive_resource_collection_action,
95
- record_action: action_type == :interactive_resource_record_action,
96
- collection_record_action: action_type == :interactive_resource_record_action,
97
- resource_action: action_type == :interactive_resource_recordless_action
101
+ bulk_action: action_type == :interactive_collection_action,
102
+ record_action: action_type == :interactive_record_action,
103
+ collection_record_action: action_type == :interactive_record_action,
104
+ resource_action: action_type == :interactive_resource_action
98
105
  }
99
106
  end
100
107
 
@@ -2,9 +2,9 @@ module Plutonium
2
2
  module Core
3
3
  module Actions
4
4
  class BasicAction < Plutonium::Core::Action
5
- def initialize(*args, **kwargs)
5
+ def initialize(*, **kwargs)
6
6
  kwargs.reverse_merge! action_options
7
- super(*args, **kwargs)
7
+ super
8
8
  end
9
9
 
10
10
  private
@@ -8,12 +8,12 @@ module Plutonium
8
8
 
9
9
  attr_reader :interaction, :inline, :inputs
10
10
 
11
- def initialize(name, *args, interaction:, **kwargs)
11
+ def initialize(name, *, interaction:, **kwargs)
12
12
  set_interaction interaction
13
13
 
14
14
  kwargs[:route_options] ||= build_route_options name
15
15
  kwargs.reverse_merge! action_options
16
- super(name, *args, **kwargs)
16
+ super(name, *, **kwargs)
17
17
  end
18
18
 
19
19
  def confirmation
@@ -99,7 +99,7 @@ module Plutonium
99
99
  def root_path(*)
100
100
  return send(:"#{scoped_entity_param_key}_root_path", *) if scoped_to_entity? && scoped_entity_strategy == :path
101
101
 
102
- super(*)
102
+ super
103
103
  end
104
104
 
105
105
  def registered_resources
@@ -5,9 +5,9 @@ module Plutonium
5
5
  class AttachmentInput < SimpleFormInput
6
6
  attr_reader :reflection
7
7
 
8
- def initialize(name, reflection:, **options)
8
+ def initialize(name, reflection:, **)
9
9
  @reflection = reflection
10
- super(name, **options)
10
+ super(name, **)
11
11
  end
12
12
 
13
13
  private
@@ -7,14 +7,14 @@ module Plutonium
7
7
 
8
8
  attr_reader :inputs, :resource_class
9
9
 
10
- def initialize(name, inputs:, resource_class:, allow_destroy:, update_only:, limit:, **options)
10
+ def initialize(name, inputs:, resource_class:, allow_destroy:, update_only:, limit:, **)
11
11
  @inputs = inputs
12
12
  @resource_class = resource_class
13
13
  @allow_destroy = allow_destroy
14
14
  @update_only = update_only
15
15
  @limit = limit
16
16
 
17
- super(name, **options)
17
+ super(name, **)
18
18
  end
19
19
 
20
20
  def render
@@ -27,6 +27,7 @@ module Plutonium
27
27
  include DefineableProps
28
28
  include ConfigAttr
29
29
  include Actions
30
+ include Sorting
30
31
  include Search
31
32
 
32
33
  class IndexPage < Plutonium::UI::Page::Index; end
@@ -37,6 +38,8 @@ module Plutonium
37
38
 
38
39
  class EditPage < Plutonium::UI::Page::Edit; end
39
40
 
41
+ class InteractiveActionPage < Plutonium::UI::Page::InteractiveAction; end
42
+
40
43
  class Form < Plutonium::UI::Form::Resource; end
41
44
 
42
45
  class Table < Plutonium::UI::Table::Resource; end
@@ -47,7 +50,7 @@ module Plutonium
47
50
  defineable_props :field, :input, :display, :column
48
51
 
49
52
  # queries
50
- defineable_props :filter, :scope, :sort
53
+ defineable_props :filter, :scope
51
54
 
52
55
  # pages
53
56
  config_attr \
@@ -76,6 +79,10 @@ module Plutonium
76
79
  self.class::EditPage
77
80
  end
78
81
 
82
+ def interactive_action_page_class
83
+ self.class::InteractiveActionPage
84
+ end
85
+
79
86
  def form_class
80
87
  self.class::Form
81
88
  end
@@ -0,0 +1,15 @@
1
+ module Plutonium
2
+ module Definition
3
+ module Sorting
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ defineable_props :sort
8
+
9
+ def self.sorts(*names)
10
+ names.each { |name| sort name }
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -255,7 +255,7 @@ class MyInteraction < Plutonium::Interaction::Base
255
255
  include Plutonium::Interaction::Concerns::Presentable
256
256
 
257
257
  presents label: "My Interaction",
258
- icon: "star",
258
+ icon: Phlex::TablerIcons::Activate,
259
259
  description: "Does something awesome"
260
260
 
261
261
  # ... rest of the interaction
@@ -366,4 +366,37 @@ module Orders
366
366
  end
367
367
  end
368
368
  ```
369
+
370
+
371
+ class Sample < Phlex::HTML
372
+ def view_template
373
+ p { "my custom template" }
374
+ end
375
+ end
376
+
377
+ class Rename < ResourceInteraction
378
+ attribute :resource
379
+
380
+ attribute :name
381
+ validates :name, presence: true
382
+
383
+ # input :name, as: :file
384
+ turbo false
385
+
386
+ presents label: "Rename resource",
387
+ icon: Phlex::TablerIcons::Pencil,
388
+ description: "Some cool stuff"
389
+
390
+ private
391
+
392
+ def execute
393
+ resource.name = name
394
+ if resource.save
395
+ succeed.with_message("Action completed").with_render_response(Sample.new)
396
+ else
397
+ failed resource.errors
398
+ end
399
+ end
400
+ end
401
+ # action :rename, interaction: Rename
369
402
  -->
@@ -22,9 +22,16 @@ module Plutonium
22
22
  class Base
23
23
  include ActiveModel::Model
24
24
  include ActiveModel::Attributes
25
- # include Concerns::Presentable
25
+ include Concerns::Presentable
26
+ include Plutonium::Definition::DefineableProps
27
+ include Plutonium::Definition::ConfigAttr
26
28
  # include Concerns::WorkflowDSL
27
29
 
30
+ class Form < Plutonium::UI::Form::Interaction; end
31
+
32
+ config_attr :turbo
33
+ defineable_props :field, :input
34
+
28
35
  # Executes the interaction with the given arguments.
29
36
  #
30
37
  # @param args [Hash] The arguments to initialize the interaction.
@@ -33,17 +40,30 @@ module Plutonium
33
40
  new(**args).call
34
41
  end
35
42
 
43
+ def self.build_form(instance)
44
+ self::Form.new(instance || new)
45
+ end
46
+
36
47
  # Executes the interaction.
37
48
  #
38
49
  # @return [Plutonium::Interaction::Outcome] The result of the interaction.
39
50
  def call
40
51
  if valid?
41
- execute
52
+ outcome = execute
53
+ unless outcome.is_a?(Plutonium::Interaction::Outcome)
54
+ raise "#{self.class}#execute must return an instance of Plutonium::Interaction::Outcome.\n" \
55
+ "#{outcome.inspect} received instead"
56
+ end
57
+ outcome
42
58
  else
43
- failure(errors)
59
+ failure.with_message("An error occurred")
44
60
  end
45
61
  end
46
62
 
63
+ def build_form
64
+ self.class.build_form(self)
65
+ end
66
+
47
67
  private
48
68
 
49
69
  # Implement the main logic of the interaction.
@@ -59,16 +79,27 @@ module Plutonium
59
79
  #
60
80
  # @param value [Object] The value to be wrapped in the successful outcome.
61
81
  # @return [Plutonium::Interaction::Success] A successful outcome.
62
- def success(value)
63
- Success.new(value)
82
+ def succeed(value = nil)
83
+ Plutonium::Interaction::Outcome::Success.new(value)
84
+ end
85
+ alias_method :success, :succeed
86
+
87
+ def failed(errors = nil, attribute = :base)
88
+ case errors
89
+ when Hash
90
+ errors.each { |attribute, error| self.errors.add(attribute, error) }
91
+ else
92
+ Array(errors).each { |error| self.errors.add(attribute, error) }
93
+ end
94
+ failure
64
95
  end
65
96
 
66
97
  # Creates a failure outcome.
67
98
  #
68
99
  # @param errors [ActiveModel::Errors, Array<String>] The errors to be wrapped in the failure outcome.
69
100
  # @return [Plutonium::Interaction::Failure] A failure outcome.
70
- def failure(errors)
71
- Failure.new(errors)
101
+ def failure
102
+ Plutonium::Interaction::Outcome::Failure.new
72
103
  end
73
104
  end
74
105
  end
@@ -33,27 +33,39 @@ module Plutonium
33
33
  def presents(**options)
34
34
  self.presentation_metadata = options
35
35
  end
36
+
37
+ # Returns the label for the interaction.
38
+ #
39
+ # @return [String] The label defined in the presentation metadata or a default generated from the class name.
40
+ def label
41
+ presentation_metadata[:label] || name.demodulize.titleize
42
+ end
43
+
44
+ # Returns the icon for the interaction.
45
+ #
46
+ # @return [String, nil] The icon defined in the presentation metadata.
47
+ def icon
48
+ presentation_metadata[:icon]
49
+ end
50
+
51
+ # Returns the description for the interaction.
52
+ #
53
+ # @return [String, nil] The description defined in the presentation metadata.
54
+ def description
55
+ presentation_metadata[:description]
56
+ end
36
57
  end
37
58
 
38
- # Returns the label for the interaction.
39
- #
40
- # @return [String] The label defined in the presentation metadata or a default generated from the class name.
41
59
  def label
42
- self.class.presentation_metadata[:label] || self.class.name.demodulize.titleize
60
+ self.class.label
43
61
  end
44
62
 
45
- # Returns the icon for the interaction.
46
- #
47
- # @return [String, nil] The icon defined in the presentation metadata.
48
63
  def icon
49
- self.class.presentation_metadata[:icon]
64
+ self.class.icon
50
65
  end
51
66
 
52
- # Returns the description for the interaction.
53
- #
54
- # @return [String, nil] The description defined in the presentation metadata.
55
67
  def description
56
- self.class.presentation_metadata[:description]
68
+ self.class.description
57
69
  end
58
70
  end
59
71
  end
@@ -7,8 +7,7 @@ module Plutonium
7
7
  #
8
8
  # @abstract Subclass and override {#and_then}, {#map}, and {#to_response} to implement
9
9
  class Outcome
10
- # @return [Array<Array(String, Symbol)>] Messages associated with the outcome.
11
- attr_reader :messages
10
+ def messages = @messages || []
12
11
 
13
12
  # Checks if the outcome is successful.
14
13
  #
@@ -27,7 +26,7 @@ module Plutonium
27
26
  # Adds a message to the outcome.
28
27
  #
29
28
  # @param msg [String] The message to add.
30
- # @param type [Symbol] The type of the message (e.g., :notice, :error).
29
+ # @param type [Symbol] The type of the message (e.g., :notice, :alert).
31
30
  # @return [self]
32
31
  def with_message(msg, type = :notice)
33
32
  @messages ||= []
@@ -60,69 +59,92 @@ module Plutonium
60
59
  def to_response
61
60
  raise NotImplementedError, "#{self.class} must implement #to_response"
62
61
  end
63
- end
64
62
 
65
- # Represents a successful outcome of an interaction.
66
- class Success < Outcome
67
- # @return [Object] The value wrapped by this successful outcome.
68
- attr_reader :value
63
+ # Represents a successful outcome of an interaction.
64
+ class Success < Outcome
65
+ # @return [Object] The value wrapped by this successful outcome.
66
+ attr_reader :value
69
67
 
70
- # @param value [Object] The value to be wrapped in this successful outcome.
71
- def initialize(value)
72
- @value = value
73
- end
68
+ # @param value [Object] The value to be wrapped in this successful outcome.
69
+ def initialize(value)
70
+ @value = value
71
+ end
74
72
 
75
- # Chains another operation to be executed with the value of this outcome.
76
- #
77
- # @yield [Object] The value wrapped by this outcome.
78
- # @return [Outcome] The result of the yielded block.
79
- def and_then
80
- yield value
81
- end
73
+ # Chains another operation to be executed with the value of this outcome.
74
+ #
75
+ # @yield [Object] The value wrapped by this outcome.
76
+ # @return [Outcome] The result of the yielded block.
77
+ def and_then
78
+ yield value
79
+ end
82
80
 
83
- # Sets the response for this successful outcome.
84
- #
85
- # @param response [Plutonium::Interaction::Response::Base] The response to set.
86
- # @return [self]
87
- def with_response(response)
88
- @to_response = nil
89
- @response = response
90
- self
91
- end
81
+ # Sets the response for this successful outcome.
82
+ #
83
+ # @param response [Plutonium::Interaction::Response::Base] The response to set.
84
+ # @return [self]
85
+ def with_response(response)
86
+ @to_response = nil
87
+ @response = response
88
+ self
89
+ end
92
90
 
93
- # Converts this successful outcome to a response object.
94
- #
95
- # @return [Plutonium::Interaction::Response::Base] The response object.
96
- def to_response
97
- @to_response ||= begin
98
- @response ||= Response::Null.new(value)
99
- @response.with_flash(messages)
91
+ def with_redirect_response(*, **)
92
+ with_response(Response::Redirect.new(*, **))
100
93
  end
101
- end
102
- end
103
94
 
104
- # Represents a failed outcome of an interaction.
105
- class Failure < Outcome
106
- # @return [ActiveModel::Errors, Array<String>] The errors associated with this failure.
107
- attr_reader :errors
95
+ def with_render_response(*, **)
96
+ with_response(Response::Render.new(*, **))
97
+ end
108
98
 
109
- # @param errors [ActiveModel::Errors, Array<String>] The errors to be wrapped in this failure.
110
- def initialize(errors)
111
- @errors = errors
112
- end
99
+ def with_file_response(*, **)
100
+ with_response(Response::File.new(*, **))
101
+ end
113
102
 
114
- # Returns self without executing the given block, propagating the failure.
115
- #
116
- # @return [self]
117
- def and_then
118
- self
103
+ # Converts this successful outcome to a response object.
104
+ #
105
+ # @return [Plutonium::Interaction::Response::Base] The response object.
106
+ def to_response
107
+ @to_response ||= begin
108
+ @response ||= Response::Null.new(value)
109
+ @response.with_flash(messages)
110
+ end
111
+ end
119
112
  end
120
113
 
121
- # Returns self without setting a response.
122
- #
123
- # @return [self]
124
- def with_response(response)
125
- self
114
+ # Represents a failed outcome of an interaction.
115
+ class Failure < Outcome
116
+ # Adds a message to the outcome.
117
+ #
118
+ # @param msg [String] The message to add.
119
+ # @param type [Symbol] The type of the message (e.g., :notice, :alert).
120
+ # @return [self]
121
+ def with_message(msg, type = :alert)
122
+ super
123
+ end
124
+
125
+ # Returns self without executing the given block, propagating the failure.
126
+ #
127
+ # @return [self]
128
+ def and_then
129
+ self
130
+ end
131
+
132
+ # Returns self without setting a response.
133
+ #
134
+ # @return [self]
135
+ def with_response(response)
136
+ self
137
+ end
138
+
139
+ # Converts this failure outcome to a response object.
140
+ #
141
+ # @return [Plutonium::Interaction::Response::Null] The response object.
142
+ def to_response
143
+ @to_response ||= begin
144
+ @response ||= Response::Failure.new
145
+ @response.with_flash(messages)
146
+ end
147
+ end
126
148
  end
127
149
  end
128
150
  end
@@ -13,7 +13,9 @@ module Plutonium
13
13
  attr_reader :flash
14
14
 
15
15
  # Initializes a new Response::Base instance.
16
- def initialize
16
+ def initialize(*args, **options)
17
+ @args = args
18
+ @options = options
17
19
  @flash = []
18
20
  end
19
21