Class: Tagtical::Tag::Type

Inherits:
String
  • Object
show all
Defined in:
lib/tagtical/tag.rb

Constant Summary collapse

BASE =

“tag” should always correspond with demodulize name of the base Tag class (ie Tagtical::Tag).

"tag".freeze
@@cache =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(str, taggable_class, options = {}) ⇒ Type

Returns a new instance of Type.



187
188
189
190
191
# File 'lib/tagtical/tag.rb', line 187

def initialize(str, taggable_class, options={})
  options.each { |k, v| instance_variable_set("@#{k}", v) }
  @taggable_class = taggable_class
  super(str)
end

Instance Attribute Details

#taggable_classObject (readonly)

Returns the value of attribute taggable_class.



185
186
187
# File 'lib/tagtical/tag.rb', line 185

def taggable_class
  @taggable_class
end

Class Method Details

.find(input, taggable_class) ⇒ Object Also known as: []



197
198
199
200
201
202
203
204
# File 'lib/tagtical/tag.rb', line 197

def find(input, taggable_class)
  case input
  when self then input
  when String, Symbol then new(sanitize(input), taggable_class)
  when Hash  then input.map { |input, klass| new(sanitize(input), taggable_class, :klass => klass) }
  when Array then input.map { |c| find(c, taggable_class) }.flatten
  end
end

.register(inputs, taggable_class) ⇒ Object

Stores the tag types in memory



208
209
210
211
212
213
# File 'lib/tagtical/tag.rb', line 208

def register(inputs, taggable_class)
  find(inputs, taggable_class).each do |tag_type|
    cache[tag_type] ||= []
    cache[tag_type] << tag_type unless cache[tag_type].include?(tag_type)
  end
end

Instance Method Details

#==(input) ⇒ Object



232
233
234
235
236
237
238
# File 'lib/tagtical/tag.rb', line 232

def ==(input)
  case input
  when self.class then comparable_array==input.comparable_array
  when String then input==self
  else false
  end
end

#active_record_sti_levelObject

Returns the level from which it extends from Tagtical::Tag



314
315
316
317
318
319
320
321
322
323
# File 'lib/tagtical/tag.rb', line 314

def active_record_sti_level
  @active_record_sti_level ||= begin
    count, current_class = 0, klass
    while !current_class.descends_from_active_record?
      current_class = current_class.superclass
      count += 1
    end
    count
  end
end

#all_tag_list_ivarObject



305
306
307
# File 'lib/tagtical/tag.rb', line 305

def all_tag_list_ivar
  tag_list_ivar(:all)
end

#base?Boolean

Returns:

  • (Boolean)


286
287
288
# File 'lib/tagtical/tag.rb', line 286

def base?
  BASE==self
end

#comparable_arrayObject



228
229
230
# File 'lib/tagtical/tag.rb', line 228

def comparable_array
  [to_s, klass]
end

#expand_tag_types(*args) ⇒ Object



325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/tagtical/tag.rb', line 325

def expand_tag_types(*args)
  scopes, options = convert_finder_type_arguments(*args)
  classes, types = [], []

  types.concat(Array(options[:types]).map { |t| taggable_class.find_tag_type!(t) }) if options[:types]

  if scopes.include?(:current)
    classes << klass
  end
  if scopes.include?(:children)
    classes.concat(klass.descendants)
  end
  if scopes.include?(:parents) # include searches up the STI chain
    parent_class = klass.superclass
    while parent_class <= Tagtical::Tag
      classes << parent_class
      parent_class = parent_class.superclass
    end
  end

  if options[:only]
    classes &= find_tag_classes_for(options[:only])
  elsif options[:except]
    except = find_tag_classes_for(options[:except])
    classes.reject! { |t| except.any? { |e| t <= e }}
  end
  tag_types_by_classes = taggable_class.tag_types.index_by(&:klass)
  types.concat(classes.map { |k| tag_types_by_classes[k] }.uniq.compact)

  types # for clarity
end

#finder_type_condition(*args) ⇒ Object

Leverages current type_condition logic from ActiveRecord while also allowing for type conditions when no Tag subclass is defined. Also, it builds the type condition for STI inheritance.

Options:

<tt>sql</tt> - Set to true to return sql string. Set to :append to return a sql string which can be appended as a condition.
<tt>only</tt> - An array of the following: :parents, :current, :children. Will construct conditions to query the current, parent, and/or children STI classes.


247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/tagtical/tag.rb', line 247

def finder_type_condition(*args)
  sql = args[-1].is_a?(Hash) && args[-1].delete(:sql)

  sti_column = Tagtical::Tag.arel_table[Tagtical::Tag.inheritance_column]
  condition = expand_tag_types(*args).map { |x| x.klass.sti_name }.inject(nil) do |conds, sti_name|
    cond = sti_column.eq(sti_name)
    conds.nil? ? cond : conds.or(cond)
  end

  if condition && sql
    condition = condition.to_sql
    condition.insert(0, " AND ") if sql==:append
  end
  condition
end

#has_many_nameObject Also known as: scope_name



290
291
292
# File 'lib/tagtical/tag.rb', line 290

def has_many_name
  pluralize.to_sym
end

#klassObject

Return the Tag subclass



282
283
284
# File 'lib/tagtical/tag.rb', line 282

def klass
  @klass ||= find_tag_class!
end

#match?(input) ⇒ Boolean

Matches the string against the type after sanitizing it.

Returns:

  • (Boolean)


224
225
226
# File 'lib/tagtical/tag.rb', line 224

def match?(input)
  self==self.class.send(:sanitize, input)
end

#scope_ivarObject



309
310
311
# File 'lib/tagtical/tag.rb', line 309

def scope_ivar
  "@#{scope_name}"
end

#scoping(*args, &block) ⇒ Object

Accepts:

scoping(:<=)
scoping(:scoping => :<=)


266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/tagtical/tag.rb', line 266

def scoping(*args, &block)
  finder_type_condition = finder_type_condition(*args)
  if block_given?
    if finder_type_condition
      Tagtical::Tag.send(:with_scope, :find => Tagtical::Tag.where(finder_type_condition), :create => {:type => klass.sti_name}) do
        Tagtical::Tag.instance_exec(&block)
      end
    else
      Tagtical::Tag.instance_exec(&block)
    end
  else
    Tagtical::Tag.send(*(finder_type_condition ? [:where, finder_type_condition] : :unscoped))
  end
end

#tag_list_ivar(*args) ⇒ Object



301
302
303
# File 'lib/tagtical/tag.rb', line 301

def tag_list_ivar(*args)
  "@#{tag_list_name(*args)}"
end

#tag_list_name(prefix = nil) ⇒ Object



295
296
297
298
299
# File 'lib/tagtical/tag.rb', line 295

def tag_list_name(prefix=nil)
  prefix = prefix.to_s.dup
  prefix << "_" unless prefix.blank?
  "#{prefix}#{self}_list"
end