class Decidim::OrganizationSettings
Takes care of holding and accessing organization settings for each organization or the default organization.
Public Class Methods
Returns the default configuration value for the given setting key chain.
For example:
Decidim::OrganizationSettings.default(:upload, :maximum_file_size, :default) #=> 10
Note: this cannot fetch the default settings from the class instance variable “defaults” because that would cause an infinite loop.
@param *chain [Symbol, String] The configuration key(s) to dig into
inside the default configurations hash.
@return The value found from the default configurations hash.
# File lib/decidim/organization_settings.rb, line 54 def default(*chain) return if chain.blank? configs = defaults_hash while (lookup = chain.shift) configs = configs[lookup.to_s] return configs if chain.empty? return unless configs.is_a?(Hash) end nil end
This is a class level helper to get a “dummy” default settings object that responds to the same methods as the normal organization specific settings objects. This allows for the following kind of syntactic sugar:
settings = Decidim::OrganizationSettings.for(actual_org) settings.target_config_accessor #=> returns the organization setting settings = Decidim::OrganizationSettings.defaults settings.target_config_accessor #=> returns the default setting
This can be used through the Decidim
module as follows:
Decidim.organization_settings(org).target_config_accessor #=> returns the organization specific setting Decidim.organization_settings(model_beloging_to_org).target_config_accessor #=> returns the organization specific setting for model's organization Decidim.organization_settings(nil).target_config_accessor #=> returns the default setting
@return [Decidim::OrganizationSettings] The default settings object.
# File lib/decidim/organization_settings.rb, line 89 def defaults @defaults ||= new(OpenStruct.new) end
Fetches or creates a settings object for the given organization.
@param organization [Decidim::Organization] The organization in
question.
@return [Decidim::OrganizationSettings] The settings object.
# File lib/decidim/organization_settings.rb, line 15 def for(organization) # Before the organization has an ID attached to it, it cannot be stored # to the registry. return new(organization) if organization.new_record? @registry ||= {} @registry[organization.id] ||= new(organization) end
# File lib/decidim/organization_settings.rb, line 140 def initialize(organization) # This maps the local configuration top level keys to the methods/column # names in the organization model that provide the values for these # settings. keys_map = { upload: :file_upload_settings } # Pass a configuration hash to the parent constructor that combines the # default settings with the organization level settings. This ensures that # all configurations have values even when the organization settings do # not define them. super( keys_map.map do |config, method| [ config.to_s, generate_config( organization.public_send(method) || {}, self.class.default(config) ) ] end.to_h ) keys_map.keys.each do |config| define_config_accessors(public_send(config), [config]) end end
Reloads the settings object for a given organization. Should be called when the configurations have changed and need to be reloaded.
@param organization [Decidim::Organization] The organization in question. @return [Decidim::OrganizationSettings] The settings object.
# File lib/decidim/organization_settings.rb, line 29 def reload(organization) @registry.delete(organization.id) if @registry self.for(organization) end
The settings should be reset during the tests in order for the new tests to always load the latest settings. The results of the previous tests should not affect the settings of the following test.
# File lib/decidim/organization_settings.rb, line 37 def reset! @registry = {} end
Private Class Methods
Stores the default settings hash which is used to create the settings objects. This will provide all the missing configuration values for the final object if it does not define some of the values.
Note: This cannot be stored in a class variable because it would change the arrays into comma separated strings.
@return [Hash] The default settings hash.
# File lib/decidim/organization_settings.rb, line 103 def defaults_hash { "upload" => { "allowed_file_extensions" => { "default" => %w(jpg jpeg gif png bmp pdf rtf txt), "admin" => %w(jpg jpeg gif png bmp pdf doc docx xls xlsx ppt ppx rtf txt odt ott odf otg ods ots), "image" => %w(jpg jpeg gif png bmp ico) }, "allowed_content_types" => { "default" => %w( image/* application/pdf application/rtf text/plain ), "admin" => %w( image/* application/vnd.oasis.opendocument application/vnd.ms-* application/msword application/vnd.ms-word application/vnd.openxmlformats-officedocument application/vnd.oasis.opendocument application/pdf application/rtf text/plain ) }, "maximum_file_size" => { "default" => 10, "avatar" => 5 } } } end
Public Instance Methods
# File lib/decidim/organization_settings.rb, line 175 def wrap_upload_allowed_content_types(value) content_type_array(value) end
# File lib/decidim/organization_settings.rb, line 179 def wrap_upload_allowed_content_types_admin(value) content_type_array(value) end
# File lib/decidim/organization_settings.rb, line 167 def wrap_upload_maximum_file_size(value) value.megabytes end
# File lib/decidim/organization_settings.rb, line 171 def wrap_upload_maximum_file_size_avatar(value) value.megabytes end
Private Instance Methods
Turns the stars into wildcard regular expression matches in the matching strings.
@param [Array<String>] An array of glob strings to match against. @return [Array<Regexp>] An array of regular expressions to match against.
# File lib/decidim/organization_settings.rb, line 205 def content_type_array(types) types.map do |match_string| Regexp.new(Regexp.escape(match_string).gsub("\\*", ".*?")) end end
This defines all the config accessors for the configuration parameters that can be directly called for the settings instance without having to “drill down” to the child structs. For example, if the whole settings object was initialized with the following hash:
{ "upload" => { "allowed_file_extensions" => { "default" => %w(jpg jpeg), "admin" => %w(jpg jpeg gif png) } }, "another_thing" => { "bleep" => "bloop", "foo" => { "bar" => 1 "baz" => 2 } } }
This would automatically generate the following methods in the settings instance:
- upload_allowed_file_extensions #=> ["jpg", "jpeg"] - upload_allowed_file_extensions_admin #=> ["jpg", "jpeg", "gif", "png"] - another_thing_bleep #=> "bloop" - another_thing_foo_bar #=> 1 - another_thing_foo_baz #=> 2
Note that when the deepest configuration hash has the key “default”, it will not be appended to the method name.
@param obj [Decidim::OrganizationSettings, OpenStruct] The settings object
for which to define the accessors.
@param chain [Array<Symbol>] The current lookup chain for the settings
object. Needed when called recursively.
# File lib/decidim/organization_settings.rb, line 248 def define_config_accessors(obj, chain) obj.each_pair do |key, val| if val.is_a?(OpenStruct) define_config_accessors(val, [*chain, key]) else prefix = chain.join("_") method = prefix method = "#{method}_#{key}" unless key.to_sym == :default define_singleton_method(method) do value = dig(*chain, key) return value unless respond_to?("wrap_#{method}") public_send("wrap_#{method}", value) end end end end
Generates a final settigns configuration struct from the given settings hash. Combines the given defaults with the settings hash.
@param hash [Hash] The configurations hash. @param default [Hash] The default configurations. @return [OpenStruct] The configuration struct.
# File lib/decidim/organization_settings.rb, line 191 def generate_config(hash, default = {}) OpenStruct.new( default.deep_merge(hash).map do |key, value| value = generate_config(value) if value.is_a?(Hash) [key, value] end.to_h ) end