edit_in_place 0.1.0 → 0.2.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
2
  SHA256:
3
- metadata.gz: 1a49b654229bb462de8d09e761fb800ef58647a8964b793e90c308e29b65589b
4
- data.tar.gz: dbc63f81542231c4defe07042f10664cf0376a61f47a41abf2983175134671ba
3
+ metadata.gz: 98f6c29f5c933c2f0051d9199089dc41125fe9cf6bdf8d3f61e7a6718b828a40
4
+ data.tar.gz: 95f123e6fcacbd5b8a42489d9dea077d0b381f482d1cdb152245f61dd56071da
5
5
  SHA512:
6
- metadata.gz: 615184175d7f147d9764c2a35ce3246e3114db24e33699ad02bfd422e8e6d9021653f2600ee0793245966e76538a8ccd286fd4e0c2aca361ddf29da279e5e76d
7
- data.tar.gz: fef7dc43b4333a89fe8d23b3f62d92aabbca2372fffca8535899c6b089c21be8f64201621eea27c71c26f7e9aed54a7a97d4027963f69dc6519877ca6cc60218
6
+ metadata.gz: 50f8954118b90962787e4131feae133a5babe443a4bdb36231c0a6c3fcbadfdc0f65d71831d8c449a0d9f07afc7f026598a8119088bc9bf1100e3a2a7da7658c
7
+ data.tar.gz: 5a66d2fbdbbc040ef95acaaa29f61aa886d8172baf9b298e44ae5f61ab2ffed669eb0e9113bd361babbe2bf85dcec0b00729a7deb536b80a3a878bb3a30e8fef
data/README.md CHANGED
@@ -1,11 +1,12 @@
1
1
  # EditInPlace
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/edit_in_place.svg)](https://badge.fury.io/rb/edit_in_place)
3
4
  [![Build Status](https://travis-ci.com/jacoblockard99/edit_in_place.svg?branch=master)](https://travis-ci.com/jacoblockard99/edit_in_place)
4
5
  [![Inline docs](http://inch-ci.org/github/jacoblockard99/edit_in_place.svg?branch=master)](http://inch-ci.org/github/jacoblockard99/edit_in_place)
5
6
  [![Maintainability](https://api.codeclimate.com/v1/badges/389fc591cd9cccb2ceb1/maintainability)](https://codeclimate.com/github/jacoblockard99/edit_in_place/maintainability)
6
7
  [![Test Coverage](https://api.codeclimate.com/v1/badges/389fc591cd9cccb2ceb1/test_coverage)](https://codeclimate.com/github/jacoblockard99/edit_in_place/test_coverage)
7
8
 
8
- `edit_in_place` is a Rails plugin that facilitates the creation of user interfaces that allow the user to edit content "in place" in a natural way. `edit_in_place` aims to be:
9
+ `edit_in_place` is a Ruby gem that facilitates the creation of user interfaces that allow the user to edit content "in place" in a natural way. `edit_in_place` aims to be:
9
10
  - **Flexible.** Everything has been designed with extensibility in mind. The `edit_in_place` core (this repository) can be extended for a huge variety of use cases.
10
11
  - **Reliable.** Every aspect of the plugin is thoroughly tested and documented.
11
12
  - **Natural.** Coding with `edit_in_place` is just as natural as editing content with it is! We think you'll really enjoy working with the `edit_in_place` API.
@@ -34,7 +35,7 @@ Or you may install it manually with:
34
35
  $ gem install edit_in_place
35
36
  ```
36
37
 
37
- `edit_in_place` currently has two dependencies: `rails` and `middlegem`.
38
+ `edit_in_place` currently has two dependencies: `activesupport` and `middlegem`. The only extension required from `activesupport` is `Hash#deep_merge`.
38
39
 
39
40
  ## Concepts
40
41
 
@@ -65,12 +66,12 @@ Here are a few examples:
65
66
  class TextFieldType < EditInPlace::FieldType
66
67
  protected
67
68
 
68
- def render_viewing(options, name, value)
69
- options.view.tag.p value
69
+ def render_viewing(mode, name, value)
70
+ "<p>#{value}</p>"
70
71
  end
71
72
 
72
- def render_editing(options, name, value)
73
- options.view.text_field_tag name, value
73
+ def render_editing(mode, name, value)
74
+ "<input type='text' value='#{value}' name='#{name]' />"
74
75
  end
75
76
  end
76
77
  ```
@@ -79,13 +80,13 @@ end
79
80
  # boolean_field_type.rb
80
81
 
81
82
  class DummyFieldtype < EditInPlace::FieldType
82
- def render(options, *)
83
- "You are currently #{options.mode} the webpage!"
83
+ def render(mode, *)
84
+ "You are currently #{mode} the webpage!"
84
85
  end
85
86
  end
86
87
  ```
87
88
 
88
- Notice that the `render` method is passed an options parameter, which is an instance of `EditInPlace::FieldOptions`, that contains the view context and the mode. Also note how `render_viewing` and `render_editing` will be called according to the current mode. If you want to define a `render_*` method for a different mode, you'll need to override the `supported_modes` method, like so:
89
+ Notice that the `render` method is passed a mode parameter. Also note how `render_viewing` and `render_editing` will be called according to the current mode. If you want to define a `render_*` method for a different mode, you'll need to override the `supported_modes` method, like so:
89
90
 
90
91
  ```ruby
91
92
  class LockedField
@@ -109,7 +110,7 @@ class LockedField
109
110
  end
110
111
  ```
111
112
 
112
- Attempts to call `render` with a mode that is not is `supported_modes` will result in an `EditInPlace::UnsupportedModeError`, even if the field type has a corresponding `render_*` method.
113
+ Attempts to call `render` with a mode that is not in `supported_modes` will result in an `EditInPlace::UnsupportedModeError`, even if the field type has a corresponding `render_*` method.
113
114
 
114
115
  As mentioned earlier, one of the aims of `edit_in_place` is to be natural for the developer. Thus, in the interests of convenience, `edit_in_place` allows you to "register" field types with a name, making them easier to use. We might register our "text" field type, for example, like this:
115
116
 
@@ -133,6 +134,25 @@ Becomes:
133
134
 
134
135
  Note that field type names must be symbols—strings are not allowed. Also note that duplicate registrations are not alowed and will raise an `EditInPlace::DuplicateRegistrationError`.
135
136
 
137
+ Another convenient feature is that you may use or register field type _classes_ whose
138
+ constructor has no parameters. For example:
139
+
140
+ ```ruby
141
+ @builder.config.field_types.register :image, ImageFieldType
142
+ ```
143
+
144
+ ```ruby
145
+ <%= @builder.field TextFieldType, 'contact_name', 'Jacob' %>
146
+ <%= @builder.field :image, 'contact_name', 'Jacob' %>
147
+ ```
148
+
149
+ Equivalent to:
150
+
151
+ ```ruby
152
+ <%= @builder.field TextFieldType.new, 'contact_name', 'Jacob' %>
153
+ <%= @builder.field ImageFieldType.new, 'contact_name', 'Jacob' %>
154
+ ```
155
+
136
156
  ### Configuring a Builder
137
157
 
138
158
  The next step is creating and using an `EditInPlace::Builder` instance. A builder always has an `EditInPlace::Configuration` instance that contains all its options and context. When a builder is first instantiated, its configuration is copied from the global `EditInPlace` configuration. Thus, you can set any global configuration options using `EditInPlace.config` or `EditInPlace.configure`, and all builders with use those options by default. For example:
@@ -152,27 +172,6 @@ This would make editing the *default* mode. Then, you can modify builder-specifi
152
172
 
153
173
  Both `EditInPlace.config` and `Builder#config` are `EditInPlace::Configuration` instances, so you configure them identically. You are encouraged to check out the [docs](https://rubydoc.info/github/jacoblockard99/edit_in_place/EditInPlace/Configuration) on `Configuration` to see all the available configuration options.
154
174
 
155
- Only two options are really critical to using the builder: the view context and the mode. The view context is necessary when the field type needs access to a view context to render the field. In our `TextFieldType` example above, for example, the `text_field_tag` method was required. Probably the easiest way to pass the view context is to simply use the `view_context` method in Rails controllers. For example:
156
-
157
- ```
158
- class SomeController
159
- def index
160
- @builder = Builder.new
161
- @builder.field_options.view = view_context
162
- end
163
- end
164
- ```
165
-
166
- Now, field types will automatically have access to the view context. This method has some pitfalls, however, most importantly that `view_context` returns a _new_ view context, not the one used in the actual view. If you must have the actual view context object, something like this could be done instead:
167
-
168
- ```erb
169
- <% @builder.field_options.view = self %>
170
-
171
- <%= @builder.field :text, "hello, world" %>
172
- ```
173
-
174
- Of course, you would need to put this at the top of all your views.
175
-
176
175
  There are a few approaches to managing builder modes. One approach is to have a seperate controller for each, like so:
177
176
 
178
177
  ```ruby
@@ -220,6 +219,12 @@ If your field type happens to expect the first input argument to be a hash, you
220
219
  <%= @builder.field :some_type, {}, { option: true }, 'etc' %>
221
220
  ```
222
221
 
222
+ `Builder` also overrides `method_missing` to make it easier to call registered fields. If, for example, you have registered a `:text` field type, you can do the following:
223
+
224
+ ```erb
225
+ <%= @builder.text_field 'phone_number', '(123) 456-7890' %>
226
+ ```
227
+
223
228
  ### Middlewares
224
229
 
225
230
  Perhaps the most powerful feature of `edit_in_place` are the field middlewares. `edit_in_place` uses [`middlegem`](https://github/jacoblockard99/middlegem) for middlewares, which you may want to briefly review. Field middlewares allow the inputs to a field to be transformed before actually making it to the field type's `render` method. The use cases for this are limitless.
@@ -254,6 +259,16 @@ end
254
259
 
255
260
  Now, when viewing the site, the first one would show "(5000)" and the second would show "(a string)". Note that middlewares are often too verbose to be easily used like this. They are really best used by edit_in_place extensions.
256
261
 
262
+ Like field types, middlewares can also be registered, using `Configuration#registered_middlewares`. For example:
263
+
264
+ ```ruby
265
+ @builder = Builder.new
266
+ @builder.configure do |c|
267
+ c.registered_middlewares.register :parentheses, ParenthesesMiddleware
268
+ c.field_options.middlewares << :parentheses
269
+ ```
270
+
271
+
257
272
  ### Scoped Builders
258
273
 
259
274
  There will likely be times when you wish for many fields to have the same `FieldOptions`. This can be accomplished with the `Builder#scoped` method, which allows field options to be shared across a block. For example:
@@ -264,7 +279,15 @@ There will likely be times when you wish for many fields to have the same `Field
264
279
  <% end %>
265
280
  ```
266
281
 
267
- Now any fields generated with the scoped `b` builder will have an `'example'` argument appended to their input (assuming that `AppendArgumentMiddleware` has been defined).
282
+ Now any fields generated with the scoped `b` builder will have an `'example'` argument appended to their input (assuming that `AppendArgumentMiddleware` has been defined). In fact, scoping a builder with middleware is comon enough that `Builder` also provides a `with_middlewares` convenience method:
283
+
284
+ ```erb
285
+ <%= @builder.with_middlewares AppendArgumentMiddleware.new('example') |b| do %>
286
+ <%= b.field :text, 'name', 'value' %>
287
+ <% end %>
288
+ ```
289
+
290
+ Note that `Builder#scope` and `Builder#middleware_scope` are aliases for `Builder#scoped` and `Builder#with_middlewares`, respectively.
268
291
 
269
292
  ### Extending Builder
270
293
 
data/Rakefile CHANGED
@@ -1,15 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'bundler/setup'
4
-
5
3
  require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
6
7
 
7
- require 'rake/testtask'
8
+ require 'rubocop/rake_task'
8
9
 
9
- Rake::TestTask.new(:test) do |t|
10
- t.libs << 'test'
11
- t.pattern = 'test/**/*_test.rb'
12
- t.verbose = false
13
- end
10
+ RuboCop::RakeTask.new
14
11
 
15
- task default: :test
12
+ task default: %i[spec rubocop]
data/lib/edit_in_place.rb CHANGED
@@ -1,14 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'edit_in_place/version'
4
- require 'edit_in_place/railtie'
3
+ require 'edit_in_place/array_definition'
5
4
  require 'edit_in_place/builder'
6
5
  require 'edit_in_place/configuration'
7
- require 'edit_in_place/registrar'
8
6
  require 'edit_in_place/extended_builder'
9
7
  require 'edit_in_place/field_options'
10
8
  require 'edit_in_place/field_type'
11
9
  require 'edit_in_place/field_type_registrar'
10
+ require 'edit_in_place/middleware_registrar'
11
+ require 'edit_in_place/middleware_wrapper'
12
+ require 'edit_in_place/registrar'
13
+ require 'edit_in_place/version'
14
+
15
+ require 'edit_in_place/error'
16
+ require 'edit_in_place/duplicate_registration_error'
17
+ require 'edit_in_place/invalid_field_type_error'
18
+ require 'edit_in_place/invalid_registration_name_error'
19
+ require 'edit_in_place/unregistered_field_type_error'
20
+ require 'edit_in_place/unregistered_middleware_error'
21
+ require 'edit_in_place/unsupported_mode_error'
12
22
 
13
23
  # {EditInPlace} is a namespace that contains all the modules and classes of the edit_in_place
14
24
  # Rails gemified plugin.
@@ -16,22 +26,9 @@ require 'edit_in_place/field_type_registrar'
16
26
  # @author Jacob Lockard
17
27
  # @since 0.1.0
18
28
  module EditInPlace
19
- # {Error} is a subclass of {https://ruby-doc.org/core-2.5.0/StandardError.html StandardError}
20
- # from which all custom errors in edit_in_place are derived. One potential use for this class
21
- # is to rescue all custom errors produced by edit_in_place. For example:
22
- #
23
- # begin
24
- # # Do something risky with edit_in_place here...
25
- # rescue EditInPlace::Error
26
- # # Catch any edit_in_place-specific error here...
27
- # end
28
- #
29
- # @see https://ruby-doc.org/core-2.0.0/Exception.html
30
- class Error < StandardError; end
31
-
32
29
  @config = Configuration.new
33
30
 
34
- # Gets the `Configuration` instance that represents the global configuration for the
31
+ # Gets the {Configuration} instance that contains the global configuration for the
35
32
  # edit_in_place plugin. The global configuration will be applied to all created {Builder}
36
33
  # instances.
37
34
  # @return [Configuration] the global configuration.
@@ -40,7 +37,7 @@ module EditInPlace
40
37
  @config
41
38
  end
42
39
 
43
- # Sets the `Configuration` instance that represents the global configuration for the
40
+ # Sets the {Configuration} instance that represents the global configuration for the
44
41
  # edit_in_place plugin. A convenient use for this method is to reset the global configuration
45
42
  # by setting it to +EditInPlace::Configuration.new+.
46
43
  # @param config [Configuration] the global configuration.
@@ -65,8 +62,3 @@ module EditInPlace
65
62
  yield config if block_given?
66
63
  end
67
64
  end
68
-
69
- require 'edit_in_place/invalid_field_type_error'
70
- require 'edit_in_place/unregistered_field_type_error'
71
- require 'edit_in_place/invalid_registration_name_error'
72
- require 'edit_in_place/duplicate_registration_error'
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'middlegem'
4
+
5
+ module EditInPlace
6
+ # {ArrayDefinition} is a subclass of +Middlegem::ArrayDefinition+ that works properly with
7
+ # {MiddlewareWrapper} instances. The problem is that +Middlegem::ArrayDefinition+, by default,
8
+ # tries to use the class of the defined middlewares themselves. By overriding {matches_class?},
9
+ # {ArrayDefinition} is able to cause +middlegem+ to use the class of the _base_ middleware of
10
+ # any {MiddlewareWrapper} instances.
11
+ #
12
+ # @author Jacob Lockard
13
+ # @since 0.2.0
14
+ class ArrayDefinition < Middlegem::ArrayDefinition
15
+ protected
16
+
17
+ # Overrides +matches_class?+ to use the base middleware's class if the middleware is a
18
+ # {MiddlewareWrapper}.
19
+ # @param middleware [Object] the middleware to check.
20
+ # @param klass [Class] the class against which the middleware should be checked.
21
+ # @return [Boolean] whether the given middleware has the given class.
22
+ def matches_class?(middleware, klass)
23
+ middleware.is_a?(MiddlewareWrapper) ? middleware.base.instance_of?(klass) : super
24
+ end
25
+ end
26
+ end
@@ -2,12 +2,13 @@
2
2
 
3
3
  module EditInPlace
4
4
  # {Builder} is the class that provides the actual functionality to build and render editable
5
- # content. This class will usually be instantiated in a controller and passed somehow to a
6
- # view. The view can then use its methods to generate content. Note that when a {Builder} is
7
- # created, it's {Configuration} is copied from the global configuration.
5
+ # content. If used in a Rails setting, this class will usually be instantiated in a controller
6
+ # and passed somehow to a view. The view can then use its methods to generate content. Note
7
+ # that when a {Builder} is created, its {Configuration} is copied from the global
8
+ # configuration.
8
9
  #
9
10
  # This class can be extended by utilizing {ExtendedBuilder} to safely add additional
10
- # functionality. This can be particularly helpful for edit_in_place extensions that would like
11
+ # functionality. This can be particularly helpful for edit_in_place extensions that wish
11
12
  # to add other content generation methods without requiring the user to yield another builder
12
13
  # to the view.
13
14
  #
@@ -25,15 +26,40 @@ module EditInPlace
25
26
  @config = EditInPlace.config.dup
26
27
  end
27
28
 
28
- # Creates a deep copy of this {Builder}, whose configuration can be safely modified.
29
+ # Overrides +method_missing+ to allow methods like +*_field+ to be called for registered
30
+ # fields. For example, if a +:text+ field type has been registered, then calling
31
+ # +Builder#text_field(...)+ is equivalent to calling +Builder#field(:text, ...)+.
32
+ # @param method_name [Symbol, String] the name of the missing method being called.
33
+ # @param args [Array] the arguments passed to the missing method.
34
+ # @yield the block, if any, passed to the missing method.
35
+ # @return the result of calling {#field} with the appropriate type if possible; the result of
36
+ # calling +super+ if not.
37
+ # @since 0.2.0
38
+ def method_missing(method_name, *args, &block)
39
+ field_type = parse_field_method(method_name)
40
+ field_type ? field(field_type, *args, &block) : super
41
+ end
42
+
43
+ # Overrides +respond_to_missing?+ to allow methods like +*_field+ to be responded to by
44
+ # {Builder}.
45
+ # @param method_name [Symbol, String] the name of the missing method being checked.
46
+ # @return [Boolean] +true+ if this {Builder} can respond to the given method name; +false+
47
+ # otherwise.
48
+ # @see #method_missing
49
+ # @since 0.2.0
50
+ def respond_to_missing?(method_name, inlude_private = false)
51
+ parse_field_method(method_name) || super
52
+ end
53
+
54
+ # Creates a deep copy of this {Builder} whose configuration can be safely modified.
29
55
  # @return [Builder] a deep copy of this {Builder}.
30
56
  def dup
31
- b = Builder.new
57
+ b = self.class.new
32
58
  b.config = config.dup
33
59
  b
34
60
  end
35
61
 
36
- # Configures this {Builder} by yielding its configuration to the given block. For example,
62
+ # Configures this {Builder} by yielding its configuration to the given block. For example:
37
63
  #
38
64
  # @builder = EditInPlace::Builder.new
39
65
  # @builder.configure do |c|
@@ -41,71 +67,62 @@ module EditInPlace
41
67
  # c.field_options.middlewares = [:one, :two]
42
68
  # end
43
69
  #
44
- # Note that this method is simply a convenience method, and the above code is exactly
70
+ # Note that this method is simply a convenience method and that the above code is exactly
45
71
  # equivalent to the following:
46
72
  #
47
73
  # @builder = EditInPlace::Builder.new
48
74
  # @builder.config.field_options.mode = :editing
49
75
  # @builder.config.field_options.middlewares = [:one, :two]
76
+ #
50
77
  # @yieldparam config [Configuration] the {Configuration} instance associated with this
51
78
  # {Builder}.
52
79
  # @yieldreturn [void]
53
80
  # @return [void]
54
- # @see EditInPlace.configure
55
81
  def configure
56
82
  yield config if block_given?
57
83
  end
58
84
 
85
+ # Renders a single "field", that is, a single piece of editable content defined by a field
86
+ # type. Field options may or may not be provided and will be automatically injected if not.
87
+ # The input given to this method will be transformed by any middlewares added from various
88
+ # sources.
59
89
  # @overload field(type, options, *args)
60
- # Renders a single field of the given type with the given field option and arguments
61
- # to be passed to the field type renderer.
62
- # @param type [FieldType, Symbol] the type of field to render, either an actual instance of
63
- # {FieldType}, or the symbol name of a registered field type.
90
+ # Renders a single field of the given type with the given field options and input.
91
+ # @param type [FieldType, Class, Symbol] the type of field to render, either an actual
92
+ # instance of {FieldType}, a field type class that can be instantiated with no arguments,
93
+ # or the symbol name of a registered field type.
64
94
  # @param options [FieldOptions, Hash] the field options to be used when rendering the
65
- # field. These options are defined in {FieldOptions}. Either an actual instance of
95
+ # field. These options are as defined in {FieldOptions}. Either an actual instance of
66
96
  # {FieldOptions} or a hash are acceptable.
67
- # @param args [Array] the arguments to be passed to the field renderer.
68
- # @return [String] the rendered field, as HTML.
97
+ # @param args [Array] the input arguments to be passed to `FieldType#render`.
98
+ # @return the rendered field.
69
99
  # @overload field(type, *args)
70
- # Renders a single field of the given type with the given arguments to be passed to the
71
- # field type renderer. The default field options (as defined in {FieldOptions}) will be
72
- # used.
73
- # @param type [FieldType, Symbol] the type of field to render, either an actual instance of
74
- # {FieldType}, or the symbol name of a registered field type.
75
- # @param args [Array] the arguments to be passed to the field renderer.
76
- # @return [String] the rendered field, as HTML.
100
+ # Renders a single field of the given type with the default field options and the given
101
+ # input.
102
+ # @param type [FieldType, Class, Symbol] the type of field to render, either an actual
103
+ # instance of {FieldType}, a field type class that can be instantiated with no arguments,
104
+ # or the symbol name of a registered field type.
105
+ # @param args [Array] the input arguments to be passed to `FieldType#render`.
106
+ # @return the rendered field.
77
107
  def field(type, *args)
78
- inject_field_options!(args)
79
- args[0] = config.field_options.merge(args[0])
108
+ options = config.field_options.merge(get_field_options!(args))
109
+ args.unshift(options.mode)
80
110
 
81
- definition = Middlegem::ArrayDefinition.new(config.defined_middlewares)
82
- stack = Middlegem::Stack.new(definition, middlewares: args[0].middlewares)
83
- args = stack.call(*args)
111
+ args = apply_middlewares(options.middlewares, *args)
84
112
 
85
113
  type = evaluate_field_type(type)
86
114
  type.render(*args)
87
115
  end
88
116
 
89
117
  # Yields a new, scoped {Builder} with the given field options. This method is helpful when
90
- # many fields require the same options. One use, for example, is to easily give field types
91
- # access to the current view context, like so:
92
- #
93
- # <!-- some_view.html.erb -->
94
- #
95
- # <%= @builder.scoped view: self do |b|
96
- # <%= b.field(:example_type, 'random scoped field') %>
97
- # <!-- ... -->
98
- # <% end %>
99
- #
100
- # Now all fields generated using +b+ will have access to +self+ as the view context in
101
- # {FieldOptions#view}.
118
+ # many fields require the same options.
102
119
  # @yieldparam scoped_builder [Builder] the new, scoped {Builder} instance.
103
- # @yieldreturn [string] the output generated with the scoped builder.
120
+ # @yieldreturn the output.
104
121
  # @param field_options [FieldOptions, Hash] the field options that the scoped builder should
105
122
  # have. Note that these options will be merged (using {FieldOptions#merge!}) with the
106
123
  # current ones. Either an actual {FieldOptions} instance or a hash of options are
107
124
  # acceptable.
108
- # @return [string] the output of the block.
125
+ # @return the output of the block.
109
126
  def scoped(field_options = {})
110
127
  field_options = FieldOptions.new(field_options) unless field_options.is_a? FieldOptions
111
128
 
@@ -114,48 +131,104 @@ module EditInPlace
114
131
 
115
132
  yield scoped_builder
116
133
  end
134
+ # @since 0.2.0
135
+ alias scope scoped
136
+
137
+ # Yields a new, scoped {Builder} with the given middlewares merged into the current ones.
138
+ # Note that this method is for convenience only and is exactly equivalent to calling
139
+ # +scoped(middlewares: ...)+.
140
+ # @yieldparam scoped_builder [Builder] the new, scoped {Builder} instance.
141
+ # @yieldreturn the output.
142
+ # @param middlewares [Array] the array of middlewares that the scoped builder should have
143
+ # merged into it.
144
+ # @return the output of the block.
145
+ # @since 0.2.0
146
+ def with_middlewares(*middlewares, &block)
147
+ scoped(middlewares: middlewares, &block)
148
+ end
149
+ alias middleware_scope with_middlewares
117
150
 
118
151
  private
119
152
 
120
- # Ensures that the first argument in the given list of arguments is a valid, appropriate
121
- # {FieldOptions} instance for the list of arguments. In particular:
122
- # - When the first argument is already an instance of {FieldOptions}, the argument list
123
- # is not touched.
124
- # - When the first argument is a hash, then it is converted to a
125
- # {FieldOptions} instance.
126
- # - Otherwise, the default {FieldOptions} instance is prepended to the argument list.
127
- # @param args [Array] the raw arguments into which to inject the field options.
128
- # @return [void]
129
- def inject_field_options!(args)
130
- options = args.first
153
+ # Attempts to get a field type from the given '*_field' method name.
154
+ # @param method_name [Symbol, String] the name of the method to parse.
155
+ # @return [FieldType, nil] the field type if one could be found; +nil+ if not.
156
+ def parse_field_method(method_name)
157
+ method_name = method_name.to_s
158
+ return nil unless method_name.end_with? '_field'
131
159
 
132
- return if options.is_a? FieldOptions
160
+ field_type_name = method_name.delete_suffix('_field').to_sym
161
+ config.field_types.find(field_type_name)
162
+ end
133
163
 
134
- if options.is_a? Hash
135
- args[0] = FieldOptions.new(options)
164
+ # Gets an appropriate {FieldOptions} instance for the given list of field arguments and
165
+ # removes any present field options from the argument list.
166
+ # @param args [Array] the raw arguments from which to get the field options.
167
+ # @return [FieldOptions] the retrieved field options.
168
+ # @since 0.2.0
169
+ def get_field_options!(args)
170
+ case args.first
171
+ when FieldOptions
172
+ args.shift
173
+ when Hash
174
+ FieldOptions.new(args.shift)
136
175
  else
137
- args.unshift(FieldOptions.new)
176
+ FieldOptions.new
138
177
  end
139
178
  end
140
179
 
141
180
  # Gets an appropriate {FieldType} instance for the given raw field type argument. In
142
181
  # particular:
143
- # - When the input is already a FieldType instance, that instance is simply returned.
144
182
  # - When the input is a symbol, attempts to find a registered field type associated with it.
183
+ # - When the input is a class, instatiates it.
184
+ # - When the input is already a FieldType instance, that instance is simply returned.
145
185
  # - Otherwise, raises an error.
186
+ # @param type [Symbol, Class, FieldType] the raw field type argument to evaluate.
146
187
  # @return [FieldType] an appropriate {FieldType} instance for the given input.
147
188
  def evaluate_field_type(type)
148
189
  case type
190
+ when Symbol
191
+ evaluate_field_type(lookup_field_type(type))
192
+ when Class
193
+ evaluate_field_type(type.new)
149
194
  when FieldType
150
195
  type
151
- when Symbol
152
- result = config.field_types.find(type)
153
- raise UnregisteredFieldTypeError, type if result.nil?
154
-
155
- result
156
196
  else
157
197
  raise InvalidFieldTypeError, type
158
198
  end
159
199
  end
200
+
201
+ # Attempts to find a field type registered with the given name in the field type registrar.
202
+ # If one could not be found, raises an appropriate error.
203
+ # @param name [Symbol] the name to search for.
204
+ # @return the found field type.
205
+ # @since 0.2.0
206
+ def lookup_field_type(name)
207
+ result = config.field_types.find(name)
208
+ raise UnregisteredFieldTypeError, name if result.nil?
209
+
210
+ result
211
+ end
212
+
213
+ # Applies the given array of middlewares to the given input arguments and returns the result.
214
+ # @param middlewares [Array] the array of middlewares to apply.
215
+ # @param args [Array] the array of input arguments.
216
+ # @return [Array] the resulting argument list.
217
+ # @since 0.2.0
218
+ def apply_middlewares(middlewares, *args)
219
+ definition = ArrayDefinition.new(config.defined_middlewares)
220
+ stack = Middlegem::Stack.new(definition, middlewares: wrap_middlewares(middlewares))
221
+
222
+ stack.call(*args)
223
+ end
224
+
225
+ # Converts each of the given middleware instances into a {MiddlewareWrapper} and returns the
226
+ # result.
227
+ # @param middlewares [Array] the middlewares to wrap.
228
+ # @return [Array] the wrapped middlewares.
229
+ # @since 0.2.0
230
+ def wrap_middlewares(middlewares)
231
+ middlewares.map { |m| MiddlewareWrapper.new(m, config.registered_middlewares) }
232
+ end
160
233
  end
161
234
  end
@@ -1,16 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/core_ext/object/deep_dup'
4
+
3
5
  module EditInPlace
4
6
  # {Configuration} is a class that is capable of storing configuration for an edit_in_place
5
- # {Builder}. Essentially all the options provided by edit_in_place reside in this class for
7
+ # {Builder}. Essentially all the options provided by edit_in_place reside in this class, for
6
8
  # easy reuse. This class is currently used in two locations---the global configuration in
7
9
  # {EditInPlace.config} and the builder-specific configuration in {Builder#config}.
8
10
  #
9
11
  # @author Jacob Lockard
10
12
  # @since 0.1.0
11
13
  class Configuration
12
- # The default mode in which fields should be rendered if left unpspecified in the
13
- # configuration.
14
+ # The default mode in which fields should be rendered if left unspecified in
15
+ # {#field_options}.
14
16
  DEFAULT_MODE = :viewing
15
17
 
16
18
  # The {FieldTypeRegistrar} used to store the list of registered field types.
@@ -27,21 +29,28 @@ module EditInPlace
27
29
  # @return [Array] the array of defined middlewares.
28
30
  attr_accessor :defined_middlewares
29
31
 
32
+ # The {MiddlewareRegistrar} used to store the list of registered middlewares.
33
+ # @return [MiddlewareRegistrar] the {MiddlewareRegistrar} that stores the list of registered
34
+ # middlewares.
35
+ attr_accessor :registered_middlewares
36
+
30
37
  # Creates a new, default instance of {Configuration}.
31
38
  def initialize
32
39
  @field_types = FieldTypeRegistrar.new
33
40
  @field_options = FieldOptions.new(mode: DEFAULT_MODE)
34
41
  @defined_middlewares = []
42
+ @registered_middlewares = MiddlewareRegistrar.new
35
43
  end
36
44
 
37
45
  # Creates a deep copy of this {Configuration} that can be safely modified.
38
46
  # @return [Configuration] a deep copy of this configuration.
39
47
  def dup
40
- c = Configuration.new
48
+ c = self.class.new
41
49
  c.field_types = field_types.dup
42
50
  c.field_options = field_options.dup
43
51
  # Note that this is purposely NOT a deep copy---it doesn't make sense to duplicate classes.
44
52
  c.defined_middlewares = defined_middlewares.dup
53
+ c.registered_middlewares = registered_middlewares.dup
45
54
  c
46
55
  end
47
56
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EditInPlace
4
+ # {Error} is a subclass of {https://ruby-doc.org/core-2.5.0/StandardError.html StandardError}
5
+ # from which all custom errors in edit_in_place are derived. One potential use for this class
6
+ # is to rescue all custom errors produced by edit_in_place. For example:
7
+ #
8
+ # begin
9
+ # # Do something risky with edit_in_place here...
10
+ # rescue EditInPlace::Error
11
+ # # Catch any edit_in_place-specific error here...
12
+ # end
13
+ #
14
+ # @see https://ruby-doc.org/core-2.0.0/Exception.html
15
+ class Error < StandardError; end
16
+ end
@@ -29,12 +29,33 @@ module EditInPlace
29
29
  # quack like a {Builder}.
30
30
  attr_reader :base
31
31
 
32
- delegate_missing_to :base
33
-
34
32
  # Creates a new {ExtendedBuilder} with the given base builder.
35
33
  # @param base [Object] the base builder to extend. It should quack like a {Builder}.
36
34
  def initialize(base)
37
35
  @base = base
38
36
  end
37
+
38
+ # Overrides +method_missing+ to allow the use of methods defined on the base builder. This
39
+ # method was added in version 0.2.0 when Rails support (and thus support for
40
+ # +delegate_missing_to+) was removed.
41
+ # @param method_name [Symbol, String] the name of the missing method.
42
+ # @param args [Array] the arguments given to the missing method.
43
+ # @yield the block passed to the missing method.
44
+ # @return the result of calling the method on the base builder, if it was defined, or the
45
+ # result of calling +super+ if not.
46
+ # @since 0.2.0
47
+ def method_missing(method_name, *args, &block)
48
+ base.respond_to?(method_name) ? base.send(method_name, *args, &block) : super
49
+ end
50
+
51
+ # Overrides +respond_to_missing?+ to respond to methods defined on the base builder. This
52
+ # method was added in version 0.2.0 when Rails support (and thus support for
53
+ # +delegate_missing_to+) was removed.
54
+ # @param method_name [Symbol, String] the name of the missing method.
55
+ # @return [Boolean] whether this {ExtendedBuilder} can respond to the given method name.
56
+ # @since 0.2.0
57
+ def respond_to_missing?(method_name, priv = false)
58
+ base.respond_to?(method_name) || super
59
+ end
39
60
  end
40
61
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module EditInPlace
4
4
  # {FieldOptions} is a class that stores the options and context required to render a field.
5
+ # More specifically, it stores options given to *the {Builder#field} method itself*, not
6
+ # options given to the field renderer.
5
7
  #
6
8
  # @author Jacob Lockard
7
9
  # @since 0.1.0
@@ -18,11 +20,6 @@ module EditInPlace
18
20
  # @return [void]
19
21
  attr_reader :mode
20
22
 
21
- # The view context to be used when rendering the field. This view context can be derived in
22
- # a number of ways, most commonly by creating a new instance of +ActionView::Base+.
23
- # @return the view context to be used when rendering the field.
24
- attr_accessor :view
25
-
26
23
  # An array of middleware instances that should be applied to the field's input.
27
24
  # @return the array of middlewares.
28
25
  attr_accessor :middlewares
@@ -31,12 +28,11 @@ module EditInPlace
31
28
  # Creates a new instance of {FieldOptions} with the given options.
32
29
  # @param options [Hash, #[]] a hash containing the given field options.
33
30
  # @option options [Symbol] :mode the {#mode} in which fields should be rendered.
34
- # @option options :view the {#view} context to use when rendering the field.
31
+ # @option options [Array] :middlewares the {#middlewares} for the field.
35
32
  # @overload initialize
36
33
  # Creates a new instance of {FieldOptions} with the default options.
37
34
  def initialize(options = {})
38
35
  self.mode = options[:mode]
39
- self.view = options[:view]
40
36
  self.middlewares = options[:middlewares] || []
41
37
  end
42
38
 
@@ -48,24 +44,22 @@ module EditInPlace
48
44
  # Creates a deep copy of this {FieldOptions} instance that can be safely modified.
49
45
  # @return [FieldOptions] a deep copy of this {FieldOptions} instance.
50
46
  def dup
51
- f = FieldOptions.new
47
+ f = self.class.new
52
48
  f.mode = mode
53
- f.view = view
54
- f.middlewares = middlewares.deep_dup
49
+ f.middlewares = middlewares.map { |m| m.instance_of?(Class) ? m : m.dup }
55
50
  f
56
51
  end
57
52
 
58
- # Merges the given {FieldOptions} instance into this one. Modes and view contexts from the
59
- # other instance will overwrite those in this instance if present. The other instance is
60
- # duplicated before being merged, so it can be safely modified after the fact. All
61
- # middleware arrays will be merged.
53
+ # Merges the given {FieldOptions} instance into this one. A mode from the
54
+ # other instance will overwrite the one in this instance if present. Middleware arrays will
55
+ # be merged. Note that the other instance is duplicated before being merged, so it can be
56
+ # safely modified after the fact.
62
57
  # @param other [FieldOptions] the other field options to merge into this one.
63
58
  # @return [void]
64
59
  def merge!(other)
65
60
  other = other.dup
66
61
 
67
62
  self.mode = other.mode unless other.mode.nil?
68
- self.view = other.view unless other.view.nil?
69
63
  self.middlewares += other.middlewares
70
64
  end
71
65
 
@@ -3,13 +3,13 @@
3
3
  module EditInPlace
4
4
  # {FieldType} is a class that represents a single type of field. A field is a single,
5
5
  # self-contained component that displays data in various "modes", typically either "viewing" or
6
- # "editing". Field types provide the templates for similar fields.
6
+ # "editing". Field types provide the templates for rendering fields.
7
7
  #
8
8
  # @abstract
9
9
  # @author Jacob Lockard
10
10
  # @since 0.1.0
11
11
  class FieldType
12
- # Render the field, given a {FieldOptions} instance and an array of arguments passed by
12
+ # Render the field, given the mode and an array of arguments passed by
13
13
  # the caller.
14
14
  #
15
15
  # While subclasses may override this method as appropriate, the default
@@ -18,13 +18,12 @@ module EditInPlace
18
18
  # 2. calls a +render_*+ method.
19
19
  # For example, if the mode were +:admin_editing+, then a +render_admin_editing+ method would
20
20
  # be called. Naturally, the +render_*+ methods need to be defined by the subclass.
21
- # @param options [FieldOptions] options passed by the {Builder} instance that should
22
- # be used to render the field.
21
+ # @param mode [Symbol] the mode with which to render the field.
23
22
  # @param args [Array<Object>] the arguments passed by the field creator.
24
- # @return [String] the rendered HTML.
25
- def render(options, *args)
26
- validate_mode!(options.mode)
27
- send("render_#{options.mode}", options, *args)
23
+ # @return the rendered result.
24
+ def render(mode, *args)
25
+ validate_mode!(mode)
26
+ send("render_#{mode}", mode, *args)
28
27
  end
29
28
 
30
29
  # Gets the modes that are supported by this field type, +:viewing+ and +:editing+ by default.
@@ -1,22 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'edit_in_place/registrar'
4
+
3
5
  module EditInPlace
4
6
  # {FieldTypeRegistrar} is a subcalss of {Registrar} that only allows {FieldType}
5
- # instances to be registered.
7
+ # instances and field type classes to be registered.
6
8
  #
7
9
  # @author Jacob Lockard
8
10
  # @since 0.1.0
9
11
  class FieldTypeRegistrar < Registrar
10
12
  protected
11
13
 
12
- # Adds to the default `validate_registration!` implementation by ensuring that only
13
- # {FieldType} instances can be registered.
14
+ # Adds to the default +validate_registration!+ implementation by ensuring that only
15
+ # {FieldType} instances or field type classes can be registered.
14
16
  # @param name [Symbol] the name to validate.
15
- # @param field_type [FieldType] the field type to validate.
17
+ # @param field_type [FieldType, Class] the field type to validate.
16
18
  # @return [void]
17
19
  def validate_registration!(name, field_type)
18
20
  super
19
- raise InvalidFieldTypeError, field_type unless field_type.is_a? FieldType
21
+ unless field_type.is_a?(FieldType) || field_type.instance_of?(Class)
22
+ raise InvalidFieldTypeError, field_type
23
+ end
20
24
  end
21
25
  end
22
26
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EditInPlace
4
+ # {MiddlewareRegistrar} is a subclass of {Registrar} that only allows middleware objects (as
5
+ # defined by +Middlegem::Middleware.valid?+) or middleware classes to be registered.
6
+ #
7
+ # @author Jacob Lockard
8
+ # @since 0.2.0
9
+ class MiddlewareRegistrar < Registrar
10
+ protected
11
+
12
+ # Adds to the default +validate_registration!+ implementation by ensuring that only
13
+ # middleware objects (as defined by +Middlegem::Middleware.valid?+) or middleware classes
14
+ # can be registered.
15
+ def validate_registration!(name, middleware)
16
+ super
17
+ unless Middlegem::Middleware.valid?(middleware) || middleware.instance_of?(Class)
18
+ raise Middlegem::InvalidMiddlewareError
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'middlegem'
4
+
5
+ module EditInPlace
6
+ # {MiddlewareWrapper} is a class that provides a consistent wrapper for a middleware, which
7
+ # currently can be one of the following:
8
+ # 1. an actual middleware object (i.e. an object that responds to +#call+),
9
+ # 2. a symbol name corresponding to a registered middleware, or
10
+ # 3. a parameterless middleware class that should be instantiated.
11
+ # {MiddlewareWrapper}, which is itself a +Middlegem::Middleware+ does all the necessary
12
+ # conversions, providing a simple {#call} method.
13
+ #
14
+ # @author Jacob Lockard
15
+ # @since 0.2.0
16
+ class MiddlewareWrapper < Middlegem::Middleware
17
+ # The base middleware, which should be a middleware object, a middleware class, or a
18
+ # middleware name.
19
+ # @return the base middleware.
20
+ attr_reader :base
21
+
22
+ # Creates a new instance of {MiddlewareWrapper} with the given middleware and registrar.
23
+ # @param base the middleware to wrap.
24
+ # @param registrar [MiddlewareRegistrar] the middleware registrar in which to search for
25
+ # registered middlewares.
26
+ def initialize(base, registrar)
27
+ base = lookup_middleware(base, registrar) if base.is_a? Symbol
28
+ base = base.new if base.instance_of? Class
29
+
30
+ @base = base
31
+
32
+ super()
33
+ end
34
+
35
+ # Executes this {MiddlewareWrapper} with the given input by delegating appropriately to the
36
+ # base middleware.
37
+ # @param args [Array] the input arguments.
38
+ # @return [Array] the transformed output.
39
+ def call(*args)
40
+ base.call(*args)
41
+ end
42
+
43
+ private
44
+
45
+ # Attempts to find a middleware registered with the given name in the middleware registrar.
46
+ # If one could not be found, raises an appropriate error.
47
+ # @param name [Symbol] the name to search for.
48
+ # @return the found middleware.
49
+ def lookup_middleware(name, registrar)
50
+ result = registrar.find(name)
51
+ raise UnregisteredMiddlewareError, name if result.nil?
52
+
53
+ result
54
+ end
55
+ end
56
+ end
@@ -3,7 +3,7 @@
3
3
  module EditInPlace
4
4
  # {Registrar} is a class that is capable of storing a list of objects registered with symbol
5
5
  # names. Note that it makes no attempt to validate the objects registered. If such validation
6
- # is required feel free to subclass {Registrar} and override the {validate_registration!}
6
+ # is required feel free to subclass {Registrar} and override the {#validate_registration!}
7
7
  # method.
8
8
  #
9
9
  # @author Jacob Lockard
@@ -17,7 +17,7 @@ module EditInPlace
17
17
  # Creates a deep copy of this {Registrar} that can be safely modified.
18
18
  # @return [Registrar] a deep copy of this registrar.
19
19
  def dup
20
- r = Registrar.new
20
+ r = self.class.new
21
21
  r.register_all(all)
22
22
  r
23
23
  end
@@ -59,17 +59,15 @@ module EditInPlace
59
59
  # internal one and can be safely modified.
60
60
  # @return [Hash<(Symbol, Object)>] the hash of registered names and objects.
61
61
  def all
62
- registrations.deep_dup
62
+ # Be sure to not duplicate classes.
63
+ registrations.transform_values { |r| r.instance_of?(Class) ? r : r.deep_dup }
63
64
  end
64
65
 
65
66
  protected
66
67
 
67
- # @return [Hash<(Symbol, Object)>] A hash of registrations.
68
- attr_reader :registrations
69
-
70
68
  # Should ensure that the given registration is valid. By default a registration is valid if
71
- # its name is not already taken and is a symbol. Subclasses may override this method to add
72
- # validation rules. Errors should be raised for any invalid registrations.
69
+ # its name is not already taken and it is a symbol. Subclasses may override this method to
70
+ # add validation rules. Errors should be raised for any invalid registrations.
73
71
  # @param name [Symbol] the name to validate.
74
72
  # @param _object [Object] the object to validate.
75
73
  # @return [void]
@@ -86,5 +84,11 @@ module EditInPlace
86
84
  ERR
87
85
  end
88
86
  end
87
+
88
+ private
89
+
90
+ # The hash of registrations contained in this {Registrar}.
91
+ # @return [Hash<(Symbol, Object)>] the hash of registrations.
92
+ attr_reader :registrations
89
93
  end
90
94
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EditInPlace
4
+ # An error that occurs when no registered middlewares exist for the middleare name given.
5
+ class UnregisteredMiddlewareError < Error
6
+ # Creates a new instance of {UnregisteredMiddlewareError} with the given middleware name that
7
+ # caused the error.
8
+ # @param name [Symbol] the middleware that caused the error; used in the error message.
9
+ def initialize(name)
10
+ super("No middlewares are registered with the name '#{name}'")
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EditInPlace
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: edit_in_place
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacob
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-15 00:00:00.000000000 Z
11
+ date: 2021-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: byebug
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '11.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rspec-rails
28
+ name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '5.0'
33
+ version: '3.10'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '5.0'
40
+ version: '3.10'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rubocop
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -81,42 +81,35 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0.17'
83
83
  - !ruby/object:Gem::Dependency
84
- name: middlegem
84
+ name: activesupport
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '='
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.1.0
89
+ version: 6.1.3
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '='
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 0.1.0
96
+ version: 6.1.3
97
97
  - !ruby/object:Gem::Dependency
98
- name: rails
98
+ name: middlegem
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: 6.1.3
104
- - - ">="
101
+ - - '='
105
102
  - !ruby/object:Gem::Version
106
- version: 6.1.3.2
103
+ version: 0.2.0
107
104
  type: :runtime
108
105
  prerelease: false
109
106
  version_requirements: !ruby/object:Gem::Requirement
110
107
  requirements:
111
- - - "~>"
112
- - !ruby/object:Gem::Version
113
- version: 6.1.3
114
- - - ">="
108
+ - - '='
115
109
  - !ruby/object:Gem::Version
116
- version: 6.1.3.2
117
- description: 'edit_in_place is a Ruby on Rails plugin that allows the creation of
118
- user interfaces that allow the user to edit content in an intuitive, natural, "in
119
- place" way.
110
+ version: 0.2.0
111
+ description: 'edit_in_place is a gem that allows the creation of user interfaces that
112
+ allow the user to edit content in an intuitive, natural, "in place" way.
120
113
 
121
114
  '
122
115
  email:
@@ -129,18 +122,22 @@ files:
129
122
  - README.md
130
123
  - Rakefile
131
124
  - lib/edit_in_place.rb
125
+ - lib/edit_in_place/array_definition.rb
132
126
  - lib/edit_in_place/builder.rb
133
127
  - lib/edit_in_place/configuration.rb
134
128
  - lib/edit_in_place/duplicate_registration_error.rb
129
+ - lib/edit_in_place/error.rb
135
130
  - lib/edit_in_place/extended_builder.rb
136
131
  - lib/edit_in_place/field_options.rb
137
132
  - lib/edit_in_place/field_type.rb
138
133
  - lib/edit_in_place/field_type_registrar.rb
139
134
  - lib/edit_in_place/invalid_field_type_error.rb
140
135
  - lib/edit_in_place/invalid_registration_name_error.rb
141
- - lib/edit_in_place/railtie.rb
136
+ - lib/edit_in_place/middleware_registrar.rb
137
+ - lib/edit_in_place/middleware_wrapper.rb
142
138
  - lib/edit_in_place/registrar.rb
143
139
  - lib/edit_in_place/unregistered_field_type_error.rb
140
+ - lib/edit_in_place/unregistered_middleware_error.rb
144
141
  - lib/edit_in_place/unsupported_mode_error.rb
145
142
  - lib/edit_in_place/version.rb
146
143
  - lib/tasks/edit_in_place_tasks.rake
@@ -166,5 +163,5 @@ requirements: []
166
163
  rubygems_version: 3.2.3
167
164
  signing_key:
168
165
  specification_version: 4
169
- summary: A Rails plugin that facilitates the creation of intuitive editable content.
166
+ summary: A gem that facilitates the creation of intuitive editable content.
170
167
  test_files: []
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EditInPlace
4
- class Railtie < ::Rails::Railtie
5
- end
6
- end