formula 1.1.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b3c844a3b82fc2394cc192c4eaaf04990a6b21a7
4
- data.tar.gz: 4539895dac54e7330b3c5f2c429499fabb1b11f5
2
+ SHA256:
3
+ metadata.gz: 8e753004d2065d2a0aa15c73ac8393b54de9ae40086f2f5da874e0cd1a0ccd8a
4
+ data.tar.gz: 21797db2580b4ae567942e4b3c36e2c86caed7645d58ecd4ba10cecb25449ad5
5
5
  SHA512:
6
- metadata.gz: e6e13d92a4e16f4aebdfd1925edd425223404984fd2fb721454011b72d331a2080684eafb619781afc803d13c48d4cff34aa5ff31f360792ae95587d26a64f86
7
- data.tar.gz: c4cb45eb4a68624974886b3c62c16209e89f6447a20e5d5daef21ef904a82b98e8271bd52207be19486f4019bb8c4afa26c410efe810fbf76e144d34d700d1d2
6
+ metadata.gz: 59d014229aa1940f2b0d08b263d6bc49ab9caa836b4e4b993bc3c9407b2544fd789e8a36f1e324a19f467d8895b23ab3d15fa14fd3af27c77b426abe25c908b4
7
+ data.tar.gz: cd47a5b0382b1bf898a2e0691c3234504e016ab29d96496290127903ae3bafe6140cedd651e554f3f2a626ecf43293d1cb4fc318ef833e236417cca9bd11b522
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ gem 'bcrypt'
8
+ gem 'puma'
9
+ gem 'rubocop'
10
+ gem 'sqlite3'
11
+ gem 'yard'
data/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Formula
2
+
3
+ Formula is a Rails form helper that generates awesome markup. The project lets users create semantically beautiful forms without introducing too much syntax.
4
+
5
+ ## Requirements
6
+
7
+ The gem is tested with:
8
+
9
+ - Ruby 3.3
10
+ - Rails 7.2
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ gem install formula
16
+ ```
17
+
18
+ ## Examples
19
+
20
+ ```erb
21
+ <%= formula_form_for @user do |f| %>
22
+ <%= f.input :email %>
23
+ <%= f.input :password %>
24
+ <%= f.button 'Save' %>
25
+ <% end %>
26
+ ```
27
+
28
+ ```erb
29
+ <%= formula_form_for @user do |f| %>
30
+ <%= f.input :email, label: "Email:", hint: "We promise never to bother you." %>
31
+ <%= f.input :password, label: "Password:", hint: "Must be at least six characters." %>
32
+ <%= f.button 'Save' %>
33
+ <% end %>
34
+ ```
35
+
36
+ ```erb
37
+ <%= formula_form_for @company do |f|
38
+ <%= f.input :url, container: { class: 'third' }, input: { class: 'fill' } %>
39
+ <%= f.input :phone, container: { class: 'third' }, input: { class: 'fill' } %>
40
+ <%= f.input :email, container: { class: 'third' }, input: { class: 'fill' } %>
41
+ <%= f.button 'Save', button: { class: 'fancy' } %>
42
+ <% end %>
43
+ ```
44
+
45
+ ```erb
46
+ <%= formula_form_for @user do |f| %>
47
+ <%= f.input :email, label: "Email:" %>
48
+ <%= f.input :password, label: "Password:" %>
49
+ <%= f.input :gender, label: 'Gender:', as: :select, choices: User::GENDERS %>
50
+ <%= formula_fields_for @user.payment do |payment_f| %>
51
+ <%= payment_f.input :credit_card_number, label: 'Number:' %>
52
+ <%= payment_f.input :credit_card_expiration, label: 'Expiration:' %>
53
+ <% end %>
54
+ <%= f.button 'Save', button: { class: 'fancy' } %>
55
+ <% end %>
56
+ ```
57
+
58
+ ```erb
59
+ <%= formula_form_for @user do |f| %>
60
+ <%= f.block :favourite %>
61
+ <% @favourites.each do |favourite| %>
62
+ ...
63
+ <% end %>
64
+ <% end %>
65
+ <%= f.button 'Save', button: { class: 'fancy' } %>
66
+ <% end %>
67
+ ```
68
+
69
+ ## Copyright
70
+
71
+ Copyright (c) 2010 - 2024 Kevin Sylvestre. See LICENSE for details.
data/bin/rubocop ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ require "rubygems"
3
+ require "bundler/setup"
4
+
5
+ # explicit rubocop config increases performance slightly while avoiding config confusion.
6
+ ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__))
7
+
8
+ load Gem.bin_path("rubocop", "rubocop")
data/bin/test ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path("../test", __dir__)
3
+
4
+ require "bundler/setup"
5
+ require "rails/plugin/test"
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Formula
4
+ class Config
5
+ # @!attribute [rw] box_options
6
+ # @return [Hash]
7
+ attr_accessor :box_options
8
+
9
+ # @!attribute [rw] area_options
10
+ # @return [Hash]
11
+ attr_accessor :area_options
12
+
13
+ # @!attribute [rw] file_options
14
+ # @return [Hash]
15
+ attr_accessor :file_options
16
+
17
+ # @!attribute [rw] field_options
18
+ # @return [Hash]
19
+ attr_accessor :field_options
20
+
21
+ # @!attribute [rw] select_options
22
+ # @return [Hash]
23
+ attr_accessor :select_options
24
+
25
+ # @!attribute [rw] label_options
26
+ # @return [Hash]
27
+ attr_accessor :label_options
28
+
29
+ # Default class assigned to block (<div class="block">...</div>).
30
+ #
31
+ # @!attribute [rw] block_class
32
+ # @return [String]
33
+ attr_accessor :block_class
34
+
35
+ # Default class assigned to input (<div class="input">...</div>).
36
+ #
37
+ # @!attribute [rw] input_class
38
+ # @return [String]
39
+ attr_accessor :input_class
40
+
41
+ # Default class assigned to association (<div class="association">...</div>).
42
+ #
43
+ # @!attribute [rw] association_class
44
+ # @return [String]
45
+ attr_accessor :association_class
46
+
47
+ # Default class assigned to block with errors (<div class="block errors">...</div>).
48
+ #
49
+ # @!attribute [rw] block_error_class
50
+ # @return [String]
51
+ attr_accessor :block_error_class
52
+
53
+ # Default class assigned to input with errors (<div class="input errors">...</div>).
54
+ #
55
+ # @!attribute [rw] input_error_class
56
+ # @return [String]
57
+ attr_accessor :input_error_class
58
+
59
+ # Default class assigned to input with errors (<div class="association errors">...</div>).
60
+ #
61
+ # @!attribute [rw] association_error_class
62
+ # @return [String]
63
+ attr_accessor :association_error_class
64
+
65
+ # Default class assigned to error (<div class="error">...</div>).
66
+ #
67
+ # @!attribute [rw] error_class
68
+ # @return [String]
69
+ attr_accessor :error_class
70
+
71
+ # Default class assigned to hint (<div class="hint">...</div>).
72
+ #
73
+ # @!attribute [rw] hint_class
74
+ # @return [String]
75
+ attr_accessor :hint_class
76
+
77
+ # Default tag assigned to block (<div class="input">...</div>).
78
+ #
79
+ # @!attribute [rw] block_tag
80
+ # @return [Symbol]
81
+ attr_accessor :block_tag
82
+
83
+ # Default tag assigned to input (<div class="input">...</div>).
84
+ #
85
+ # @!attribute [rw] input_tag
86
+ # @return [Symbol]
87
+ attr_accessor :input_tag
88
+
89
+ # Default tag assigned to association (<div class="association">...</div>).
90
+ #
91
+ # @!attribute [rw] association_tag
92
+ # @return [Symbol]
93
+ attr_accessor :association_tag
94
+
95
+ # Default tag assigned to error (<div class="error">...</div>).
96
+ #
97
+ # @!attribute [rw] error_tag
98
+ # @return [Symbol]
99
+ attr_accessor :error_tag
100
+
101
+ # Default tag assigned to hint (<div class="hint">...</div>).
102
+ #
103
+ # @!attribute [rw] hint_tag
104
+ # @return [Symbol]
105
+ attr_accessor :hint_tag
106
+
107
+ # Default as is :string.
108
+ #
109
+ # @!attribute [rw] default_as
110
+ # @return [Symbol]
111
+ attr_accessor :default_as
112
+
113
+ def initialize
114
+ @box_options = {}
115
+ @area_options = {}
116
+ @file_options = {}
117
+ @field_options = {}
118
+ @select_options = {}
119
+ @label_options = {}
120
+ @block_class = 'block'
121
+ @input_class = 'input'
122
+ @association_class = 'association'
123
+ @block_error_class = 'errors'
124
+ @input_error_class = false
125
+ @association_error_class = false
126
+ @error_class = 'error'
127
+ @hint_class = 'hint'
128
+ @block_tag = :div
129
+ @input_tag = :div
130
+ @association_tag = :div
131
+ @error_tag = :div
132
+ @hint_tag = :div
133
+ @default_as = :string
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,351 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Formula
4
+ class FormBuilder < ::ActionView::Helpers::FormBuilder
5
+ # Generate a form button.
6
+ #
7
+ # Options:
8
+ #
9
+ # * :container - add custom options to the container
10
+ # * :button - add custom options to the button
11
+ #
12
+ # Usage:
13
+ #
14
+ # f.button(:name)
15
+ #
16
+ # Equivalent:
17
+ #
18
+ # <div class="block">
19
+ # <%= f.submit("Save")
20
+ # </div>
21
+ def button(value = nil, options = {})
22
+ options[:button] ||= {}
23
+
24
+ options[:container] ||= {}
25
+ options[:container][:class] = arrayorize(options[:container][:class]) << config.block_class
26
+
27
+ @template.content_tag(config.block_tag, options[:container]) do
28
+ submit value, options[:button]
29
+ end
30
+ end
31
+
32
+ # Basic container generator for use with blocks.
33
+ #
34
+ # Options:
35
+ #
36
+ # * :hint - specify a hint to be displayed ('We promise not to spam you.', etc.)
37
+ # * :label - override the default label used ('Name:', 'URL:', etc.)
38
+ # * :error - override the default error used ('invalid', 'incorrect', etc.)
39
+ #
40
+ # Usage:
41
+ #
42
+ # f.block(:name, :label => "Name:", :hint => "Please use your full name.", :container => { :class => 'fill' }) do
43
+ # ...
44
+ # end
45
+ #
46
+ # Equivalent:
47
+ #
48
+ # <div class='block fill'>
49
+ # <%= f.label(:name, "Name:") %>
50
+ # ...
51
+ # <div class="hint">Please use your full name.</div>
52
+ # <div class="error">...</div>
53
+ # </div>
54
+ def block(method = nil, options = {}, &block)
55
+ options[:error] ||= error(method) if method
56
+
57
+ components = ''.html_safe
58
+
59
+ components << label(method, options[:label], config.label_options) if method
60
+
61
+ components << @template.capture(&block)
62
+
63
+ options[:container] ||= {}
64
+ options[:container][:class] = arrayorize(options[:container][:class]) << config.block_class << method
65
+ options[:container][:class] << config.block_error_class if config.block_error_class.present? and error?(method)
66
+
67
+ if options[:hint]
68
+ components << @template.content_tag(config.hint_tag, options[:hint],
69
+ class: config.hint_class)
70
+ end
71
+ if options[:error]
72
+ components << @template.content_tag(config.error_tag, options[:error],
73
+ class: config.error_class)
74
+ end
75
+
76
+ @template.content_tag(config.block_tag, options[:container]) do
77
+ components
78
+ end
79
+ end
80
+
81
+ # Generate a suitable form input for a given method by performing introspection on the type.
82
+ #
83
+ # Options:
84
+ #
85
+ # * :as - override the default type used (:url, :email, :phone, :password, :number, :text)
86
+ # * :label - override the default label used ('Name:', 'URL:', etc.)
87
+ # * :error - override the default error used ('invalid', 'incorrect', etc.)
88
+ # * :input - add custom options to the input ({ :class => 'goregous' }, etc.)
89
+ # * :container - add custom options to the container ({ :class => 'gorgeous' }, etc.)
90
+ #
91
+ # Usage:
92
+ #
93
+ # f.input(:name)
94
+ # f.input(:email)
95
+ # f.input(:password_a, :label => "Password", :hint => "It's a secret!", :container => { :class => "half" })
96
+ # f.input(:password_b, :label => "Password", :hint => "It's a secret!", :container => { :class => "half" })
97
+ #
98
+ # Equivalent:
99
+ #
100
+ # <div class="block name">
101
+ # <%= f.label(:name)
102
+ # <div class="input string"><%= f.text_field(:name)</div>
103
+ # <div class="error">...</div>
104
+ # </div>
105
+ # <div class="block email">
106
+ # <%= f.label(:email)
107
+ # <div class="input string"><%= f.email_field(:email)</div>
108
+ # <div class="error">...</div>
109
+ # </div>
110
+ # <div class="block half password_a">
111
+ # <div class="input">
112
+ # <%= f.label(:password_a, "Password")
113
+ # <%= f.password_field(:password_a)
114
+ # <div class="hint">It's a secret!</div>
115
+ # <div class="error">...</div>
116
+ # </div>
117
+ # </div>
118
+ # <div class="block half password_b">
119
+ # <div class="input">
120
+ # <%= f.label(:password_b, "Password")
121
+ # <%= f.password_field(:password_b)
122
+ # <div class="hint">It's a secret!</div>
123
+ # <div class="error">...</div>
124
+ # </div>
125
+ # </div>
126
+ def input(method, options = {})
127
+ options[:as] ||= as(method)
128
+ options[:input] ||= {}
129
+
130
+ return hidden_field method, options[:input] if options[:as] == :hidden
131
+
132
+ klass = [config.input_class, options[:as]]
133
+ klass << config.input_error_class if config.input_error_class.present? and error?(method)
134
+
135
+ block(method, options) do
136
+ @template.content_tag(config.input_tag, class: klass) do
137
+ case options[:as]
138
+ when :text then text_area method, config.area_options.merge(options[:input] || {})
139
+ when :file then file_field method, config.file_options.merge(options[:input] || {})
140
+ when :string then text_field method, config.field_options.merge(options[:input] || {})
141
+ when :password then password_field method, config.field_options.merge(options[:input] || {})
142
+ when :url then url_field method, config.field_options.merge(options[:input] || {})
143
+ when :email then email_field method, config.field_options.merge(options[:input] || {})
144
+ when :phone then phone_field method, config.field_options.merge(options[:input] || {})
145
+ when :number then number_field method, config.field_options.merge(options[:input] || {})
146
+ when :boolean then check_box method, config.box_options.merge(options[:input] || {})
147
+ when :country then country_select method, config.select_options.merge(options[:input] || {})
148
+ when :date then date_select method, config.select_options.merge(options[:input] || {}),
149
+ options[:input].delete(:html) || {}
150
+ when :time then time_select method, config.select_options.merge(options[:input] || {}),
151
+ options[:input].delete(:html) || {}
152
+ when :datetime then datetime_select method, config.select_options.merge(options[:input] || {}),
153
+ options[:input].delete(:html) || {}
154
+ when :select then select method, options[:choices],
155
+ config.select_options.merge(options[:input] || {}), options[:input].delete(:html) || {}
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ # Generate a suitable form association for a given method by performing introspection on the type.
162
+ #
163
+ # Options:
164
+ #
165
+ # * :label - override the default label used ('Name:', 'URL:', etc.)
166
+ # * :error - override the default error used ('invalid', 'incorrect', etc.)
167
+ # * :association - add custom options to the input ({ :class => 'goregous' }, etc.)
168
+ # * :container - add custom options to the container ({ :class => 'gorgeous' }, etc.)
169
+ #
170
+ # Usage:
171
+ #
172
+ # f.association(:category, Category.all, :id, :name, :hint => "What do you do?")
173
+ # f.association(:category, Category.all, :id, :name, :association => { :prompt => "Category?" })
174
+ # f.association(:category, Category.all, :id, :name, :association => { :html => { :class => "category" } })
175
+ #
176
+ # Equivalent:
177
+ #
178
+ # <div>
179
+ # <div class="association category">
180
+ # <%= f.label(:category)
181
+ # <div class="association">
182
+ # <%= f.collection_select(:category, Category.all, :id, :name) %>
183
+ # </div>
184
+ # <div class="hint">What do you do?</div>
185
+ # <div class="error">...</div>
186
+ # </div>
187
+ # </div>
188
+ # <div>
189
+ # <div class="association category">
190
+ # <%= f.label(:category)
191
+ # <div class="association">
192
+ # <%= f.collection_select(:category, Category.all, :id, :name, { :prompt => "Category") } %>
193
+ # </div>
194
+ # <div class="error">...</div>
195
+ # </div>
196
+ # </div>
197
+ # <div>
198
+ # <div class="association category">
199
+ # <%= f.label(:category)
200
+ # <div class="association">
201
+ # <%= f.collection_select(:category, Category.all, :id, :name, {}, { :class => "category" } %>
202
+ # </div>
203
+ # <div class="error">...</div>
204
+ # </div>
205
+ # </div>
206
+ def association(method, collection, value, text, options = {})
207
+ options[:as] ||= :select
208
+ options[:association] ||= {}
209
+
210
+ klass = [config.association_class, options[:as]]
211
+ klass << config.association_error_class if config.association_error_class.present? and error?(method)
212
+
213
+ block(method, options) do
214
+ @template.content_tag(config.association_tag, class: klass) do
215
+ case options[:as]
216
+ when :select then collection_select :"#{method}_id", collection, value, text,
217
+ options[:association], options[:association].delete(:html) || {}
218
+ end
219
+ end
220
+ end
221
+ end
222
+
223
+ private
224
+
225
+ def config
226
+ ::Formula.config
227
+ end
228
+
229
+ # Introspection on the column to determine how to render a method. The method is used to
230
+ # identify a method type (if the method corresponds to a column)
231
+ #
232
+ # Returns:
233
+ #
234
+ # * :text - for columns of type 'text'
235
+ # * :string - for columns of type 'string'
236
+ # * :integer - for columns of type 'integer'
237
+ # * :float - for columns of type 'float'
238
+ # * :decimal - for columns of type 'decimal'
239
+ # * :datetime - for columns of type 'datetime'
240
+ # * :date - for columns of type 'date'
241
+ # * :time - for columns of type 'time'
242
+ # * nil - for unkown columns
243
+ def type(method)
244
+ return unless @object.respond_to?(:has_attribute?) && @object.has_attribute?(method)
245
+
246
+ column = @object.column_for_attribute(method) if @object.respond_to?(:column_for_attribute)
247
+ column.type if column
248
+ end
249
+
250
+ # Introspection on an association to determine if a method is a file. This
251
+ # is determined by the methods ability to respond to file methods.
252
+ def file?(method)
253
+ @files ||= {}
254
+ @files[method] ||= begin
255
+ file = @object.send(method) if @object && @object.respond_to?(method)
256
+ file.is_a?(::ActiveStorage::Attached)
257
+ end
258
+ end
259
+
260
+ # Introspection on the field and method to determine how to render a method. The method is
261
+ # used to generate form element types.
262
+ #
263
+ # Returns:
264
+ #
265
+ # * :url - for columns containing 'url'
266
+ # * :email - for columns containing 'email'
267
+ # * :phone - for columns containing 'phone'
268
+ # * :password - for columns containing 'password'
269
+ # * :number - for integer, float or decimal columns
270
+ # * :datetime - for datetime or timestamp columns
271
+ # * :date - for date column
272
+ # * :time - for time column
273
+ # * :text - for time column
274
+ # * :string - for all other cases
275
+ def as(method)
276
+ case "#{method}"
277
+ when /url/ then return :url
278
+ when /email/ then return :email
279
+ when /phone/ then return :phone
280
+ when /password/ then return :password
281
+ end
282
+
283
+ case type(method)
284
+ when :string then return :string
285
+ when :integer then return :number
286
+ when :float then return :number
287
+ when :decimal then return :number
288
+ when :timestamp then return :datetime
289
+ when :datetime then return :datetime
290
+ when :date then return :date
291
+ when :time then return :time
292
+ when :text then return :text
293
+ end
294
+
295
+ return :file if file?(method)
296
+
297
+ config.default_as
298
+ end
299
+
300
+ # Generate error messages by combining all errors on an object into a comma seperated string
301
+ # representation.
302
+ def error(method)
303
+ errors = @object.errors[method] if @object
304
+ errors.to_sentence if errors.present?
305
+ end
306
+
307
+ # Identify if error message exists for a given method by checking for the presence of the object
308
+ # followed by the presence of errors.
309
+ def error?(method)
310
+ @object.present? and @object.errors[method].present?
311
+ end
312
+
313
+ # Create an array from a string, a symbol, or an undefined value. The default is to return
314
+ # the value and assume it has already is valid.
315
+ def arrayorize(value)
316
+ case value
317
+ when nil then []
318
+ when String then value.to_s.split
319
+ when Symbol then value.to_s.split
320
+ else value
321
+ end
322
+ end
323
+
324
+ public
325
+
326
+ # Generates a wrapper around fields_form with :builder set to FormBuilder.
327
+ #
328
+ # Supports:
329
+ #
330
+ # * f.formula_fields_for(@user.company)
331
+ # * f.fieldsula_for(@user.company)
332
+ #
333
+ # Equivalent:
334
+ #
335
+ # * f.fields_for(@user.company, builder: Formula::FormBuilder))
336
+ #
337
+ # Usage:
338
+ #
339
+ # <% f.formula_fields_for(@user.company) do |company_f| %>
340
+ # <%= company_f.input :url %>
341
+ # <%= company_f.input :phone %>
342
+ # <% end %>
343
+ def formula_fields_for(record_or_name_or_array, *args, &block)
344
+ options = args.extract_options!
345
+ options[:builder] ||= self.class
346
+ fields_for(record_or_name_or_array, *(args << options), &block)
347
+ end
348
+
349
+ alias fieldsula_for formula_fields_for
350
+ end
351
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Formula
4
+ module FormHelper
5
+ # Generates a wrapper around form_for with :builder set to Formula::FormBuilder.
6
+ #
7
+ # Supports:
8
+ #
9
+ # * formula_form_for(@user)
10
+ #
11
+ # Equivalent:
12
+ #
13
+ # * form_for(@user, builder: Formula::FormBuilder))
14
+ #
15
+ # Usage:
16
+ #
17
+ # <% formula_form_for(@user) do |f| %>
18
+ # <%= f.input :email %>
19
+ # <%= f.input :password %>
20
+ # <% end %>
21
+ def formula_form_for(record_or_name_or_array, *args, &proc)
22
+ options = args.extract_options!
23
+ options[:builder] ||= ::Formula::FormBuilder
24
+ form_for(record_or_name_or_array, *(args << options), &proc)
25
+ end
26
+
27
+ # Generates a wrapper around fields_for with :builder set to Formula::FormBuilder.
28
+ #
29
+ # Supports:
30
+ #
31
+ # * f.formula_fields_for(@user.company)
32
+ #
33
+ # Equivalent:
34
+ #
35
+ # * f.fields_for(@user.company, builder: Formula::FormulaFormBuilder))
36
+ #
37
+ # Usage:
38
+ #
39
+ # <% f.formula_fields_for(@user.company) do |company_f| %>
40
+ # <%= company_f.input :url %>
41
+ # <%= company_f.input :phone %>
42
+ # <% end %>
43
+ def formula_fields_for(record_or_name_or_array, *args, &block)
44
+ options = args.extract_options!
45
+ options[:builder] ||= ::Formula::FormBuilder
46
+ fields_for(record_or_name_or_array, *(args << options), &block)
47
+ end
48
+ end
49
+ end
@@ -1,10 +1,11 @@
1
- require 'formula'
1
+ # frozen_string_literal: true
2
+
2
3
  require 'rails'
3
4
 
4
5
  module Formula
5
6
  class Railtie < Rails::Railtie
6
7
  initializer 'formula.initialize' do
7
- ActionView::Base.send :include, Formula::FormulaFormHelper
8
+ ActionView::Base.include Formula::FormHelper
8
9
  end
9
10
  end
10
11
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Formula
2
- VERSION = "1.1.1"
4
+ VERSION = '2.0.0'
3
5
  end