Module: Compony
- Defined in:
- lib/compony.rb,
lib/compony/engine.rb,
lib/compony/version.rb,
lib/compony/component.rb,
lib/compony/model_mixin.rb,
lib/compony/view_helpers.rb,
lib/compony/components/new.rb,
lib/compony/components/edit.rb,
lib/compony/components/form.rb,
lib/compony/request_context.rb,
lib/compony/controller_mixin.rb,
lib/compony/model_fields/url.rb,
lib/compony/components/button.rb,
lib/compony/model_fields/base.rb,
lib/compony/model_fields/date.rb,
lib/compony/model_fields/text.rb,
lib/compony/model_fields/time.rb,
lib/compony/components/destroy.rb,
lib/compony/model_fields/email.rb,
lib/compony/model_fields/float.rb,
lib/compony/model_fields/phone.rb,
lib/compony/model_fields/string.rb,
lib/compony/components/with_form.rb,
lib/compony/model_fields/boolean.rb,
lib/compony/model_fields/decimal.rb,
lib/compony/model_fields/integer.rb,
lib/compony/model_fields/currency.rb,
lib/compony/model_fields/datetime.rb,
lib/compony/method_accessible_hash.rb,
lib/compony/model_fields/rich_text.rb,
lib/compony/model_fields/attachment.rb,
lib/compony/model_fields/anchormodel.rb,
lib/compony/model_fields/association.rb,
lib/compony/component_mixins/resourceful.rb,
lib/compony/component_mixins/default/labelling.rb,
lib/compony/component_mixins/default/standalone.rb,
lib/compony/component_mixins/default/standalone/verb_dsl.rb,
lib/compony/component_mixins/default/standalone/standalone_dsl.rb,
lib/compony/component_mixins/default/standalone/resourceful_verb_dsl.rb
Overview
Root module, containing confguration and pure helpers. For
the setters, create an initializer config/initializers/compony.rb and call
them from there.
Defined Under Namespace
Modules: ComponentMixins, Components, ControllerMixin, ModelFields, ModelMixin, Version, ViewHelpers Classes: Component, Engine, MethodAccessibleHash, RequestContext
Class Method Summary collapse
-
.authentication_before_action ⇒ Object
Getter for the name of the Rails
before_actionthat enforces authentication. -
.authentication_before_action=(authentication_before_action) ⇒ Object
Setter for the name of the Rails
before_actionthat should be called to ensure that users are authenticated before accessing the component. -
.button(comp_name_or_cst, model_or_family_name_or_cst, label_opts: nil, params: nil, feasibility_action: nil, feasibility_target: nil, method: nil, **override_kwargs) ⇒ Object
Given a component and a family/model, this instanciates and returns a button component.
-
.button_component_class ⇒ Object
Getter for the global button component class.
-
.button_component_class=(button_component_class) ⇒ Object
Setter for the global button component class.
-
.button_defaults ⇒ Object
Getter for current button defaults.
-
.comp_class_for(comp_name_or_cst, model_or_family_name_or_cst) ⇒ Object
Given a component and a family/model, this returns the matching component class if any, or nil if the component does not exist.
-
.comp_class_for!(comp_name_or_cst, model_or_family_name_or_cst) ⇒ Object
Same as Compony#comp_class_for but fails if none found.
-
.family_name_for(model_or_family_name_or_cst) ⇒ Object
Given a family name or a model-like class, this returns the suitable family name as String.
-
.model_field_class_for(constant) ⇒ Object
Goes through model_field_namespaces and returns the first hit for the given constant.
-
.model_field_namespaces ⇒ Object
Getter for the global field namespaces.
-
.model_field_namespaces=(model_field_namespaces) ⇒ Object
Setter for the global field namespaces.
-
.path(comp_name_or_cst, model_or_family_name_or_cst, *args_for_path_helper, **kwargs_for_path_helper) ⇒ Object
Generates a Rails path to a component.
-
.path_helper_name ⇒ Object
Given a component and a family, this returns the name of the Rails URL helper returning the path to this component.
The parameters are the same as for Compony.rails_action_name.
Example usage:send("#{path_helper_name(:index, :users)}_url). -
.rails_action_name(comp_name_or_cst, model_or_family_name_or_cst, name = nil) ⇒ Object
Given a component and a family, this returns the name of the ComponyController action for this component.
Optionally can pass a name for extra standalone configs. -
.root_comp ⇒ Object
Returns the current root component, if any.
-
.with_button_defaults(**keys_to_overwrite, &block) ⇒ Object
Overwrites the keys of the current button defaults by the ones provided during the execution of a given block and restores them afterwords.
Class Method Details
.authentication_before_action ⇒ Object
Getter for the name of the Rails before_action that enforces authentication.
63 64 65 |
# File 'lib/compony.rb', line 63 def self.authentication_before_action @authentication_before_action end |
.authentication_before_action=(authentication_before_action) ⇒ Object
Setter for the name of the Rails before_action that should be called to
ensure that users are authenticated before accessing the component. For
instance, implement a method def enforce_authentication in your
ApplicationController. In the method, make sure the user has a session and
redirect to the login page if they don't.
The action must be accessible
by ComponyController and the easiest way to achieve this is to implement
the action in your ApplicationController. If this is never called,
authentication is disabled.
39 40 41 |
# File 'lib/compony.rb', line 39 def self.authentication_before_action=(authentication_before_action) @authentication_before_action = authentication_before_action.to_sym end |
.button(comp_name_or_cst, model_or_family_name_or_cst, label_opts: nil, params: nil, feasibility_action: nil, feasibility_target: nil, method: nil, **override_kwargs) ⇒ Object
Given a component and a family/model, this instanciates and returns a button component.
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/compony.rb', line 142 def self.(comp_name_or_cst, model_or_family_name_or_cst, label_opts: nil, params: nil, feasibility_action: nil, feasibility_target: nil, method: nil, **override_kwargs) label_opts ||= [:label_opts] || {} params ||= [:params] || {} model = model_or_family_name_or_cst.respond_to?(:model_name) ? model_or_family_name_or_cst : nil target_comp_instance = Compony.comp_class_for!(comp_name_or_cst, model_or_family_name_or_cst).new(data: model) feasibility_action ||= [:feasibility_action] || comp_name_or_cst.to_s.underscore.to_sym feasibility_target ||= [:feasibility_target] || model = { label: target_comp_instance.label(model, **label_opts), icon: target_comp_instance.icon, color: target_comp_instance.color, path: Compony.path(target_comp_instance.comp_name, target_comp_instance.family_name, model, **params), method:, visible: ->(controller) { target_comp_instance.standalone_access_permitted_for?(controller, verb: method) } } if feasibility_target .merge!({ enabled: feasibility_target.feasible?(feasibility_action), title: feasibility_target.(feasibility_action).presence }) end .merge!(override_kwargs.symbolize_keys) return Compony..new(**.symbolize_keys) end |
.button_component_class ⇒ Object
Getter for the global button component class.
49 50 51 52 53 |
# File 'lib/compony.rb', line 49 def self. @button_component_class ||= Components::Button @button_component_class = const_get(@button_component_class) if @button_component_class.is_a?(String) return @button_component_class end |
.button_component_class=(button_component_class) ⇒ Object
Setter for the global button component class. This allows you to implement a custom button component and have all Compony button helpers use your custom button component instead of Compony::Components::Button.
15 16 17 |
# File 'lib/compony.rb', line 15 def self.() @button_component_class = end |
.button_defaults ⇒ Object
document params
Getter for current button defaults
193 194 195 |
# File 'lib/compony.rb', line 193 def self. RequestStore.store[:button_defaults] || {} end |
.comp_class_for(comp_name_or_cst, model_or_family_name_or_cst) ⇒ Object
Given a component and a family/model, this returns the matching component class if any, or nil if the component does not exist.
94 95 96 97 98 99 100 101 |
# File 'lib/compony.rb', line 94 def self.comp_class_for(comp_name_or_cst, model_or_family_name_or_cst) family_cst_str = family_name_for(model_or_family_name_or_cst).camelize comp_cst_str = comp_name_or_cst.to_s.camelize return nil unless ::Components.const_defined?(family_cst_str) family_constant = ::Components.const_get(family_cst_str) return nil unless family_constant.const_defined?(comp_cst_str) return family_constant.const_get(comp_cst_str) end |
.comp_class_for!(comp_name_or_cst, model_or_family_name_or_cst) ⇒ Object
Same as Compony#comp_class_for but fails if none found
105 106 107 108 109 |
# File 'lib/compony.rb', line 105 def self.comp_class_for!(comp_name_or_cst, model_or_family_name_or_cst) comp_class_for(comp_name_or_cst, model_or_family_name_or_cst) || fail( "No component found for [#{comp_name_or_cst.inspect}, #{model_or_family_name_or_cst.inspect}]" ) end |
.family_name_for(model_or_family_name_or_cst) ⇒ Object
Given a family name or a model-like class, this returns the suitable family name as String.
183 184 185 186 187 188 189 |
# File 'lib/compony.rb', line 183 def self.family_name_for(model_or_family_name_or_cst) if model_or_family_name_or_cst.respond_to?(:model_name) return model_or_family_name_or_cst.model_name.plural else return model_or_family_name_or_cst.to_s.underscore end end |
.model_field_class_for(constant) ⇒ Object
Goes through model_field_namespaces and returns the first hit for the given constant
224 225 226 227 228 229 230 231 232 |
# File 'lib/compony.rb', line 224 def self.model_field_class_for(constant) model_field_namespaces.each do |model_field_namespace| model_field_namespace = model_field_namespace.constantize if model_field_namespace.is_a?(::String) if model_field_namespace.const_defined?(constant, false) return model_field_namespace.const_get(constant, false) end end fail("No `model_field_namespace` implements ...::#{constant}. Configured namespaces: #{Compony.model_field_namespaces.inspect}") end |
.model_field_namespaces ⇒ Object
Getter for the global field namespaces.
57 58 59 |
# File 'lib/compony.rb', line 57 def self.model_field_namespaces return @model_field_namespaces ||= ['Compony::ModelFields'] end |
.model_field_namespaces=(model_field_namespaces) ⇒ Object
Setter for the global field namespaces. This allows you to implement custom Fields, be it new ones or overrides for existing Compony model fields. Must give an array of strings of namespaces that contain field classes named after the field type. The array is queried in order, if the first namespace does not contain the class we're looking for, the next is considered and so on. The classes defined in the namespace must inherit from Compony::ModelFields::Base
26 27 28 |
# File 'lib/compony.rb', line 26 def self.model_field_namespaces=(model_field_namespaces) @model_field_namespaces = model_field_namespaces end |
.path(comp_name_or_cst, model_or_family_name_or_cst, *args_for_path_helper, **kwargs_for_path_helper) ⇒ Object
Generates a Rails path to a component. Examples: Compony.path(:index, :users), Compony.path(:show, User.first)
79 80 81 82 83 84 85 86 87 |
# File 'lib/compony.rb', line 79 def self.path(comp_name_or_cst, model_or_family_name_or_cst, *args_for_path_helper, **kwargs_for_path_helper) # Extract model if any, to get the ID kwargs_for_path_helper.merge!(id: model_or_family_name_or_cst.id) if model_or_family_name_or_cst.respond_to?(:model_name) return Rails.application.routes.url_helpers.send( "#{path_helper_name(comp_name_or_cst, model_or_family_name_or_cst)}_path", *args_for_path_helper, **kwargs_for_path_helper ) end |
.path_helper_name ⇒ Object
Given a component and a family, this returns the name of the Rails URL helper returning the path to this component.
The parameters are the same as for rails_action_name.
Example usage: send("#{path_helper_name(:index, :users)}_url)
116 117 118 |
# File 'lib/compony.rb', line 116 def self.path_helper_name(...) "#{rails_action_name(...)}_comp" end |
.rails_action_name(comp_name_or_cst, model_or_family_name_or_cst, name = nil) ⇒ Object
Given a component and a family, this returns the name of the ComponyController action for this component.
Optionally can pass a name for extra standalone configs.
126 127 128 |
# File 'lib/compony.rb', line 126 def self.rails_action_name(comp_name_or_cst, model_or_family_name_or_cst, name = nil) [name.presence, comp_name_or_cst.to_s.underscore, family_name_for(model_or_family_name_or_cst)].compact.join('_') end |
.root_comp ⇒ Object
Returns the current root component, if any
175 176 177 |
# File 'lib/compony.rb', line 175 def self.root_comp RequestStore.store[:compony_root_comp] end |
.with_button_defaults(**keys_to_overwrite, &block) ⇒ Object
Overwrites the keys of the current button defaults by the ones provided during the execution of a given block and restores them afterwords. This method is useful when the same set of options is to be given to a multitude of buttons.
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/compony.rb', line 201 def self.(**keys_to_overwrite, &block) # Lazy initialize butto_defaults store if it hasn't been yet RequestStore.store[:button_defaults] ||= {} keys_to_overwrite.transform_keys!(&:to_sym) old_values = {} newly_defined_keys = keys_to_overwrite.keys - RequestStore.store[:button_defaults].keys keys_to_overwrite.each do |key, new_value| # Assign new value old_values[key] = RequestStore.store[:button_defaults][key] RequestStore.store[:button_defaults][key] = new_value end return_value = block.call # Restore previous value keys_to_overwrite.each do |key, _new_value| RequestStore.store[:button_defaults][key] = old_values[key] end # Undefine keys that were not there previously newly_defined_keys.each { |key| RequestStore.store[:button_defaults].delete(key) } return return_value end |