protos-protoform 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +9 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +245 -0
- data/LICENSE.txt +21 -0
- data/README.md +61 -0
- data/Rakefile +8 -0
- data/lib/generators/protoform/install/USAGE +8 -0
- data/lib/generators/protoform/install/install_generator.rb +39 -0
- data/lib/generators/protoform/install/templates/application_form.rb +36 -0
- data/lib/protoform/dom.rb +60 -0
- data/lib/protoform/field.rb +38 -0
- data/lib/protoform/field_collection.rb +39 -0
- data/lib/protoform/namespace.rb +159 -0
- data/lib/protoform/namespace_collection.rb +77 -0
- data/lib/protoform/node.rb +14 -0
- data/lib/protoform/rails/components/button.rb +28 -0
- data/lib/protoform/rails/components/checkbox.rb +28 -0
- data/lib/protoform/rails/components/component.rb +15 -0
- data/lib/protoform/rails/components/field_component.rb +18 -0
- data/lib/protoform/rails/components/input.rb +42 -0
- data/lib/protoform/rails/components/label.rb +22 -0
- data/lib/protoform/rails/components/select.rb +72 -0
- data/lib/protoform/rails/components/textarea.rb +14 -0
- data/lib/protoform/rails/form/field.rb +62 -0
- data/lib/protoform/rails/form.rb +121 -0
- data/lib/protoform/rails/option_mapper.rb +40 -0
- data/lib/protoform/rails/strong_parameters.rb +19 -0
- data/lib/protoform/version.rb +5 -0
- data/lib/protoform.rb +22 -0
- data/protos-protoform.gemspec +49 -0
- metadata +122 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protoform
|
4
|
+
# A Namespace maps and object to values, but doesn't actually have a value
|
5
|
+
# itself. For example, a `User` object or ActiveRecord model could be passed
|
6
|
+
# into the `:user` namespace. To access the values on a Namespace, the `field`
|
7
|
+
# can be called for single values.
|
8
|
+
#
|
9
|
+
# Additionally, to access namespaces within a namespace, such as if a `User
|
10
|
+
# has_many :addresses` in ActiveRecord, the `namespace` method can be called
|
11
|
+
# which will return another Namespace object and set the current Namespace as
|
12
|
+
# the parent.
|
13
|
+
class Namespace < Node
|
14
|
+
include Enumerable
|
15
|
+
|
16
|
+
attr_reader :object
|
17
|
+
|
18
|
+
def initialize(key, parent:, object: nil, field_class: Field)
|
19
|
+
super(key, parent:)
|
20
|
+
@object = object
|
21
|
+
@field_class = field_class
|
22
|
+
@children = {}
|
23
|
+
yield self if block_given?
|
24
|
+
end
|
25
|
+
|
26
|
+
# Creates a `Namespace` child instance with the parent set to the current
|
27
|
+
# instance, adds to the `@children` Hash to ensure duplicate child
|
28
|
+
# namespaces aren't created, then calls the method on the `@object` to get
|
29
|
+
# the child object to pass into that namespace.
|
30
|
+
#
|
31
|
+
# For example, if a `User#permission` returns a `Permission` object, we
|
32
|
+
# could map that to a form like this:
|
33
|
+
#
|
34
|
+
# ```ruby
|
35
|
+
# Protoform :user, object: User.new do |form|
|
36
|
+
# form.namespace :permission do |permission|
|
37
|
+
# form.field :role
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
# ```
|
41
|
+
def namespace(key, &block)
|
42
|
+
create_child(
|
43
|
+
key:,
|
44
|
+
child_class: self.class,
|
45
|
+
field_class: @field_class,
|
46
|
+
object: object_for(key:),
|
47
|
+
&block
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Maps the `Object#proprety` and `Object#property=` to a field in a web form
|
52
|
+
# that can be read and set by the form. For example, a User form might look
|
53
|
+
# like this:
|
54
|
+
#
|
55
|
+
# ```ruby
|
56
|
+
# Protoform :user, object: User.new do |form|
|
57
|
+
# form.field :email
|
58
|
+
# form.field :name
|
59
|
+
# end
|
60
|
+
# ```
|
61
|
+
def field(key)
|
62
|
+
create_child(
|
63
|
+
key:,
|
64
|
+
child_class: @field_class,
|
65
|
+
object:
|
66
|
+
).tap do |field|
|
67
|
+
yield field if block_given?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Wraps an array of objects in Namespace classes. For example, if
|
72
|
+
# `User#addresses` returns an enumerable or array of `Address` classes:
|
73
|
+
#
|
74
|
+
# ```ruby
|
75
|
+
# Protoform :user, object: User.new do |form|
|
76
|
+
# form.field :email
|
77
|
+
# form.field :name
|
78
|
+
# form.collection :addresses do |address|
|
79
|
+
# address.field(:street)
|
80
|
+
# address.field(:state)
|
81
|
+
# address.field(:zip)
|
82
|
+
# end
|
83
|
+
# end
|
84
|
+
# ```
|
85
|
+
# The object within the block is a `Namespace` object that maps each object
|
86
|
+
# within the enumerable to another `Namespace` or `Field`.
|
87
|
+
def collection(key, &block)
|
88
|
+
create_child(
|
89
|
+
key:,
|
90
|
+
child_class: NamespaceCollection,
|
91
|
+
field_class: @field_class,
|
92
|
+
&block
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Creates a Hash of Hashes and Arrays that represent the fields and
|
97
|
+
# collections of the Protoform. This can be used to safely update
|
98
|
+
# ActiveRecord objects without the need for Strong Parameters. You will want
|
99
|
+
# to make sure that all the fields displayed in the form are ones that
|
100
|
+
# you're OK updating from the generated hash.
|
101
|
+
def serialize
|
102
|
+
each_with_object({}) do |child, hash|
|
103
|
+
hash[child.key] = child.serialize
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Iterates through the children of the current namespace, which could be
|
108
|
+
# `Namespace` or `Field` objects.
|
109
|
+
def each(&block)
|
110
|
+
@children.values.each(&block)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Assigns a hash to the current namespace and children namespace.
|
114
|
+
def assign(hash)
|
115
|
+
tap do
|
116
|
+
each do |child|
|
117
|
+
child.assign hash[child.key] if hash.key? child.key
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Creates a root Namespace, which is essentially a form.
|
123
|
+
def self.root(*args, **kwargs, &block)
|
124
|
+
new(*args, parent: nil, **kwargs, &block)
|
125
|
+
end
|
126
|
+
|
127
|
+
protected
|
128
|
+
|
129
|
+
# Calls the corresponding method on the object for the `key` name, if it
|
130
|
+
# exists. For example if the `key` is `email` on `User`, this method would
|
131
|
+
# call `User#email` if the method is present.
|
132
|
+
#
|
133
|
+
# This method could be overwritten if the mapping between the `@object` and
|
134
|
+
# `key` name is not a method call. For example, a `Hash` would be accessed
|
135
|
+
# via `user[:email]` instead of `user.send(:email)`
|
136
|
+
def object_for(key:)
|
137
|
+
@object.send(key) if @object.respond_to? key
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
# Checks if the child exists. If it does then it returns that. If it
|
143
|
+
# doesn't, it will build the child.
|
144
|
+
def create_child(key:, child_class:, **kwargs, &block)
|
145
|
+
if (child = @children.fetch(key, nil))
|
146
|
+
# ensure that found children are also yielded
|
147
|
+
child.tap { yield child if block }
|
148
|
+
else
|
149
|
+
# new children added to hash and block passed to constructor
|
150
|
+
@children[key] = child_class.new(
|
151
|
+
key,
|
152
|
+
parent: self,
|
153
|
+
**kwargs,
|
154
|
+
&block
|
155
|
+
)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protoform
|
4
|
+
class NamespaceCollection < Node
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def initialize(key, parent:, field_class:, &template)
|
8
|
+
super(key, parent:)
|
9
|
+
@template = template
|
10
|
+
@field_class = field_class
|
11
|
+
@namespaces = enumerate(parent_collection)
|
12
|
+
end
|
13
|
+
|
14
|
+
def serialize
|
15
|
+
map(&:serialize)
|
16
|
+
end
|
17
|
+
|
18
|
+
def assign(array)
|
19
|
+
# The problem with zip-ing the array is if I need to add new
|
20
|
+
# elements to it and wrap it in the namespace.
|
21
|
+
zip(array) do |namespace, hash|
|
22
|
+
namespace.assign hash
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def each(&block)
|
27
|
+
@namespaces.each(&block)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def enumerate(enumerator)
|
33
|
+
Enumerator.new do |y|
|
34
|
+
enumerator.each.with_index do |object, key|
|
35
|
+
y << build_namespace(key, object:)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def build_namespace(index, **kwargs)
|
41
|
+
parent.class.new(
|
42
|
+
index,
|
43
|
+
parent: self,
|
44
|
+
field_class: @field_class,
|
45
|
+
**kwargs,
|
46
|
+
&@template
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def parent_collection
|
51
|
+
raise_missing_object unless @parent.respond_to? :object
|
52
|
+
@parent.object.send(@key).tap do |value|
|
53
|
+
raise_invalid_enumerator(value) unless value.respond_to? :each
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def raise_invalid_enumerator(value)
|
58
|
+
raise(
|
59
|
+
ArgumentError,
|
60
|
+
<<~ERROR
|
61
|
+
#{@parent.object.class} did not return something that responds to
|
62
|
+
:each for #{@key}. #{self.class} requires the model to return
|
63
|
+
something that can be enumerated for #{@key}.
|
64
|
+
Got #{value.class}: #{value.inspect} instead.
|
65
|
+
ERROR
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
def raise_missing_object
|
70
|
+
raise(
|
71
|
+
ArgumentError,
|
72
|
+
"Parent of a #{self.class} must respond to :object, " \
|
73
|
+
"#{@parent.class} does not"
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protoform
|
4
|
+
# Superclass for Namespace and Field classes. Not much to it other than it has
|
5
|
+
# a `name` and `parent` node attribute. Think of it as a tree.
|
6
|
+
class Node
|
7
|
+
attr_reader :key, :parent
|
8
|
+
|
9
|
+
def initialize(key, parent:)
|
10
|
+
@key = key
|
11
|
+
@parent = parent
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protoform
|
4
|
+
module Rails
|
5
|
+
module Components
|
6
|
+
class Button < FieldComponent
|
7
|
+
def view_template(&content)
|
8
|
+
content ||= proc { button_text }
|
9
|
+
button(**attrs, &content)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def button_text
|
15
|
+
attrs.fetch(:value, dom.value).titleize
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_attrs
|
19
|
+
{
|
20
|
+
id: dom.id,
|
21
|
+
name: dom.name,
|
22
|
+
value: dom.value
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protoform
|
4
|
+
module Rails
|
5
|
+
module Components
|
6
|
+
class Checkbox < FieldComponent
|
7
|
+
def view_template
|
8
|
+
# Rails has a hidden and checkbox input to deal with sending back
|
9
|
+
# a value to the server regardless of if the input is checked or not.
|
10
|
+
input(name: dom.name, type: :hidden, value: "0")
|
11
|
+
# The hard coded keys need to be in here so the user can't overrite
|
12
|
+
# them.
|
13
|
+
input(type: :checkbox, value: "1", **attrs)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def default_attrs
|
19
|
+
{
|
20
|
+
id: dom.id,
|
21
|
+
name: dom.name,
|
22
|
+
checked: field.value
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protoform
|
4
|
+
module Rails
|
5
|
+
module Components
|
6
|
+
class Input < FieldComponent
|
7
|
+
option :type, reader: false, default: -> { inferred_type }
|
8
|
+
|
9
|
+
def view_template
|
10
|
+
input(**attrs)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def default_attrs
|
16
|
+
{
|
17
|
+
id: dom.id,
|
18
|
+
name: dom.name,
|
19
|
+
type: @type
|
20
|
+
}.tap do |hash|
|
21
|
+
hash[:value] = field.value unless @type.to_sym == :file
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def inferred_type
|
26
|
+
case field.value
|
27
|
+
when URI
|
28
|
+
"url"
|
29
|
+
when Integer
|
30
|
+
"number"
|
31
|
+
when Date, DateTime
|
32
|
+
"date"
|
33
|
+
when Time
|
34
|
+
"time"
|
35
|
+
else
|
36
|
+
"text"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protoform
|
4
|
+
module Rails
|
5
|
+
module Components
|
6
|
+
class Label < Component
|
7
|
+
def view_template(&content)
|
8
|
+
content ||= proc { field.key.to_s.titleize }
|
9
|
+
label(**attrs, &content)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def default_attrs
|
15
|
+
{
|
16
|
+
for: dom.id
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protoform
|
4
|
+
module Rails
|
5
|
+
module Components
|
6
|
+
class Select < FieldComponent
|
7
|
+
option :collection, default: -> { [] }
|
8
|
+
option :include_blank, default: -> { true }
|
9
|
+
option :multiple, reader: false, default: -> { false }
|
10
|
+
|
11
|
+
def view_template(&options)
|
12
|
+
name = @multiple ? "#{attrs[:name]}[]" : attrs[:name]
|
13
|
+
|
14
|
+
if @multiple
|
15
|
+
input(
|
16
|
+
name:,
|
17
|
+
type: :hidden,
|
18
|
+
value: ""
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
if options
|
23
|
+
select(multiple: @multiple, **attrs, name:, &options)
|
24
|
+
else
|
25
|
+
select(multiple: @multiple, **attrs, name:) do
|
26
|
+
blank_option
|
27
|
+
options(*@collection)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def options(*collection)
|
33
|
+
map_options(collection).each do |key, value|
|
34
|
+
option(
|
35
|
+
selected: selected_value_for(key) ? "selected" : false,
|
36
|
+
value: key
|
37
|
+
) { value }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def blank_option(&block)
|
42
|
+
option(selected: field.value.nil?, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
def true_option(&block)
|
46
|
+
option(selected: field.value == true, value: true.to_s, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def false_option(&block)
|
50
|
+
option(selected: field.value == false, value: false.to_s, &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
def selected_value_for(key)
|
56
|
+
case field.value
|
57
|
+
when String, Symbol
|
58
|
+
field.value.to_s == key.to_s
|
59
|
+
when Array
|
60
|
+
field.value.include?(key)
|
61
|
+
else
|
62
|
+
field.value == key
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def map_options(collection)
|
67
|
+
OptionMapper.new(collection)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protoform
|
4
|
+
module Rails
|
5
|
+
class Form
|
6
|
+
# The Field class is designed to be extended to create custom forms. To
|
7
|
+
# override, in your subclass you may have something like this:
|
8
|
+
#
|
9
|
+
# ```ruby
|
10
|
+
# class MyForm < Protoform::Rails::Form
|
11
|
+
# class MyLabel < Protoform::Rails::Components::LabelComponent
|
12
|
+
# def view_template(&content)
|
13
|
+
# label(form: @field.dom.name, class: "text-bold", &content)
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# class Field < Field
|
18
|
+
# def label(**attributes)
|
19
|
+
# MyLabel.new(self, **attributes)
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
# ```
|
24
|
+
#
|
25
|
+
# Now all calls to `label` will have the `text-bold` class applied to it.
|
26
|
+
class Field < Protoform::Field
|
27
|
+
def button(...)
|
28
|
+
Components::Button.new(self, ...)
|
29
|
+
end
|
30
|
+
|
31
|
+
def input(...)
|
32
|
+
Components::Input.new(self, ...)
|
33
|
+
end
|
34
|
+
|
35
|
+
def checkbox(...)
|
36
|
+
Components::Checkbox.new(self, ...)
|
37
|
+
end
|
38
|
+
|
39
|
+
def label(...)
|
40
|
+
Components::Label.new(self, ...)
|
41
|
+
end
|
42
|
+
|
43
|
+
def textarea(...)
|
44
|
+
Components::Textarea.new(self, ...)
|
45
|
+
end
|
46
|
+
|
47
|
+
def select(*collection, **attributes, &block)
|
48
|
+
Components::Select.new(
|
49
|
+
self,
|
50
|
+
collection:,
|
51
|
+
**attributes,
|
52
|
+
&block
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
def title
|
57
|
+
key.to_s.titleize
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protoform
|
4
|
+
module Rails
|
5
|
+
Component = ::ApplicationComponent
|
6
|
+
# A Protos::Component class that accepts a model and sets
|
7
|
+
# a `Protoform::Namespace` with the `Object#model_name` as the key and maps
|
8
|
+
# the object to form fields and namespaces.
|
9
|
+
#
|
10
|
+
# The `Form::Field` is a class that's meant to be extended so you can
|
11
|
+
# customize the `Form` inputs to your applications needs. Defaults for the
|
12
|
+
# `input`, `button`, `label`, and `textarea` tags are provided.
|
13
|
+
#
|
14
|
+
# The `Form` component also handles Rails authenticity tokens via the
|
15
|
+
# `authenticity_toklen_field` method and the HTTP verb via the
|
16
|
+
# `_method_field`.
|
17
|
+
class Form < Component
|
18
|
+
param :model, reader: false
|
19
|
+
option :helpers, reader: false, default: -> {}
|
20
|
+
option :action, reader: false, default: -> {}
|
21
|
+
option :method, reader: false, default: -> {}
|
22
|
+
option :namespace, reader: false, default: -> do
|
23
|
+
Namespace.root(key, object: @model, field_class: self.class::Field)
|
24
|
+
end
|
25
|
+
|
26
|
+
def field(...)
|
27
|
+
@namespace.field(...)
|
28
|
+
end
|
29
|
+
|
30
|
+
def collection(...)
|
31
|
+
@namespace.collection(...)
|
32
|
+
end
|
33
|
+
|
34
|
+
def namespace(...)
|
35
|
+
@namespace.namespace(...)
|
36
|
+
end
|
37
|
+
|
38
|
+
def assign(...)
|
39
|
+
@namespace.assign(...)
|
40
|
+
end
|
41
|
+
|
42
|
+
def serialize(...)
|
43
|
+
@namespace.serialize(...)
|
44
|
+
end
|
45
|
+
|
46
|
+
def around_template(&block)
|
47
|
+
form_tag do
|
48
|
+
authenticity_token_field
|
49
|
+
_method_field
|
50
|
+
super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def form_tag(&block)
|
55
|
+
form action:, method: form_method, **attrs, &block
|
56
|
+
end
|
57
|
+
|
58
|
+
def view_template(&block)
|
59
|
+
yield_content(&block)
|
60
|
+
end
|
61
|
+
|
62
|
+
def submit(value = submit_value, **attributes)
|
63
|
+
input(
|
64
|
+
**attributes.merge(
|
65
|
+
name: "commit",
|
66
|
+
type: "submit",
|
67
|
+
value:
|
68
|
+
)
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
def key
|
73
|
+
@model.model_name.param_key
|
74
|
+
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
|
78
|
+
def authenticity_token_field
|
79
|
+
input(
|
80
|
+
name: "authenticity_token",
|
81
|
+
type: "hidden",
|
82
|
+
value: helpers.form_authenticity_token
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
def _method_field
|
87
|
+
input(
|
88
|
+
name: "_method",
|
89
|
+
type: "hidden",
|
90
|
+
value: _method_field_value
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
def _method_field_value
|
95
|
+
@method || (@model.persisted? ? "patch" : "post")
|
96
|
+
end
|
97
|
+
|
98
|
+
def submit_value
|
99
|
+
"#{resource_action.to_s.capitalize} #{@model.model_name}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def resource_action
|
103
|
+
@model.persisted? ? :update : :create
|
104
|
+
end
|
105
|
+
|
106
|
+
def action
|
107
|
+
@action ||= helpers.url_for(action: resource_action)
|
108
|
+
end
|
109
|
+
|
110
|
+
def form_method
|
111
|
+
@method.to_s.downcase == "get" ? "get" : "post"
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def helpers
|
117
|
+
@helpers ||= super
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|