wallaby-core 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +31 -0
- data/app/controllers/wallaby/application_controller.rb +84 -0
- data/app/controllers/wallaby/resources_controller.rb +381 -0
- data/app/controllers/wallaby/secure_controller.rb +81 -0
- data/app/security/ability.rb +13 -0
- data/config/locales/wallaby.en.yml +140 -0
- data/config/locales/wallaby_class.en.yml +30 -0
- data/config/routes.rb +39 -0
- data/lib/adaptors/wallaby/custom.rb +7 -0
- data/lib/adaptors/wallaby/custom/default_provider.rb +9 -0
- data/lib/adaptors/wallaby/custom/model_decorator.rb +71 -0
- data/lib/adaptors/wallaby/custom/model_finder.rb +13 -0
- data/lib/adaptors/wallaby/custom/model_pagination_provider.rb +14 -0
- data/lib/adaptors/wallaby/custom/model_service_provider.rb +48 -0
- data/lib/authorizers/wallaby/cancancan_authorization_provider.rb +72 -0
- data/lib/authorizers/wallaby/default_authorization_provider.rb +58 -0
- data/lib/authorizers/wallaby/model_authorizer.rb +100 -0
- data/lib/authorizers/wallaby/pundit_authorization_provider.rb +89 -0
- data/lib/concerns/wallaby/authorizable.rb +103 -0
- data/lib/concerns/wallaby/baseable.rb +36 -0
- data/lib/concerns/wallaby/decoratable.rb +101 -0
- data/lib/concerns/wallaby/defaultable.rb +38 -0
- data/lib/concerns/wallaby/engineable.rb +61 -0
- data/lib/concerns/wallaby/fieldable.rb +78 -0
- data/lib/concerns/wallaby/paginatable.rb +72 -0
- data/lib/concerns/wallaby/rails_overridden_methods.rb +42 -0
- data/lib/concerns/wallaby/resourcable.rb +149 -0
- data/lib/concerns/wallaby/servicable.rb +68 -0
- data/lib/concerns/wallaby/shared_helpers.rb +22 -0
- data/lib/concerns/wallaby/themeable.rb +40 -0
- data/lib/decorators/wallaby/resource_decorator.rb +189 -0
- data/lib/errors/wallaby/cell_handling.rb +6 -0
- data/lib/errors/wallaby/forbidden.rb +6 -0
- data/lib/errors/wallaby/general_error.rb +6 -0
- data/lib/errors/wallaby/invalid_error.rb +6 -0
- data/lib/errors/wallaby/model_not_found.rb +11 -0
- data/lib/errors/wallaby/not_authenticated.rb +6 -0
- data/lib/errors/wallaby/not_found.rb +6 -0
- data/lib/errors/wallaby/not_implemented.rb +6 -0
- data/lib/errors/wallaby/resource_not_found.rb +11 -0
- data/lib/errors/wallaby/unprocessable_entity.rb +6 -0
- data/lib/forms/wallaby/form_builder.rb +60 -0
- data/lib/helpers/wallaby/application_helper.rb +79 -0
- data/lib/helpers/wallaby/base_helper.rb +65 -0
- data/lib/helpers/wallaby/configuration_helper.rb +18 -0
- data/lib/helpers/wallaby/form_helper.rb +62 -0
- data/lib/helpers/wallaby/index_helper.rb +84 -0
- data/lib/helpers/wallaby/links_helper.rb +213 -0
- data/lib/helpers/wallaby/resources_helper.rb +52 -0
- data/lib/helpers/wallaby/secure_helper.rb +54 -0
- data/lib/helpers/wallaby/styling_helper.rb +82 -0
- data/lib/interfaces/wallaby/mode.rb +72 -0
- data/lib/interfaces/wallaby/model_authorization_provider.rb +99 -0
- data/lib/interfaces/wallaby/model_decorator.rb +168 -0
- data/lib/interfaces/wallaby/model_finder.rb +12 -0
- data/lib/interfaces/wallaby/model_pagination_provider.rb +107 -0
- data/lib/interfaces/wallaby/model_service_provider.rb +84 -0
- data/lib/paginators/wallaby/model_paginator.rb +115 -0
- data/lib/paginators/wallaby/resource_paginator.rb +12 -0
- data/lib/parsers/wallaby/parser.rb +34 -0
- data/lib/renderers/wallaby/cell.rb +137 -0
- data/lib/renderers/wallaby/cell_resolver.rb +89 -0
- data/lib/renderers/wallaby/custom_lookup_context.rb +64 -0
- data/lib/renderers/wallaby/custom_partial_renderer.rb +33 -0
- data/lib/renderers/wallaby/custom_renderer.rb +16 -0
- data/lib/responders/wallaby/json_api_responder.rb +101 -0
- data/lib/responders/wallaby/resources_responder.rb +28 -0
- data/lib/routes/wallaby/resources_router.rb +72 -0
- data/lib/servicers/wallaby/model_servicer.rb +154 -0
- data/lib/services/wallaby/engine_name_finder.rb +22 -0
- data/lib/services/wallaby/engine_url_for.rb +46 -0
- data/lib/services/wallaby/link_options_normalizer.rb +19 -0
- data/lib/services/wallaby/map/mode_mapper.rb +27 -0
- data/lib/services/wallaby/map/model_class_collector.rb +49 -0
- data/lib/services/wallaby/map/model_class_mapper.rb +38 -0
- data/lib/services/wallaby/prefixes_builder.rb +66 -0
- data/lib/services/wallaby/sorting/hash_builder.rb +19 -0
- data/lib/services/wallaby/sorting/link_builder.rb +69 -0
- data/lib/services/wallaby/sorting/next_builder.rb +63 -0
- data/lib/services/wallaby/sorting/single_builder.rb +20 -0
- data/lib/services/wallaby/type_renderer.rb +50 -0
- data/lib/support/action_dispatch/routing/mapper.rb +75 -0
- data/lib/tree/wallaby/node.rb +25 -0
- data/lib/utils/wallaby/cell_utils.rb +34 -0
- data/lib/utils/wallaby/field_utils.rb +43 -0
- data/lib/utils/wallaby/filter_utils.rb +20 -0
- data/lib/utils/wallaby/model_utils.rb +51 -0
- data/lib/utils/wallaby/module_utils.rb +46 -0
- data/lib/utils/wallaby/params_utils.rb +14 -0
- data/lib/utils/wallaby/preload_utils.rb +44 -0
- data/lib/utils/wallaby/test_utils.rb +34 -0
- data/lib/utils/wallaby/utils.rb +27 -0
- data/lib/wallaby/configuration.rb +103 -0
- data/lib/wallaby/configuration/features.rb +24 -0
- data/lib/wallaby/configuration/mapping.rb +140 -0
- data/lib/wallaby/configuration/metadata.rb +23 -0
- data/lib/wallaby/configuration/models.rb +46 -0
- data/lib/wallaby/configuration/pagination.rb +30 -0
- data/lib/wallaby/configuration/security.rb +98 -0
- data/lib/wallaby/configuration/sorting.rb +28 -0
- data/lib/wallaby/constants.rb +45 -0
- data/lib/wallaby/core.rb +117 -0
- data/lib/wallaby/core/version.rb +7 -0
- data/lib/wallaby/engine.rb +43 -0
- data/lib/wallaby/map.rb +170 -0
- metadata +222 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Servicer related attributes
|
5
|
+
module Servicable
|
6
|
+
# Configurable attribute
|
7
|
+
module ClassMethods
|
8
|
+
# @!attribute [w] model_servicer
|
9
|
+
def model_servicer=(model_servicer)
|
10
|
+
ModuleUtils.inheritance_check model_servicer, application_servicer
|
11
|
+
@model_servicer = model_servicer
|
12
|
+
end
|
13
|
+
|
14
|
+
# @!attribute [r] model_servicer
|
15
|
+
# If Wallaby doesn't get it right, please specify the **model_servicer**.
|
16
|
+
# @example To set model servicer
|
17
|
+
# class Admin::ProductionsController < Admin::ApplicationController
|
18
|
+
# self.model_servicer = ProductServicer
|
19
|
+
# end
|
20
|
+
# @return [Class] model servicer
|
21
|
+
# @raise [ArgumentError] when **model_servicer** doesn't inherit from **application_servicer**
|
22
|
+
# @see Wallaby::ModelServicer
|
23
|
+
# @since 5.2.0
|
24
|
+
attr_reader :model_servicer
|
25
|
+
|
26
|
+
# @!attribute [w] application_servicer
|
27
|
+
def application_servicer=(application_servicer)
|
28
|
+
ModuleUtils.inheritance_check model_servicer, application_servicer
|
29
|
+
@application_servicer = application_servicer
|
30
|
+
end
|
31
|
+
|
32
|
+
# @!attribute [r] application_servicer
|
33
|
+
# The **application_servicer** is as the base class of {#model_servicer}.
|
34
|
+
# @example To set application decorator:
|
35
|
+
# class Admin::ApplicationController < Wallaby::ResourcesController
|
36
|
+
# self.application_servicer = AnotherApplicationServicer
|
37
|
+
# end
|
38
|
+
# @return [Class] application decorator
|
39
|
+
# @raise [ArgumentError] when **model_servicer** doesn't inherit from **application_servicer**
|
40
|
+
# @see Wallaby::ModelServicer
|
41
|
+
# @since 5.2.0
|
42
|
+
def application_servicer
|
43
|
+
@application_servicer ||= ModuleUtils.try_to superclass, :application_servicer
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Model servicer for current modal class. It comes from:
|
48
|
+
#
|
49
|
+
# - controller configuration {Wallaby::Servicable::ClassMethods#model_servicer .model_servicer}
|
50
|
+
# - a generic servicer based on {Wallaby::Servicable::ClassMethods#application_servicer .application_servicer}
|
51
|
+
# @return [Wallaby::ModelServicer] model servicer
|
52
|
+
# @since 5.2.0
|
53
|
+
def current_servicer
|
54
|
+
@current_servicer ||=
|
55
|
+
(controller_to_get(:model_servicer) \
|
56
|
+
|| Map.servicer_map(current_model_class, controller_to_get(:application_servicer))).try do |klass|
|
57
|
+
Rails.logger.info %( - Current servicer: #{klass})
|
58
|
+
klass.new current_model_class, current_authorizer, current_model_decorator
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @deprecated Use {#current_servicer} instead. It will be removed from 5.3.*
|
63
|
+
def current_model_service
|
64
|
+
Utils.deprecate 'deprecation.current_model_service', caller: caller
|
65
|
+
current_servicer
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Shared helpers
|
5
|
+
module SharedHelpers
|
6
|
+
protected
|
7
|
+
|
8
|
+
# Fetch value for given attribute.
|
9
|
+
#
|
10
|
+
# If it's used in controller, it will fetch it from class attribute.
|
11
|
+
# If it's used in view, it will fetch it from controller.
|
12
|
+
# @param attribute_name [String, Symbol] instance attribute name
|
13
|
+
# @param class_attribute_name [String, Symbol] class attribute name
|
14
|
+
# @return [Object] the value
|
15
|
+
def controller_to_get(attribute_name, class_attribute_name = nil)
|
16
|
+
class_attribute_name ||= attribute_name
|
17
|
+
return ModuleUtils.try_to self.class, class_attribute_name if is_a? ::ActionController::Base # controller?
|
18
|
+
|
19
|
+
ModuleUtils.try_to controller, attribute_name # view?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Theme related methods
|
5
|
+
module Themeable
|
6
|
+
# Configurable attributes
|
7
|
+
module ClassMethods
|
8
|
+
# @!attribute [w] theme_name
|
9
|
+
def theme_name=(theme_name)
|
10
|
+
layout theme_name
|
11
|
+
@theme_name = theme_name
|
12
|
+
end
|
13
|
+
|
14
|
+
# @!attribute [r] theme_name
|
15
|
+
# The theme name is used to apply a set of frontend (html/css/javascript) implementation.
|
16
|
+
#
|
17
|
+
# When theme name is set to e.g. `custom_theme`, the following changes will be made:
|
18
|
+
#
|
19
|
+
# - layout will be set to the same name `custom_theme`
|
20
|
+
# - it will be added to the partial lookup prefixes right on top of `wallaby/resources` prefix.
|
21
|
+
#
|
22
|
+
# Once theme name is set, all its controller subclasses will inherit the same theme name
|
23
|
+
# @example To set an theme name:
|
24
|
+
# class Admin::ApplicationController < Wallaby::ResourcesController
|
25
|
+
# self.theme_name = 'admin_theme'
|
26
|
+
# end
|
27
|
+
# @return [String, Symbol, nil] theme name
|
28
|
+
# @since 5.2.0
|
29
|
+
def theme_name
|
30
|
+
@theme_name ||= ModuleUtils.try_to superclass, :theme_name
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [String, Symbol, nil] theme name
|
35
|
+
# @since 5.2.0
|
36
|
+
def current_theme_name
|
37
|
+
controller_to_get __callee__, :theme_name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Resource Decorator base class, designed for decorator pattern.
|
5
|
+
# @see Wallaby::ModelDecorator
|
6
|
+
class ResourceDecorator
|
7
|
+
extend Baseable::ClassMethods
|
8
|
+
|
9
|
+
DELEGATE_METHODS =
|
10
|
+
ModelDecorator.public_instance_methods(false) + Fieldable.public_instance_methods(false) - %i(model_class)
|
11
|
+
|
12
|
+
class << self
|
13
|
+
delegate(*DELEGATE_METHODS, to: :model_decorator, allow_nil: true)
|
14
|
+
|
15
|
+
# @!attribute [w] model_class
|
16
|
+
attr_writer :model_class
|
17
|
+
|
18
|
+
# @!attribute [r] model_class
|
19
|
+
# Return associated model class, e.g. return **Product** for **ProductDecorator**.
|
20
|
+
#
|
21
|
+
# If Wallaby can't recognise the model class for Decorator, it's required to be configured as below example:
|
22
|
+
# @example To configure model class
|
23
|
+
# class Admin::ProductDecorator < Admin::ApplicationDecorator
|
24
|
+
# self.model_class = Product
|
25
|
+
# end
|
26
|
+
# @example To configure model class for version below 5.2.0
|
27
|
+
# class Admin::ProductDecorator < Admin::ApplicationDecorator
|
28
|
+
# def self.model_class
|
29
|
+
# Product
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
# @return [Class] assoicated model class
|
33
|
+
# @return [nil] if current class is marked as base class
|
34
|
+
# @return [nil] if current class is the same as the value of {Wallaby::Configuration::Mapping#resource_decorator}
|
35
|
+
# @return [nil] if current class is {Wallaby::ResourceDecorator}
|
36
|
+
# @return [nil] if assoicated model class is not found
|
37
|
+
def model_class
|
38
|
+
return unless self < ResourceDecorator
|
39
|
+
return if base_class? || self == Wallaby.configuration.mapping.resource_decorator
|
40
|
+
|
41
|
+
@model_class ||= Map.model_class_map(name.gsub(/(^#{namespace}::)|(Decorator$)/, EMPTY_STRING))
|
42
|
+
end
|
43
|
+
|
44
|
+
# @!attribute [w] application_decorator
|
45
|
+
def application_decorator=(application_decorator)
|
46
|
+
ModuleUtils.inheritance_check self, application_decorator
|
47
|
+
@application_decorator = application_decorator
|
48
|
+
end
|
49
|
+
|
50
|
+
# @note This attribute have to be the same as the one defined in the controller in order to make things working.
|
51
|
+
# see {Wallaby::Decoratable::ClassMethods#application_decorator}
|
52
|
+
# @!attribute [r] application_decorator
|
53
|
+
# Assoicated base class.
|
54
|
+
#
|
55
|
+
# Wallaby will try to get the application decorator class from current class's ancestors chain.
|
56
|
+
# For instance, if current class is **ProductDecorator**, and it inherits from **CoreDecorator**,
|
57
|
+
# then Wallaby will return application decorator class **CoreDecorator**.
|
58
|
+
#
|
59
|
+
# However, there is a chance that Wallaby doesn't get it right.
|
60
|
+
# For instance, if **CoreDecorator** in the above example inherits from **Admin::ApplicationDecorator**, and
|
61
|
+
# the controller that needs **ProductDecorator** has set its **application_decorator** to
|
62
|
+
# **Admin::ApplicationDecorator**, then it's needed to configure **application_decorator** as the example
|
63
|
+
# describes
|
64
|
+
# @example To set application decorator class
|
65
|
+
# class ProductController < Admin::ApplicationController
|
66
|
+
# self.application_decorator = Admin::ApplicationDecorator
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# class CoreDecorator < Admin::ApplicationDecorator
|
70
|
+
# base_class!
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# class ProductDecorator < CoreDecorator
|
74
|
+
# self.application_decorator = Admin::ApplicationDecorator
|
75
|
+
# end
|
76
|
+
# @return [Class] assoicated base class.
|
77
|
+
# @return [nil] if assoicated base class is not found from its ancestors chain
|
78
|
+
# @raise [ArgumentError] when current class doesn't inherit from given value
|
79
|
+
# @since 5.2.0
|
80
|
+
def application_decorator
|
81
|
+
@application_decorator ||= ancestors.find { |parent| parent < ResourceDecorator && !parent.model_class }
|
82
|
+
end
|
83
|
+
|
84
|
+
# Return associated model decorator.
|
85
|
+
#
|
86
|
+
# Fetch model decorator instance from cached map using keys {.model_class} and {.application_decorator}
|
87
|
+
# so that model decorator can be used in its sub classes declaration/scope.
|
88
|
+
# @param model_class [Class]
|
89
|
+
# @return [Wallaby::ModelDecorator]
|
90
|
+
def model_decorator(model_class = self.model_class)
|
91
|
+
return unless self < ResourceDecorator || model_class
|
92
|
+
|
93
|
+
Map.model_decorator_map model_class, application_decorator
|
94
|
+
end
|
95
|
+
|
96
|
+
# @!attribute [w] h
|
97
|
+
attr_writer :h
|
98
|
+
|
99
|
+
# @!attribute [r] h
|
100
|
+
# @return [ActionView::Base]
|
101
|
+
# {Wallaby::Configuration::Mapping#resources_controller resources controller}'s helpers
|
102
|
+
def h
|
103
|
+
@h ||= Wallaby.configuration.mapping.resources_controller.helpers
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# @!attribute [r] resource
|
108
|
+
# @return [Object]
|
109
|
+
attr_reader :resource
|
110
|
+
|
111
|
+
# @!attribute [r] model_decorator
|
112
|
+
# @return [Wallaby::ModelDecorator]
|
113
|
+
attr_reader :model_decorator
|
114
|
+
|
115
|
+
# @return [ActionView::Base]
|
116
|
+
# {Wallaby::Configuration::Mapping#resources_controller resources controller}'s helpers
|
117
|
+
# @see .h
|
118
|
+
def h
|
119
|
+
self.class.h
|
120
|
+
end
|
121
|
+
|
122
|
+
delegate(*DELEGATE_METHODS, to: :model_decorator)
|
123
|
+
# NOTE: this delegation is to make url helper method working properly with resource decorator instance
|
124
|
+
delegate :to_s, :to_param, to: :resource
|
125
|
+
|
126
|
+
# @param resource [Object]
|
127
|
+
def initialize(resource)
|
128
|
+
@resource = resource
|
129
|
+
@model_decorator = self.class.model_decorator(model_class)
|
130
|
+
end
|
131
|
+
|
132
|
+
# @return [Class] resource's class
|
133
|
+
def model_class
|
134
|
+
resource.class
|
135
|
+
end
|
136
|
+
|
137
|
+
# @param field_name [String, Symbol]
|
138
|
+
# @return [Object] value of given field name
|
139
|
+
def value_of(field_name)
|
140
|
+
return unless field_name
|
141
|
+
|
142
|
+
resource.try field_name
|
143
|
+
end
|
144
|
+
|
145
|
+
# Guess the title for given resource.
|
146
|
+
#
|
147
|
+
# It falls back to primary key value when no text field is found.
|
148
|
+
# @return [String] a label
|
149
|
+
def to_label
|
150
|
+
# NOTE: `.to_s` at the end is to ensure String is returned that won't cause any
|
151
|
+
# issue when `#to_label` is used in a link_to block. Coz integer is ignored.
|
152
|
+
(model_decorator.guess_title(resource) || primary_key_value).to_s
|
153
|
+
end
|
154
|
+
|
155
|
+
# @return [Hash, Array] validation/result errors
|
156
|
+
def errors
|
157
|
+
model_decorator.form_active_errors(resource)
|
158
|
+
end
|
159
|
+
|
160
|
+
# @return [Object] primary key value
|
161
|
+
def primary_key_value
|
162
|
+
resource.try primary_key
|
163
|
+
end
|
164
|
+
|
165
|
+
# @return [ActiveModel::Name]
|
166
|
+
def model_name
|
167
|
+
ModuleUtils.try_to(resource, :model_name) || ActiveModel::Name.new(model_class)
|
168
|
+
end
|
169
|
+
|
170
|
+
# @return [nil] if no primary key
|
171
|
+
# @return [Array<String>] primary key
|
172
|
+
def to_key
|
173
|
+
key = ModuleUtils.try_to(resource, primary_key)
|
174
|
+
key ? [key] : nil
|
175
|
+
end
|
176
|
+
|
177
|
+
# Delegate missing method to {#resource}
|
178
|
+
def method_missing(method_id, *args, &block)
|
179
|
+
return super unless resource.respond_to? method_id
|
180
|
+
|
181
|
+
resource.try method_id, *args, &block
|
182
|
+
end
|
183
|
+
|
184
|
+
# Delegate missing method check to context
|
185
|
+
def respond_to_missing?(method_id, _include_private)
|
186
|
+
resource.respond_to?(method_id) || super
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wallaby
|
4
|
+
# Custom form builder to add more helper functions
|
5
|
+
class FormBuilder < ::ActionView::Helpers::FormBuilder
|
6
|
+
# Return error class if there is error
|
7
|
+
# @param field_name [String/Symbol]
|
8
|
+
# @return [String]
|
9
|
+
def error_class(field_name)
|
10
|
+
'has-error' if object.errors[field_name].present?
|
11
|
+
end
|
12
|
+
|
13
|
+
# Build up the HTML for displaying error messages
|
14
|
+
# @param field_name [String/Symbol]
|
15
|
+
# @return [String] HTML
|
16
|
+
def error_messages(field_name)
|
17
|
+
errors = Array object.errors[field_name]
|
18
|
+
return if errors.blank?
|
19
|
+
|
20
|
+
content_tag :ul, class: 'errors' do
|
21
|
+
errors.each do |message|
|
22
|
+
concat content_tag :li, content_tag(
|
23
|
+
:small, raw(message) # rubocop:disable Rails/OutputSafety
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Extend label to accept proc type `text` argument
|
30
|
+
# @see ActionView::Helpers::FormBuilder#label
|
31
|
+
def label(method, text = nil, options = {}, &block)
|
32
|
+
text = instance_exec(&text) if text.is_a?(Proc)
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
# Extend select to accept proc type `choices` argument
|
37
|
+
# @see ActionView::Helpers::FormBuilder#select
|
38
|
+
def select(method, choices = nil, options = {}, html_options = {}, &block)
|
39
|
+
choices = instance_exec(&choices) if choices.is_a?(Proc)
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
# Delegate missing method to `@template`
|
46
|
+
def method_missing(method, *args, &block)
|
47
|
+
return super unless @template.respond_to? method
|
48
|
+
|
49
|
+
# Delegate the method so that we don't come in here the next time
|
50
|
+
# when same method is called
|
51
|
+
self.class.delegate method, to: :@template
|
52
|
+
@template.public_send method, *args, &block
|
53
|
+
end
|
54
|
+
|
55
|
+
# Delegate missing method check to `@template`
|
56
|
+
def respond_to_missing?(method, _include_private)
|
57
|
+
@template.respond_to?(method) || super
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|