diff --git a/CHANGELOG.md b/CHANGELOG.md index ab98f0423fcdd9349ec9fcb8bff696a026a6a718..dd947cabd10c3b7accfd42ed5db49fb28ead4bf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### next version - refactor: remove unused logger +- feat: add ability to configure gem behavior ### v1.0.3 - fix commit f989786 that changed the wrong line (0b7832e) diff --git a/app/models/coupdoeil/popover/options_set.rb b/app/models/coupdoeil/popover/options_set.rb index 7388c103e5911e91c5b11dfe13eefa9f77f3709c..1a1cc65c63799e57a42016bd413f2a9b2af7587a 100644 --- a/app/models/coupdoeil/popover/options_set.rb +++ b/app/models/coupdoeil/popover/options_set.rb @@ -32,17 +32,15 @@ module Coupdoeil OptionsSet.new(options.merge(options_set.options)) end - if Rails.env.local? - def validate! - ORDERED_OPTIONS.map do |option| - next unless options.key?(option.key) - - value = options[option.key] - option.new(value).validate! - end + def validate! + return if Coupdoeil.config.validate_options == false || @to_base36.present? + + ORDERED_OPTIONS.map do |option| + next unless options.key?(option.key) + + value = options[option.key] + option.new(value).validate! end - else - def validate! = nil # no-op end def to_base36 diff --git a/app/models/coupdoeil/tag.rb b/app/models/coupdoeil/tag.rb index 2a25fcbb63ea781b3e225e21d478793865741d1c..fcda0f4fa0fedb1460d9436fa0d851c4fc2eb0ca 100644 --- a/app/models/coupdoeil/tag.rb +++ b/app/models/coupdoeil/tag.rb @@ -36,7 +36,7 @@ module Coupdoeil attributes.merge!("popover-type" => popover_setup.identifier, "popover-params" => params) end - if Rails.env.local? + if Coupdoeil.config.options_html_attributes attributes.merge!(popover_options.to_h.transform_keys { "popover-#{_1}" }) end diff --git a/docs/guides/authentication.md b/docs/guides/authentication.md index 7f73b4a47c4f1d444223e0006f079fb1766cdf07..c08c26c3d3bb390d31e1d26fd3ea1d8e191ffe53 100644 --- a/docs/guides/authentication.md +++ b/docs/guides/authentication.md @@ -2,7 +2,7 @@ layout: default title: Handle authentication parent: How-to guides -nav_order: 6 +nav_order: 7 --- # {{ page.title }} diff --git a/docs/guides/configuration.md b/docs/guides/configuration.md new file mode 100644 index 0000000000000000000000000000000000000000..a770798572099df388ef551a6348c7b22f5e8ef9 --- /dev/null +++ b/docs/guides/configuration.md @@ -0,0 +1,51 @@ +--- +layout: default +title: Configuration +parent: How-to guides +nav_order: 6 +--- + +# {{ page.title }} + +To configure Coupdoeil you can either use an initializer: + +```ruby +# config/initializers/coupdoeil.rb + +Coupdoeil.configure do |config| + config.validate_options = true +end +``` + +or set it up in `config/environments/ENVIRONMENT.rb`: + +```ruby +# config/environments/production.rb + +MyApplication.configure do + config.coupdoeil.validate_options = false +end +``` + +## Config attributes + +### `.validate_options` + +| Type | **Boolean** | +| Default | `Rails.env.local?` | + +Whether to validate popover options before building the tag when calling `coupdoeil_popover_tag`. +It will raise an error with a hint on how to fix it if an option's value is not valid. + +This is enabled in local envs only to save some resources in production, especially on pages rendering a lot a `` tags (not a huge save, but nothing's negligible if traffic is high or if we consider resources usage cumulated over a long period of time). + +Note that default options are validated only once since their compressed version is memoized. So, if you never pass custom option to the helper this option won't have much impact. + +### `.options_html_attributes` + +| Type | **Boolean** | +| Default | `Rails.env.local?` | + +Whether to insert options as HTML attributes of the `` tag for inspection. +This is not required for popovers to work since options are compressed as base 36 to lighten the HTML payload. +This option is meant to help for debug or testing. diff --git a/docs/html-elements.md b/docs/html-elements.md index e821e144f21f0ec6fe30cc4a0203789d56d5b8fe..a25be298091b241067ec0bc53137a6e452bb966a 100644 --- a/docs/html-elements.md +++ b/docs/html-elements.md @@ -16,17 +16,14 @@ If you inspect the DOM where there is a popover set up you'll see it: ``` ```html -

My Project

``` -When inspecting element in local environment (dev, test), you can also see all the options. -But to avoid cluttering the DOM with very repetitive data, and overburden HTML payload, in production the options are compressed to the minimum. -This is the `popover-options="c"` attribute that can be seen in the example above. -If you're interested to know how this compression works, you can take a look at `#to_base36` method in `Coupdoeil::Popover::OptionsSet`. +The `popover-options="63r41l"` attribute that can be seen in the example above are the popover options compressed to lighten the HTML payload. If you're interested to know how this compression works, you can take a look at `#to_base36` method in `Coupdoeil::Popover::OptionsSet`. See [inspecting options](/options.html#inspecting-options) for debug or testing. When the popover is open, the `coup-doeil` tag attribute `data-popover-open` is set to `"true"`. @@ -37,7 +34,7 @@ When rendering a popover, you can think of it made of three layers: 2. the layout 3. the content -You handle the two former elements, but the first one is fully handled by the library. +The first one is fully handled by the library, but you have control over the last two elements. The positioned element has the `.coupdoeil--popover` CSS class, a `data-placement` attribute that is set to the current popover position relative to its target, diff --git a/docs/options.md b/docs/options.md index ae577f4cbfd0253296b35b87fd3454efc6b9af9b..4cc6b585ecb4c18a90a60d3d51e5c2922c53d102 100644 --- a/docs/options.md +++ b/docs/options.md @@ -19,14 +19,14 @@ This facilitates uniform rendering of popovers across your application without h Options are passed as a hash with lower snake cased keys to either [`default_options`](/api.html#default_options---coupdoeilpopoveroptionsset) or [`default_options_for`](/api.html#default_options_for---coupdoeilpopoveroptionsset) methods. -## Differences between development and production -Options are validated when in local environment (development or test). +## Validations + +Options are validated when inserting a popover in a template. If an option is not set with a correct value, an error is raised with a hint on how to resolve it. -In production, these validations are skipped to speed up the coupdoeil tag rendering. +By default, validations are run in local environments (development or test), and skipped in production to speed up the rendering. -Also note that in production, the options are not readable on the `` element, as they are compressed to the minimum possible size. -**You should therefore not have any logic relying on the ability to read the options on this element, these are only available for debug**. +This behavior is configurable: [validation configuration](/guides/configuration.html#validate_options). ## Default options for the class @@ -96,3 +96,16 @@ ContactPopover.default_options ContactPopover.default_options_for(:tooltip) #=> { animation: false, ... } ``` + +You can also inspect options in the HTML. + +```html + + + +``` + +Note that by default, the options are not set on the `` element in production, as they are compressed to the minimum possible size (and set as the `popover-options` attribute). It is therefore advised not to have any logic relying on the ability to read the options on this element, these attributes are only meant for debug and testing. + +This behavior is configurable: [options HTML attributes configuration](/guides/configuration.html#options_html_attributes). diff --git a/lib/coupdoeil.rb b/lib/coupdoeil.rb index 3164efda7705c340a662ec6edc7f7103d514f50e..e56e8c9f513bee4bd08b0595cdbd05e01de69fda 100644 --- a/lib/coupdoeil.rb +++ b/lib/coupdoeil.rb @@ -5,4 +5,9 @@ require "coupdoeil/engine" module Coupdoeil extend ActiveSupport::Autoload + + class << self + def config = Coupdoeil::Config.current + def configure = yield(Coupdoeil::Config.current) + end end diff --git a/lib/coupdoeil/config.rb b/lib/coupdoeil/config.rb new file mode 100644 index 0000000000000000000000000000000000000000..fde6a8410da966571064fea257be5769da9a9bab --- /dev/null +++ b/lib/coupdoeil/config.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Coupdoeil + class Config + class << self + def defaults + ActiveSupport::OrderedOptions.new.merge!({ + validate_options: Rails.env.local?, + options_html_attributes: Rails.env.local?, + }) + end + + # @!attribute validate_options + # @return [Boolean] + # Whether to validate popover options when building it. + # It will raise an error with a hint on how to fix it if an option's value is not valid. + # Defaults to `Rails.env.local?`. + + # @!attribute options_html_attributes + # @return [Boolean] + # Whether to insert options as HTML attributes of the tag. + # This is not required for Coupdoeil to work since options are compressed to base 36 to lighten the HTML payload. + # This option is here to help for debug or testing. + # Defaults to `Rails.env.local?`. + end + # @!attribute current + # @return [Coupdoeil::Config] + # Returns the current Coupdoeil::Config. This is persisted against this + # class so that config options remain accessible before the rest of + # Coupdoeil has loaded. Defaults to an instance of Coupdoeil::Config + # with all other documented defaults set. + class_attribute :current, default: defaults, instance_predicate: false + end +end diff --git a/lib/coupdoeil/engine.rb b/lib/coupdoeil/engine.rb index 0a714f4a5043ddbf0e2f47a4d0042dc205eecd98..fb3f962a1e7f5670063a2b574eeecec0e973a27f 100644 --- a/lib/coupdoeil/engine.rb +++ b/lib/coupdoeil/engine.rb @@ -1,10 +1,12 @@ # frozen_string_literal: true +require "coupdoeil/config" + module Coupdoeil class Engine < ::Rails::Engine isolate_namespace Coupdoeil config.eager_load_namespaces << Coupdoeil - config.coupdoeil = ActiveSupport::OrderedOptions.new + config.coupdoeil = Coupdoeil::Config.current config.autoload_once_paths = [ "#{root}/app/controllers", diff --git a/test/dummy/config/initializers/coupdoeil.rb b/test/dummy/config/initializers/coupdoeil.rb new file mode 100644 index 0000000000000000000000000000000000000000..86d06c404e8ed0b9661b1dbf6737393e2198857f --- /dev/null +++ b/test/dummy/config/initializers/coupdoeil.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +Coupdoeil.configure do |config| + config.options_html_attributes = false +end