Module: Tagtical::Taggable::Core::InstanceMethods

Defined in:
lib/tagtical/taggable/core.rb

Instance Method Summary collapse

Instance Method Details

#all_tags_list_on(context, *args) ⇒ Object



279
280
281
# File 'lib/tagtical/taggable/core.rb', line 279

def all_tags_list_on(context, *args)
  tag_list_cache_on(context, :all)[expand_tag_types(context, *args)] ||= Tagtical::TagList.new(all_tags_on(context, *args)).freeze
end

#all_tags_on(context, *args) ⇒ Object

Returns all tags of a given context



285
286
287
288
289
290
291
292
293
294
# File 'lib/tagtical/taggable/core.rb', line 285

def all_tags_on(context, *args)
  scope = tag_scope(context, *args)
  if Tagtical::Tag.using_postgresql?
    group_columns = grouped_column_names_for(Tagtical::Tag)
    scope = scope.order("max(#{Tagtical::Tagging.table_name}.created_at)").group(group_columns)
  else
    scope = scope.group("#{Tagtical::Tag.table_name}.#{Tagtical::Tag.primary_key}")
  end
  scope.all
end

#cached_tag_list_on(context) ⇒ Object



253
254
255
# File 'lib/tagtical/taggable/core.rb', line 253

def cached_tag_list_on(context)
  self[find_tag_type!(context).tag_list_name(:cached)]
end

#grouped_column_names_for(object) ⇒ Object

all column names are necessary for PostgreSQL group clause



245
246
247
# File 'lib/tagtical/taggable/core.rb', line 245

def grouped_column_names_for(object)
  self.class.grouped_column_names_for(object)
end

#is_taggable?Boolean

Returns:

  • (Boolean)


249
250
251
# File 'lib/tagtical/taggable/core.rb', line 249

def is_taggable?
  self.class.is_taggable?
end

#reloadObject



307
308
309
310
# File 'lib/tagtical/taggable/core.rb', line 307

def reload(*)
  remove_tag_caches_on(tag_types)
  super
end

#save_tagsObject



312
313
314
315
316
317
318
319
320
321
322
323
324
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
356
357
358
359
360
# File 'lib/tagtical/taggable/core.rb', line 312

def save_tags
  # Do the classes from top to bottom. We want the list from "tag" to run before "sub_tag" runs.
  # Otherwise, we will end up removing taggings from "sub_tag" since they aren't on "tag'.
  tag_types.sort_by(&:active_record_sti_level).each do |tag_type|
    (tag_list_cache_on(tag_type) || {}).each do |expanded_tag_types, tag_list|
      # Tag list saving only runs if its affecting the current scope or the current and children scope
      # next unless [:<=, :==].any? { |scope| scopes_for_tag_list(tag_type, scope)==scopes }
      next unless expanded_tag_types.include?(tag_type)
      tag_list = tag_list.uniq

      # Find existing tags or create non-existing tags:
      tag_value_lookup = tag_type.klass.find_or_create_tags(tag_list, expanded_tag_types)
      tags = tag_value_lookup.keys


      current_tags = tags_on(tag_type, :types => expanded_tag_types, :scope => :parents) # add in the parents because we need them later on down.
      old_tags     = current_tags - tags
      new_tags     = tags         - current_tags

      unowned_taggings = taggings.where(:tagger_id => nil)

      # If relevances are specified on current tags, make sure to update those
      tags_requiring_relevance_update = tag_value_lookup.map { |tag, value| tag if !value.relevance.nil? }.compact & current_tags
      if tags_requiring_relevance_update.present? && (update_taggings = unowned_taggings.find_all_by_tag_id(tags_requiring_relevance_update)).present?
        update_taggings.each { |tagging| tagging.update_attribute(:relevance, tag_value_lookup[tagging.tag].relevance) }
      end

      # Find and remove old taggings:
      if old_tags.present? && (old_taggings = unowned_taggings.find_all_by_tag_id(old_tags)).present?
        old_taggings.reject! do |tagging|
          if tagging.tag.class > tag_type.klass # parent of current tag type/class, make sure not to remove these taggings.
            update_tagging_with_inherited_tag!(tagging, new_tags, tag_value_lookup)
            true
          end
        end
        Tagtical::Tagging.destroy_all :id => old_taggings.map(&:id) # Destroy old taggings:
      end

      new_tags.each do |tag|
        taggings.create!(:tag => tag, :taggable => self, :relevance => tag_value_lookup[tag].relevance) # Create new taggings:
      end
    end

    # Force tag lists to reload to integrate any new tags from inheritance.
    remove_tag_caches_on(tag_type)
  end

  true
end

#set_tag_list_on(context, new_list, *args) ⇒ Object

model.set_tag_list_on(“skill”, [“kung fu”, “karate”]) # will overwrite tags from inheriting tag classes model.set_tag_list_on(“skill”, [“kung fu”, “karate”], :scope => :==) # will not overwrite tags from inheriting tag classes



260
261
262
263
264
# File 'lib/tagtical/taggable/core.rb', line 260

def set_tag_list_on(context, new_list, *args)
  tag_list = Tagtical::TagList.from(new_list)
  cascade_set_tag_list!(tag_list, context, *args) if args[-1].is_a?(Hash) && args[-1].delete(:cascade)
  tag_list_cache_on(context)[expand_tag_types(context, *args)] = tag_list
end

#short_tags(options = {}) ⇒ Object

Returns flat list of tag classes and tag values.

taggable.update_attributes!(gender_list: "boy, girl", skill_list: "ruby")
taggable.short_tags                   # => %w(gender_boy gender_girl skill_ruby tag_boy tag_girl tag_ruby)
taggable.short_tags(only: :gender)    # => %w(gender_boy gender_girl)
taggable.short_tags(exclude: :gender) # => %w(skill_ruby tag_boy tag_girl tag_ruby)


368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/tagtical/taggable/core.rb', line 368

def short_tags(options = {})
  tag_types = if options[:only].present?
    self.class.tag_types.select { |tt| Array.wrap(options[:only]).map(&:to_s).include?(tt) }
  else
    self.class.tag_types - Array.wrap(options[:exclude]).compact.map(&:to_s)
  end
  tag_types.map do |tag_type|
    send(tag_type.has_many_name).map do |tag|
      "#{tag_type}_#{tag.value}"
    end
  end.flatten.to_a
end

#tag_list_cache_on(context, prefix = nil) ⇒ Object



274
275
276
277
# File 'lib/tagtical/taggable/core.rb', line 274

def tag_list_cache_on(context, prefix=nil)
  variable = find_tag_type!(context).tag_list_ivar(prefix)
  instance_variable_get(variable) || instance_variable_set(variable, {})
end

#tag_list_on(context, *args) ⇒ Object



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

def tag_list_on(context, *args)
  tag_list_cache_on(context)[expand_tag_types(context, *args)] ||= Tagtical::TagList.new(tags_on(context, *args))
end

#tag_list_on?(context, *args) ⇒ Boolean

Returns:

  • (Boolean)


266
267
268
# File 'lib/tagtical/taggable/core.rb', line 266

def tag_list_on?(context, *args)
  !tag_list_cache_on(context)[expand_tag_types(context, *args)].nil?
end

#tags_on(context, *args) ⇒ Object

Returns all tags that aren’t owned.



298
299
300
301
302
303
304
305
# File 'lib/tagtical/taggable/core.rb', line 298

def tags_on(context, *args)
  scope = tag_scope(context, *args)
  if args.empty?
    scope.reject(&:has_tagger?)
  else
    scope.where("#{Tagtical::Tagging.table_name}.tagger_id IS NULL").all
  end
end