Class: Deface::Override

Inherits:
Object
  • Object
show all
Extended by:
Applicator::ClassMethods, Search::ClassMethods
Includes:
OriginalValidator, TemplateHelper
Defined in:
lib/deface/override.rb

Constant Summary collapse

@@_early =
[]
@@actions =
[:remove, :replace, :replace_contents, :surround, :surround_contents, :insert_after, :insert_before, :insert_top, :insert_bottom, :set_attributes, :add_to_attributes, :remove_from_attributes]
@@sources =
[:text, :erb, :haml, :partial, :template]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Applicator::ClassMethods

apply

Methods included from Search::ClassMethods

find

Methods included from OriginalValidator

#original_source, #validate_original

Methods included from TemplateHelper

#element_source, #load_template_source

Constructor Details

#initialize(args, &content) ⇒ Override

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

Target

  • :virtual_path - The path of the template / partial where the override should take effect eg: “shared/_person”, “admin/posts/new” this will apply to all controller actions that use the specified template

Action

  • :remove - Removes all elements that match the supplied selector

  • :replace - Replaces all elements that match the supplied selector

  • :replace_contents - Replaces the contents of all elements that match the supplied selector

  • :surround - Surrounds all elements that match the supplied selector, expects replacement markup to contain <%= render_original %> placeholder

  • :surround_contents - Surrounds the contents of all elements that match the supplied selector, expects replacement markup to contain <%= render_original %> placeholder

  • :insert_after - Inserts after all elements that match the supplied selector

  • :insert_before - Inserts before all elements that match the supplied selector

  • :insert_top - Inserts inside all elements that match the supplied selector, before all existing child

  • :insert_bottom - Inserts inside all elements that match the supplied selector, after all existing child

  • :set_attributes - Sets attributes on all elements that match the supplied selector, replacing existing attribute value if present or adding if not. Expects :attributes option to be passed.

  • :add_to_attributes - Appends value to attributes on all elements that match the supplied selector, adds attribute if not present. Expects :attributes option to be passed.

  • :remove_from_attributes - Removes value from attributes on all elements that match the supplied selector. Expects :attributes option to be passed.

Source

  • :text - String containing markup

  • :partial - Relative path to partial

  • :template - Relative path to template

Optional

  • :name - Unique name for override so it can be identified and modified later. This needs to be unique within the same :virtual_path

  • :disabled - When set to true the override will not be applied.

  • :original - String containing original markup that is being overridden. If supplied Deface will log when the original markup changes, which helps highlight overrides that need attention when upgrading versions of the source application. Only really warranted for :replace overrides. NB: All whitespace is stripped before comparsion.

  • :closing_selector - A second css selector targeting an end element, allowing you to select a range of elements to apply an action against. The :closing_selector only supports the :replace, :remove and :replace_contents actions, and the end element must be a sibling of the first/starting element. Note the CSS general sibling selector (~) is used to match the first element after the opening selector.

  • :sequence - Used to order the application of an override for a specific virtual path, helpful when an override depends on another override being applied first. Supports: :sequence => n - where n is a positive or negative integer (lower numbers get applied first, default 100). :sequence => => “override_name” - where “override_name” is the name of an override defined for the

    same virutal_path, the current override will be appplied before
    the named override passed.
    

    :sequence => => “override_name”) - the current override will be applied after the named override passed.

  • :attributes - A hash containing all the attributes to be set on the matched elements, eg: :attributes => {:class => “green”, :title => “some string”

Raises:

  • (ArgumentError)


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/deface/override.rb', line 68

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

  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?

  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 (@@actions & args.keys).present?
      @args.reject!{|key, value| (@@actions & @args.keys).include? key }
    end

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

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

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

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

  expire_compiled_template

  self
end

Instance Attribute Details

#argsObject

Returns the value of attribute args.



9
10
11
# File 'lib/deface/override.rb', line 9

def args
  @args
end

Class Method Details

.allObject



207
208
209
# File 'lib/deface/override.rb', line 207

def self.all
  Rails.application.config.deface.overrides.all
end

.digest(details) ⇒ Object



211
212
213
214
215
# File 'lib/deface/override.rb', line 211

def self.digest(details)
  overrides = self.find(details)

  Digest::MD5.new.update(overrides.inject('') { |digest, override| digest << override.digest }).hexdigest
end

Instance Method Details

#actionObject



165
166
167
# File 'lib/deface/override.rb', line 165

def action
  (@@actions & @args.keys).first
end

#attributesObject



199
200
201
# File 'lib/deface/override.rb', line 199

def attributes
  @args[:attributes] || []
end

#digestObject



203
204
205
# File 'lib/deface/override.rb', line 203

def digest
  Digest::MD5.new.update(@args.to_s).hexdigest
end

#disabled?Boolean

Returns:

  • (Boolean)


190
191
192
# File 'lib/deface/override.rb', line 190

def disabled?
  @args.key?(:disabled) ? @args[:disabled] : false
end

#end_selectorObject



194
195
196
197
# File 'lib/deface/override.rb', line 194

def end_selector
  return nil if @args[:closing_selector].blank?
  "#{self.selector} ~ #{@args[:closing_selector]}"
end

#nameObject



124
125
126
# File 'lib/deface/override.rb', line 124

def name
  @args[:name]
end

#selectorObject



120
121
122
# File 'lib/deface/override.rb', line 120

def selector
  @args[self.action]
end

#sequenceObject



128
129
130
131
132
133
134
135
136
137
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
# File 'lib/deface/override.rb', line 128

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

#sourceObject



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/deface/override.rb', line 169

def source
  erb = if @args.key? :partial
    load_template_source(@args[:partial], true)
  elsif @args.key? :template
    load_template_source(@args[:template], false)
  elsif @args.key? :text
    @args[:text]
  elsif @args.key? :erb
    @args[:erb]
  elsif @args.key?(:haml) && Rails.application.config.deface.haml_support
    haml_engine = Deface::HamlConverter.new(@args[:haml])
    haml_engine.render
  end

  erb
end

#source_elementObject



186
187
188
# File 'lib/deface/override.rb', line 186

def source_element
  Deface::Parser.convert(source.clone)
end