super 0.0.16 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/super/application.js +1401 -125
  3. data/app/assets/stylesheets/super/application.css +90702 -90026
  4. data/app/controllers/super/application_controller.rb +49 -6
  5. data/app/controllers/super/substructure_controller.rb +121 -37
  6. data/app/views/layouts/super/application.html.erb +1 -1
  7. data/app/views/super/application/_batch_button.html.erb +12 -0
  8. data/app/views/super/application/_batch_checkbox.csv.erb +1 -0
  9. data/app/views/super/application/_batch_checkbox.html.erb +5 -0
  10. data/app/views/super/application/_batch_form.html.erb +3 -0
  11. data/app/views/super/application/_collection_header.html.erb +7 -6
  12. data/app/views/super/application/_csv_button.html.erb +25 -0
  13. data/app/views/super/application/_display_actions.html.erb +2 -2
  14. data/app/views/super/application/_filter.html.erb +62 -2
  15. data/app/views/super/application/_layout.html.erb +13 -14
  16. data/app/views/super/application/_link.html.erb +8 -0
  17. data/app/views/super/application/_member_header.html.erb +7 -7
  18. data/app/views/super/application/_pagination.html.erb +1 -0
  19. data/app/views/super/application/_site_header.html.erb +4 -4
  20. data/app/views/super/application/_sort_expression.html.erb +2 -2
  21. data/app/views/super/application/_view_chain.html.erb +5 -0
  22. data/app/views/super/application/index.csv.erb +14 -0
  23. data/config/locales/en.yml +8 -0
  24. data/frontend/super-frontend/dist/application.css +90702 -90026
  25. data/frontend/super-frontend/dist/application.js +1401 -125
  26. data/frontend/super-frontend/dist/package.json +13 -0
  27. data/lib/generators/super/webpacker/USAGE +1 -7
  28. data/lib/generators/super/webpacker/templates/pack_super_application.js.tt +2 -0
  29. data/lib/generators/super/webpacker/webpacker_generator.rb +10 -6
  30. data/lib/super/cheat.rb +1 -0
  31. data/lib/super/display/guesser.rb +1 -1
  32. data/lib/super/display/schema_types.rb +6 -1
  33. data/lib/super/display.rb +2 -1
  34. data/lib/super/engine.rb +5 -0
  35. data/lib/super/error.rb +12 -0
  36. data/lib/super/filter/form_object.rb +74 -48
  37. data/lib/super/filter/guesser.rb +2 -0
  38. data/lib/super/filter/operator.rb +90 -64
  39. data/lib/super/filter/schema_types.rb +63 -80
  40. data/lib/super/filter.rb +1 -1
  41. data/lib/super/form/builder.rb +6 -3
  42. data/lib/super/form/field_transcript.rb +43 -0
  43. data/lib/super/form/guesser.rb +1 -1
  44. data/lib/super/form/schema_types.rb +11 -20
  45. data/lib/super/layout.rb +9 -33
  46. data/lib/super/link.rb +2 -7
  47. data/lib/super/link_builder.rb +0 -4
  48. data/lib/super/packaged_asset.rb +49 -0
  49. data/lib/super/pagination.rb +2 -1
  50. data/lib/super/reorderable_hash.rb +88 -0
  51. data/lib/super/reset.rb +20 -1
  52. data/lib/super/schema.rb +4 -0
  53. data/lib/super/version.rb +1 -1
  54. data/lib/super/view_chain.rb +25 -0
  55. data/lib/super.rb +4 -0
  56. metadata +46 -9
  57. data/app/views/super/application/_filter_type_select.html.erb +0 -21
  58. data/app/views/super/application/_filter_type_text.html.erb +0 -18
  59. data/app/views/super/application/_filter_type_timestamp.html.erb +0 -24
  60. data/app/views/super/application/_form_field_select.html.erb +0 -1
  61. data/lib/generators/super/webpacker/templates/pack_super_application.js.erb.tt +0 -2
@@ -2,112 +2,95 @@
2
2
 
3
3
  module Super
4
4
  class Filter
5
- # This schema type is used to configure the filtering form on your +#index+
6
- # action.
7
- #
8
- # The +operators:+ keyword argument can be left out in each case. There is
9
- # a default set of operators that are provided.
10
- #
11
5
  # Note: The constants under "Defined Under Namespace" are considered
12
6
  # private.
13
- #
14
- # class MemberDashboard
15
- # # ...
16
- #
17
- # def filter_schema
18
- # Super::Filter.new do |fields, type|
19
- # fields[:name] = type.text(operators: [
20
- # Super::Filter::Operator.eq,
21
- # Super::Filter::Operator.contain,
22
- # Super::Filter::Operator.ncontain,
23
- # Super::Filter::Operator.start,
24
- # Super::Filter::Operator.end,
25
- # ])
26
- # fields[:rank] = type.select(collection: Member.ranks.values)
27
- # fields[:position] = type.text(operators: [
28
- # Super::Filter::Operator.eq,
29
- # Super::Filter::Operator.neq,
30
- # Super::Filter::Operator.contain,
31
- # Super::Filter::Operator.ncontain,
32
- # ])
33
- # fields[:ship_id] = type.select(
34
- # collection: Ship.all.map { |s| ["#{s.name} (Ship ##{s.id})", s.id] },
35
- # )
36
- # fields[:created_at] = type.timestamp
37
- # fields[:updated_at] = type.timestamp
38
- # end
39
- # end
40
- #
41
- # # ...
42
- # end
43
7
  class SchemaTypes
44
- class Text
45
- def initialize(partial_path:, operators:)
46
- @partial_path = partial_path
47
- @operators = operators
48
- end
8
+ class OperatorList
9
+ include Enumerable
49
10
 
50
- attr_reader :operators
11
+ def initialize(*new_operators)
12
+ @operators = {}
13
+ @operator_transcript = {}
14
+ @fallback_transcript = nil
51
15
 
52
- def to_partial_path
53
- @partial_path
16
+ push(*new_operators)
54
17
  end
55
18
 
56
- def q
57
- [:q]
58
- end
59
- end
19
+ def push(*new_operators)
20
+ new_operators.flatten.map(&:dup).each do |new_operator|
21
+ new_identifier = new_operator.identifier.to_s
22
+
23
+ raise Error::AlreadyRegistered if @operators.key?(new_identifier)
60
24
 
61
- class Select
62
- def initialize(collection:, operators:)
63
- @collection = collection
64
- @operators = operators
25
+ @operators[new_identifier] = new_operator
26
+ end
27
+
28
+ nil
65
29
  end
66
30
 
67
- attr_reader :collection
68
- attr_reader :operators
31
+ alias add push
32
+
33
+ def each
34
+ return enum_for(:each) if !block_given?
69
35
 
70
- def to_partial_path
71
- "filter_type_select"
36
+ @operators.each do |identifier, operator|
37
+ yield(
38
+ OperatorWithFieldTranscript.new(
39
+ operator,
40
+ @operator_transcript[identifier] || @fallback_transcript
41
+ )
42
+ )
43
+ end
72
44
  end
73
45
 
74
- def q
75
- [:q]
46
+ def transcribe(operator_identifier = nil)
47
+ transcript = Form::FieldTranscript.new
48
+ yield transcript
49
+
50
+ if operator_identifier.nil?
51
+ @fallback_transcript = transcript
52
+ else
53
+ @operator_transcript[operator_identifier.to_s] = transcript
54
+ end
55
+
56
+ self
76
57
  end
77
58
  end
78
59
 
79
- class Timestamp
80
- def initialize(operators:)
81
- @operators = operators
60
+ class OperatorWithFieldTranscript
61
+ def initialize(operator, field_transcript)
62
+ @operator = operator
63
+ @field_transcript = field_transcript
82
64
  end
83
65
 
84
- attr_reader :operators
85
-
86
- def to_partial_path
87
- "filter_type_timestamp"
66
+ Super::Filter::Operator.instance_methods(false).each do |name|
67
+ delegate name, to: :@operator
88
68
  end
89
69
 
90
- def q
91
- [:q0, :q1]
92
- end
70
+ attr_reader :field_transcript
71
+ end
72
+
73
+ def use(*identifiers)
74
+ found_operators = identifiers.flatten.map { |id| Operator[id] }
75
+ OperatorList.new(*found_operators)
76
+ end
77
+
78
+ def select(collection)
79
+ use("eq", "null", "nnull")
80
+ .transcribe { |f| f.super.select(collection) }
93
81
  end
94
82
 
95
- def select(collection:, operators: Filter::Operator.select_defaults)
96
- Select.new(
97
- collection: collection,
98
- operators: operators
99
- )
83
+ def text
84
+ use("contain", "ncontain", "blank", "nblank")
100
85
  end
101
86
 
102
- def text(operators: Filter::Operator.text_defaults)
103
- Text.new(
104
- partial_path: "filter_type_text",
105
- operators: operators
106
- )
87
+ def timestamp
88
+ use("between", "null", "nnull")
89
+ .transcribe { |f| f.super.datetime_flatpickr }
107
90
  end
108
91
 
109
- def timestamp(operators: Filter::Operator.range_defaults)
110
- Timestamp.new(operators: operators)
92
+ def boolean
93
+ use("true", "false", "null", "nnull")
111
94
  end
112
95
  end
113
96
  end
data/lib/super/filter.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Super
4
4
  class Filter
5
5
  def initialize
6
- @schema_type = Filter::SchemaTypes.new
6
+ @schema_type = SchemaTypes.new
7
7
  @fields = Schema::Fields.new
8
8
 
9
9
  yield(@fields, @schema_type)
@@ -71,7 +71,8 @@ module Super
71
71
  )
72
72
  options[:class] = join_classes(defaults[:class], options[:class])
73
73
  options[:data] = defaults[:data].deep_merge(options[:data] || {})
74
- options[:value] = @builder.object.public_send(attribute).presence&.iso8601
74
+ options[:value] = @builder.object.public_send(attribute).presence
75
+ options[:value] = options[:value].iso8601 if options[:value].respond_to?(:iso8601)
75
76
 
76
77
  @builder.text_field(attribute, options)
77
78
  end
@@ -91,7 +92,8 @@ module Super
91
92
  )
92
93
  options[:class] = join_classes(defaults[:class], options[:class])
93
94
  options[:data] = defaults[:data].deep_merge(options[:data] || {})
94
- options[:value] = @builder.object.public_send(attribute).presence&.iso8601
95
+ options[:value] = @builder.object.public_send(attribute).presence
96
+ options[:value] = options[:value].iso8601 if options[:value].respond_to?(:iso8601)
95
97
 
96
98
  @builder.text_field(attribute, options)
97
99
  end
@@ -112,7 +114,8 @@ module Super
112
114
  )
113
115
  options[:class] = join_classes(defaults[:class], options[:class])
114
116
  options[:data] = defaults[:data].deep_merge(options[:data] || {})
115
- options[:value] = @builder.object.public_send(attribute).presence&.strftime("%H:%M:%S")
117
+ options[:value] = @builder.object.public_send(attribute).presence
118
+ options[:value] = options[:value].strftime("%H:%M:%S") if options[:value].respond_to?(:strftime)
116
119
 
117
120
  @builder.text_field(attribute, options)
118
121
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ class Form
5
+ # Holds a recording of a form field definition
6
+ class FieldTranscript
7
+ def initialize
8
+ @super = false
9
+ end
10
+
11
+ attr_reader :method_name
12
+ attr_reader :args
13
+ attr_reader :kwargs
14
+
15
+ def super
16
+ @super = true
17
+ self
18
+ end
19
+
20
+ def super?
21
+ @super
22
+ end
23
+
24
+ def method_missing(new_method_name, *args, **kwargs)
25
+ if @method_name.present?
26
+ method_chain =
27
+ if super?
28
+ "super.#{@method_name}"
29
+ else
30
+ @method_name.to_s
31
+ end
32
+
33
+ raise Error::AlreadyTranscribed, "This instance already holds a transcription for: #{method_chain}"
34
+ end
35
+
36
+ @method_name = new_method_name
37
+ @args = args
38
+ @kwargs = kwargs
39
+ @method_name
40
+ end
41
+ end
42
+ end
43
+ end
@@ -30,7 +30,7 @@ module Super
30
30
  when :date
31
31
  @type.date_flatpickr
32
32
  else
33
- @type.string
33
+ @type.text_field
34
34
  end
35
35
  end
36
36
  end
@@ -97,7 +97,7 @@ module Super
97
97
  @fields = fields
98
98
  end
99
99
 
100
- def generic(partial_path, **extras)
100
+ def partial(partial_path, **extras)
101
101
  Generic.new(partial_path: partial_path, extras: extras, nested: {})
102
102
  end
103
103
 
@@ -105,17 +105,14 @@ module Super
105
105
  Direct.new(super_builder: super_builder, method_name: method_name, args: args, kwargs: kwargs)
106
106
  end
107
107
 
108
- def select(**extras)
109
- Generic.new(partial_path: "form_field_select", extras: extras, nested: {})
108
+ def select(*args, **kwargs)
109
+ Direct.new(super_builder: true, method_name: :select!, args: args, kwargs: kwargs)
110
110
  end
111
111
 
112
112
  def text_field(*args, **kwargs)
113
113
  Direct.new(super_builder: true, method_name: :text_field!, args: args, kwargs: kwargs)
114
114
  end
115
115
 
116
- alias string text_field
117
- alias text text_field
118
-
119
116
  def rich_text_area(*args, **kwargs)
120
117
  Direct.new(super_builder: true, method_name: :rich_text_area!, args: args, kwargs: kwargs)
121
118
  end
@@ -124,20 +121,14 @@ module Super
124
121
  Direct.new(super_builder: true, method_name: :check_box!, args: args, kwargs: kwargs)
125
122
  end
126
123
 
127
- alias checkbox check_box
128
-
129
124
  def date_flatpickr(*args, **kwargs)
130
125
  Direct.new(super_builder: true, method_name: :date_flatpickr!, args: args, kwargs: kwargs)
131
126
  end
132
127
 
133
- alias flatpickr_date date_flatpickr
134
-
135
128
  def datetime_flatpickr(*args, **kwargs)
136
129
  Direct.new(super_builder: true, method_name: :datetime_flatpickr!, args: args, kwargs: kwargs)
137
130
  end
138
131
 
139
- alias flatpickr_datetime datetime_flatpickr
140
-
141
132
  def hidden_field(*args, **kwargs)
142
133
  Direct.new(super_builder: false, method_name: :hidden_field, args: args, kwargs: kwargs)
143
134
  end
@@ -150,29 +141,29 @@ module Super
150
141
  Direct.new(super_builder: true, method_name: :time_flatpickr!, args: args, kwargs: kwargs)
151
142
  end
152
143
 
153
- alias flatpickr_time time_flatpickr
154
-
155
144
  def has_many(reader, **extras)
156
- nested = @fields.nested do
157
- yield
145
+ subfields = Schema::Fields.new
146
+ @fields.nested do
147
+ yield subfields
158
148
  end
159
149
 
160
150
  Generic.new(
161
151
  partial_path: "form_has_many",
162
152
  extras: extras.merge(reader: reader),
163
- nested: nested
153
+ nested: subfields.to_h
164
154
  )
165
155
  end
166
156
 
167
157
  def has_one(reader, **extras)
168
- nested = @fields.nested do
169
- yield
158
+ subfields = Schema::Fields.new
159
+ @fields.nested do
160
+ yield subfields
170
161
  end
171
162
 
172
163
  Generic.new(
173
164
  partial_path: "form_has_one",
174
165
  extras: extras.merge(reader: reader),
175
- nested: nested
166
+ nested: subfields.to_h
176
167
  )
177
168
  end
178
169
 
data/lib/super/layout.rb CHANGED
@@ -6,44 +6,20 @@ module Super
6
6
  class Layout
7
7
  include Super::Partial::Resolving
8
8
 
9
- def initialize(headers: nil, asides: nil, mains: nil, footers: nil)
10
- @headers = Array(headers).compact
11
- @asides = Array(asides).compact
12
- @mains = Array(mains).compact
13
- @footers = Array(footers).compact
9
+ def initialize(header: nil, aside: nil, main: nil, footer: nil)
10
+ @header = header
11
+ @aside = aside
12
+ @main = main
13
+ @footer = footer
14
14
  end
15
15
 
16
- attr_reader :headers
17
- attr_reader :asides
18
- attr_reader :mains
19
- attr_reader :footers
16
+ attr_reader :header
17
+ attr_reader :aside
18
+ attr_reader :main
19
+ attr_reader :footer
20
20
 
21
21
  def to_partial_path
22
22
  "layout"
23
23
  end
24
-
25
- def resolve(template)
26
- @resolved_headers = resolve_for_rendering(template, headers, nil)
27
- @resolved_asides = resolve_for_rendering(template, asides, nil)
28
- @resolved_mains = resolve_for_rendering(template, mains, nil)
29
- @resolved_footers = resolve_for_rendering(template, footers, nil)
30
- self
31
- end
32
-
33
- def resolved_headers
34
- @resolved_headers || []
35
- end
36
-
37
- def resolved_asides
38
- @resolved_asides || []
39
- end
40
-
41
- def resolved_mains
42
- @resolved_mains || []
43
- end
44
-
45
- def resolved_footers
46
- @resolved_footers || []
47
- end
48
24
  end
49
25
  end
data/lib/super/link.rb CHANGED
@@ -107,13 +107,8 @@ module Super
107
107
  @href = Super::Compatability.polymorphic_path_container.polymorphic_path(@href)
108
108
  end
109
109
 
110
- def to_s(default_options: nil)
111
- default_options ||= {}
112
- ActionController::Base.helpers.link_to(
113
- text,
114
- href,
115
- default_options.deep_merge(options)
116
- )
110
+ def to_partial_path
111
+ "link"
117
112
  end
118
113
 
119
114
  def ==(other)
@@ -19,10 +19,6 @@ module Super
19
19
 
20
20
  attr_reader :requirements
21
21
 
22
- def to_s(default_options: nil, **kwargs)
23
- resolve(**kwargs).to_s(default_options: default_options)
24
- end
25
-
26
22
  def resolve(**kwargs)
27
23
  Link.new(
28
24
  into_value(@text, kwargs),
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ class PackagedAsset
5
+ VERSION_BEGINNING = /\A\d+\.\d+.\d+/.freeze
6
+
7
+ class << self
8
+ attr_accessor :warning_message
9
+ end
10
+
11
+ def self.comparable_super_version
12
+ ::Super::VERSION[VERSION_BEGINNING]
13
+ end
14
+
15
+ def self.version_matches_gem?(package_json_path)
16
+ return true if ENV.key?("SUPER_IGNORE_PACKAGE_JSON_VERSION")
17
+
18
+ asset = new(package_json_path)
19
+
20
+ return true if !asset.comparable_version
21
+
22
+ asset.comparable_version == comparable_super_version
23
+ end
24
+
25
+ def initialize(package_json_path)
26
+ @package_json_path = package_json_path
27
+ end
28
+
29
+ def full_version
30
+ if instance_variable_defined?(:@full_version)
31
+ return @full_version
32
+ end
33
+
34
+ @full_version = JSON.parse(@package_json_path.read).dig("dependencies", "@superadministration/super")
35
+ rescue
36
+ @full_version = nil
37
+ end
38
+
39
+ def comparable_version
40
+ if instance_variable_defined?(:@asset_version)
41
+ return @asset_version
42
+ end
43
+
44
+ @asset_version = full_version[VERSION_BEGINNING]
45
+ rescue
46
+ @asset_version = nil
47
+ end
48
+ end
49
+ end
@@ -76,9 +76,10 @@ module Super
76
76
  module ControllerMethods
77
77
  def index
78
78
  super
79
+ return if !@records
79
80
  @pagination = initialize_pagination
80
81
  @records = paginate_records
81
- @view.mains.first.parts.push(:@pagination)
82
+ @view.main.insert(:pagination, @pagination, before: :main)
82
83
  end
83
84
  end
84
85
  end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ class ReorderableHash
5
+ include TSort
6
+ include Enumerable
7
+
8
+ UNDEFINED = BasicObject.new
9
+
10
+ def initialize(data = {})
11
+ @data = data
12
+ @ordering = {}
13
+ keys = @data.keys
14
+ dependencies = []
15
+ keys.each do |key|
16
+ @ordering[key] = dependencies.dup
17
+ dependencies.push(key)
18
+ end
19
+ end
20
+
21
+ def insert(key, value, before: UNDEFINED, after: UNDEFINED)
22
+ if @ordering.key?(key) || @data.key?(key)
23
+ raise Super::Error::ReorderableHash::DuplicateKey, "Duplicate key: #{key}"
24
+ end
25
+ @ordering[key] = []
26
+ @data[key] = value
27
+
28
+ order(key, before: before, after: after)
29
+
30
+ nil
31
+ end
32
+
33
+ def order(key, before: UNDEFINED, after: UNDEFINED)
34
+ if before != UNDEFINED
35
+ if !@ordering.key?(before)
36
+ raise KeyError, "Before key not found. Have: #{@data.keys} Requested: #{before}"
37
+ end
38
+ @ordering[before].push(key)
39
+ end
40
+
41
+ if after != UNDEFINED
42
+ if !@ordering.key?(after)
43
+ raise KeyError, "After key not found. Have: #{@data.keys} Requested: #{after}"
44
+ end
45
+ @ordering[key].push(after)
46
+ end
47
+ end
48
+
49
+ def tsort_each_node(&block)
50
+ @ordering.each_key(&block)
51
+ end
52
+
53
+ def tsort_each_child(node, &block)
54
+ dependencies = @ordering.fetch(node) { [] }
55
+ dependencies.each(&block)
56
+ end
57
+
58
+ def []=(key, where, value)
59
+ insert(key, value, **where)
60
+ end
61
+
62
+ def keys
63
+ tsort
64
+ end
65
+
66
+ def values
67
+ keys.each_with_object([]) do |key, array|
68
+ array.push(@data[key])
69
+ end
70
+ end
71
+
72
+ def to_h
73
+ keys.each_with_object({}) do |key, hash|
74
+ hash[key] = @data[key]
75
+ end
76
+ end
77
+
78
+ def each
79
+ if !block_given?
80
+ return enum_for(:each)
81
+ end
82
+
83
+ tsort_each do |key|
84
+ yield key, @data[key]
85
+ end
86
+ end
87
+ end
88
+ end
data/lib/super/reset.rb CHANGED
@@ -4,6 +4,20 @@ module Super
4
4
  module Reset
5
5
  extend ActiveSupport::Concern
6
6
 
7
+ KEEP = {
8
+ # Defined by Rails
9
+ _layout: true,
10
+ _generate_paths_by_default: true,
11
+
12
+ # Defined in Super::SubstructureController
13
+ navigation: true,
14
+ page_title: true,
15
+
16
+ # Defined in Super::ApplicationController
17
+ current_action: true,
18
+ with_current_action: true,
19
+ }
20
+
7
21
  included do
8
22
  undef_method :index
9
23
  undef_method :show
@@ -14,7 +28,12 @@ module Super
14
28
  undef_method :destroy
15
29
 
16
30
  Super::SubstructureController.private_instance_methods(false).each do |imethod|
17
- next if imethod == :navigation
31
+ next if KEEP.key?(imethod)
32
+ undef_method imethod
33
+ end
34
+
35
+ Super::ApplicationController.private_instance_methods(false).each do |imethod|
36
+ next if KEEP.key?(imethod)
18
37
  undef_method imethod
19
38
  end
20
39
  end
data/lib/super/schema.rb CHANGED
@@ -42,6 +42,10 @@ module Super
42
42
  enum_for(:each)
43
43
  end
44
44
 
45
+ def delete(key)
46
+ @backing.delete(key)
47
+ end
48
+
45
49
  def replace(other)
46
50
  @backing = other
47
51
  end
data/lib/super/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Super
4
- VERSION = "0.0.16"
4
+ VERSION = "0.19.0"
5
5
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ class ViewChain
5
+ def initialize(chain)
6
+ @data = ReorderableHash.new(chain)
7
+ end
8
+
9
+ def chain
10
+ @chain ||= @data.values
11
+ end
12
+
13
+ def insert(*args, **kwargs)
14
+ if instance_variable_defined?(:@chain)
15
+ raise Error::ViewChain::ChainAlreadyStarted
16
+ end
17
+
18
+ @data.insert(*args, **kwargs)
19
+ end
20
+
21
+ def to_partial_path
22
+ "view_chain"
23
+ end
24
+ end
25
+ end