class Deface::Override

Attributes

args[RW]
failure[RW]
parsed_document[RW]

Public Class Methods

actions() click to toggle source
# File lib/deface/override.rb, line 207
def self.actions
  Rails.application.config.deface.actions.map &:to_sym
end
all() click to toggle source
# File lib/deface/override.rb, line 203
def self.all
  Rails.application.config.deface.overrides.all
end
digest(details) click to toggle source

Creates MD5 of all overrides that apply to a particular virtual_path, used in CompiledTemplates method name so we can support re-compiling of compiled method when overrides change. Only of use in production mode.

# File lib/deface/override.rb, line 197
def self.digest(details)
  overrides = self.find(details)
  to_hash = overrides.inject('') { |digest, override| digest << override.digest }
  Deface::Digest.hexdigest(to_hash)
end
new(args, &content) click to toggle source

Initializes new override, you must supply only one Target, Action & Source parameter for each override (and any number of Optional parameters).

See READme for more!

# File lib/deface/override.rb, line 17
def initialize(args, &content)
  if Rails.application.try(:config).try(:deface).try(:enabled)
    unless Rails.application.config.deface.try(:overrides)
      @@_early << args
      warn "[WARNING] You no longer need to manually require overrides, remove require for '#{args[:name]}'."
      return
    end
  else
    warn "[WARNING] You no longer need to manually require overrides, remove require for '#{args[:name]}'."
    return
  end

  # If no name was specified, use the filename and line number of the caller
  # Including the line number ensure unique names if multiple overrides
  # are defined in the same file
  unless args.key? :name
    parts = caller[0].split(':')
    file_name = File.basename(parts[0], '.rb')
    line_number = parts[1]
    args[:name] = "#{file_name}_#{line_number}"
  end

  raise(ArgumentError, ":name must be defined") unless args.key? :name
  raise(ArgumentError, ":virtual_path must be defined") if args[:virtual_path].blank?

  args[:text] = content.call if block_given?
  args[:name] = "#{current_railtie.underscore}_#{args[:name]}" if Rails.application.try(:config).try(:deface).try(:namespaced) || args.delete(:namespaced)

  virtual_key = args[:virtual_path].to_sym
  name_key = args[:name].to_s.parameterize

  self.class.all[virtual_key] ||= {}

  if self.class.all[virtual_key].has_key? name_key
    #updating exisiting override

    @args = self.class.all[virtual_key][name_key].args

    #check if the action is being redefined, and reject old action
    if (self.class.actions & args.keys).present?
      @args.reject!{|key, value| (self.class.actions & @args.keys).include? key }
    end

    #check if the source is being redefined, and reject old action
    if (Deface::DEFAULT_SOURCES.map(&:to_sym) & args.keys).present?
      @args.reject!{|key, value| (Deface::DEFAULT_SOURCES.map(&:to_sym) & @args.keys).include? key }
    end

    @args.merge!(args)
  else
    #initializing new override
    @args = args

    raise(ArgumentError, ":action is invalid") if self.action.nil?
  end

  # Set loaded time (if not already present) for hash invalidation
  @args[:updated_at] ||= Time.current.to_f
  @args[:railtie_class] = self.class.current_railtie

  self.class.all[virtual_key][name_key] = self

  expire_compiled_template

  self
end

Public Instance Methods

action() click to toggle source
# File lib/deface/override.rb, line 133
def action
  (self.class.actions & @args.keys).first
end
attributes() click to toggle source

returns attributes hash for attribute related actions

# File lib/deface/override.rb, line 173
def attributes
  @args[:attributes] || []
end
digest() click to toggle source

Creates MD5 hash of args sorted keys and values used to determine if an override has changed

# File lib/deface/override.rb, line 187
def digest
  to_hash = @args.keys.map(&:to_s).sort.concat(@args.values.map(&:to_s).sort).join
  Deface::Digest.hexdigest(to_hash)
end
disabled?() click to toggle source
# File lib/deface/override.rb, line 162
def disabled?
  @args.key?(:disabled) ? @args[:disabled] : false
end
end_selector() click to toggle source
# File lib/deface/override.rb, line 166
def end_selector
  return nil if @args[:closing_selector].blank?
  @args[:closing_selector]
end
name() click to toggle source
# File lib/deface/override.rb, line 88
def name
  @args[:name]
end
railtie_class() click to toggle source
# File lib/deface/override.rb, line 92
def railtie_class
  @args[:railtie_class]
end
safe_source_element() click to toggle source
# File lib/deface/override.rb, line 157
def safe_source_element
  return unless source_argument
  source_element
end
selector() click to toggle source
# File lib/deface/override.rb, line 84
def selector
  @args[self.action]
end
sequence() click to toggle source
# File lib/deface/override.rb, line 96
def sequence
  return 100 unless @args.key?(:sequence)
  if @args[:sequence].is_a? Hash
    key = @args[:virtual_path].to_sym

    if @args[:sequence].key? :before
      ref_name = @args[:sequence][:before]

      if self.class.all[key].key? ref_name.to_s
        return self.class.all[key][ref_name.to_s].sequence - 1
      else
        return 100
      end
    elsif @args[:sequence].key? :after
      ref_name = @args[:sequence][:after]

      if self.class.all[key].key? ref_name.to_s
        return self.class.all[key][ref_name.to_s].sequence + 1
      else
        return 100
      end
    else
      #should never happen.. tut tut!
      return 100
    end

  else
    return @args[:sequence].to_i
  end
rescue SystemStackError
  if defined?(Rails)
    Rails.logger.error "\e[1;32mDeface: [WARNING]\e[0m Circular sequence dependency includes override named: '#{self.name}' on '#{@args[:virtual_path]}'."
  end

  return 100
end
source() click to toggle source

Returns the markup to be inserted / used

# File lib/deface/override.rb, line 139
def source
  sources = Rails.application.config.deface.sources
  source = sources.find { |source| source.to_sym == source_argument }
  raise(DefaceError, "Source #{source} not found.") unless source

  source.execute(self) || ''
end
source_argument() click to toggle source

Returns a :symbol for the source argument present

# File lib/deface/override.rb, line 149
def source_argument
  Deface::DEFAULT_SOURCES.detect { |source| @args.key? source.to_sym }.try :to_sym
end
source_element() click to toggle source
# File lib/deface/override.rb, line 153
def source_element
  Deface::Parser.convert(source.clone)
end
touch() click to toggle source

Alters digest of override to force view method recompilation (when source template/partial changes)

# File lib/deface/override.rb, line 180
def touch
  @args[:updated_at] = Time.zone.now.to_f
end

Private Instance Methods

expire_compiled_template() click to toggle source

Check if method is compiled for the current virtual path.

If the compiled method does not contain the current deface digest then remove the old method - this will allow the template to be recompiled the next time it is rendered (showing the latest changes).

# File lib/deface/override.rb, line 219
def expire_compiled_template
  virtual_path = args[:virtual_path]

  method_name = Deface.template_class.instance_methods.detect do |name|
    name =~ /#{virtual_path.gsub(/[^a-z_]/, '_')}/
  end

  if method_name && method_name !~ /\A_#{self.class.digest(virtual_path: virtual_path)}_/
    Deface.template_class.send :remove_method, method_name
  end
end