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/form.rb,
lib/compony/request_context.rb,
lib/compony/controller_mixin.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/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/anchormodel.rb,
lib/compony/model_fields/association.rb,
lib/compony/components/resourceful/new.rb,
lib/compony/components/resourceful/edit.rb,
lib/compony/component_mixins/resourceful.rb,
lib/compony/components/resourceful/destroy.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, **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
As above 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.
61 62 63 |
# File 'lib/compony.rb', line 61 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.
37 38 39 |
# File 'lib/compony.rb', line 37 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, **override_kwargs) ⇒ Object
add doc for feasibility
Given a component and a family/model, this instanciates and returns a button component.
138 139 140 141 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 |
# File 'lib/compony.rb', line 138 def self.(comp_name_or_cst, model_or_family_name_or_cst, label_opts: nil, params: nil, feasibility_action: nil, feasibility_target: 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), visible: ->(controller) { target_comp_instance.standalone_access_permitted_for?(controller) } } 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.
47 48 49 50 51 |
# File 'lib/compony.rb', line 47 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
187 188 189 |
# File 'lib/compony.rb', line 187 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.
92 93 94 95 96 97 98 99 |
# File 'lib/compony.rb', line 92 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
As above but fails if none found
102 103 104 105 106 |
# File 'lib/compony.rb', line 102 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.
177 178 179 180 181 182 183 |
# File 'lib/compony.rb', line 177 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
216 217 218 219 220 221 222 223 224 |
# File 'lib/compony.rb', line 216 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.
55 56 57 |
# File 'lib/compony.rb', line 55 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
25 26 27 |
# File 'lib/compony.rb', line 25 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)
77 78 79 80 81 82 83 84 85 |
# File 'lib/compony.rb', line 77 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)
113 114 115 |
# File 'lib/compony.rb', line 113 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.
123 124 125 |
# File 'lib/compony.rb', line 123 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
169 170 171 |
# File 'lib/compony.rb', line 169 def self.root_comp RequestStore.store[:compony_root_comp] end |
.with_button_defaults(**keys_to_overwrite, &block) ⇒ Object
document params
Overwrites the keys of the current button defaults by the ones provided during the execution of a given block and restores them afterwords.
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/compony.rb', line 193 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 |