class Card class View module Options # manages showing and hiding optional view renders module Visibility # tracks show/hide value for each view with an explicit setting # eg { toggle: :hide } def viz_hash @viz_hash ||= {} end # test methods def hide? view viz_hash[view&.to_sym] == :hide end def show? view !hide? view end def explicit_show? view viz_hash[view&.to_sym] == :show end # write methods def show *views viz views, :show end def hide *views viz views, :hide end # force write methods def show! *views viz views, :show, true end def hide! *views viz views, :hide, true end # advanced write method VIZ_SETTING = { show: :show, true => :show, hide: :hide, false => :hide, nil => :hide }.freeze def viz views, setting, force=false Array.wrap(views).flatten.each do |view| view = view.to_sym next if !force && viz_hash[view] viz_hash[view] = VIZ_SETTING[setting] end end def visible? view viz view, yield unless viz_hash[view] show? view end # test whether view is optional # (@optional is set in normalize_options # @return [true/false] def optional? @optional end # translate raw hide, show options (which can be strings, symbols, # arrays, etc) def process_visibility viz_hash.reverse_merge! parent.viz_hash if parent process_visibility_options live_options viz requested_view, @optional if @optional && !viz_hash[requested_view] end private # if true, #process returns nil def hide_requested_view? optional? && hide?(requested_view) end # takes an options_hash and processes it to update viz_hash def process_visibility_options options_hash %i[hide show].each do |setting| views = View.normalize_list(options_hash.delete(setting)).map(&:to_sym) viz views, setting, true end end def normalized_visibility_options viz_hash.each_with_object({}) do |(key, val), hash| hash[val] ||= [] hash[val] << key end end end end end end