Class: Tagtical::Tag::Type

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

Defined Under Namespace

Classes: Collection

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.



229
230
231
232
233
# File 'lib/tagtical/tag.rb', line 229

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.



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

def taggable_class
  @taggable_class
end

Class Method Details

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



239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/tagtical/tag.rb', line 239

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

.register(inputs, taggable_class) ⇒ Object

Stores the tag types in memory



254
255
256
257
258
259
# File 'lib/tagtical/tag.rb', line 254

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



278
279
280
281
282
283
284
# File 'lib/tagtical/tag.rb', line 278

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



362
363
364
365
366
367
368
369
370
371
# File 'lib/tagtical/tag.rb', line 362

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



353
354
355
# File 'lib/tagtical/tag.rb', line 353

def all_tag_list_ivar
  tag_list_ivar(:all)
end

#base?Boolean

Returns:

  • (Boolean)


334
335
336
# File 'lib/tagtical/tag.rb', line 334

def base?
  BASE==self
end

#comparable_arrayObject



274
275
276
# File 'lib/tagtical/tag.rb', line 274

def comparable_array
  [to_s, klass]
end

#expand_tag_types(*args) ⇒ Object



373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/tagtical/tag.rb', line 373

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)
    taggable_class.eager_load_tag_classes
    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.


293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'lib/tagtical/tag.rb', line 293

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]
  sti_names = expand_tag_types(*args).map { |x| x.klass.sti_name }

  condition = sti_column.eq(sti_names.delete(nil)) if sti_names.include?(nil)
  sti_names_condition = sti_column.in(sti_names)
  condition = condition ? condition.or(sti_names_condition) : sti_names_condition
  
  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



338
339
340
# File 'lib/tagtical/tag.rb', line 338

def has_many_name
  pluralize.to_sym
end

#klassObject

Return the Tag subclass



330
331
332
# File 'lib/tagtical/tag.rb', line 330

def klass
  @klass ||= find_tag_class!
end

#match?(input) ⇒ Boolean

Matches the string against the type after sanitizing it.

Returns:

  • (Boolean)


270
271
272
# File 'lib/tagtical/tag.rb', line 270

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

#scope_ivarObject



357
358
359
# File 'lib/tagtical/tag.rb', line 357

def scope_ivar
  "@#{scope_name}"
end

#scoping(*args, &block) ⇒ Object

Accepts:

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


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

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



349
350
351
# File 'lib/tagtical/tag.rb', line 349

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

#tag_list_name(prefix = nil) ⇒ Object



343
344
345
346
347
# File 'lib/tagtical/tag.rb', line 343

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