module SemanticallyTaggable::Taggable::Core::ClassMethods
Public Instance Methods
grouped_column_names_for(object)
click to toggle source
all column names are necessary for PostgreSQL group clause
# File lib/semantically_taggable/semantically_taggable/core.rb, line 56 def grouped_column_names_for(object) object.column_names.map { |column| "#{object.table_name}.#{column}" }.join(", ") end
initialize_semantically_taggable_core()
click to toggle source
# File lib/semantically_taggable/semantically_taggable/core.rb, line 16 def initialize_semantically_taggable_core scheme_names.map(&:to_s).each do |scheme_name| scheme = SemanticallyTaggable::Scheme.by_name(scheme_name) rescue SemanticallyTaggable::Scheme.new( :name => 'tmp', :id => 'initialization_only') singular_scheme_name = scheme_name.to_s.singularize scheme_taggings = "#{singular_scheme_name}_taggings".to_sym scheme_tags = scheme_name.to_sym class_eval do has_many scheme_taggings, :as => :taggable, :dependent => :destroy, :include => :tag, :class_name => "SemanticallyTaggable::Tagging" # TODO: revisit with dynamic join? Something not right about remembering scheme IDs at startup... has_many scheme_tags, :through => scheme_taggings, :source => :tag, :class_name => "SemanticallyTaggable::Tag", :conditions => "tags.scheme_id = #{scheme.id}" end class_eval %( def #{singular_scheme_name}_list tag_list_on('#{scheme_name}') end def #{singular_scheme_name}_list=(new_tags) set_tag_list_on('#{scheme_name}', new_tags) end def all_#{scheme_name}_list all_tags_list_on('#{scheme_name}') end ) end end
is_taggable?()
click to toggle source
# File lib/semantically_taggable/semantically_taggable/core.rb, line 157 def is_taggable? true end
semantically_taggable(*args)
click to toggle source
Calls superclass method
# File lib/semantically_taggable/semantically_taggable/core.rb, line 50 def semantically_taggable(*args) super(*args) initialize_semantically_taggable_core end
tagged_with(tags, options = {})
click to toggle source
Return a scope of objects that are tagged with the specified tags.
@param tags The tags that we want to query for @param [Hash] options A hash of options to alter you query:
* <tt>:exclude</tt> - if set to true, return objects that are *NOT* tagged with the specified tags * <tt>:any</tt> - if set to true, return objects that are tagged with *ANY* of the specified tags * <tt>:match_all</tt> - if set to true, return objects that are *ONLY* tagged with the specified tags
Example:
User.tagged_with("awesome", "cool") # Users that are tagged with awesome and cool User.tagged_with("awesome", "cool", :exclude => true) # Users that are not tagged with awesome or cool User.tagged_with("awesome", "cool", :any => true) # Users that are tagged with awesome or cool User.tagged_with("awesome", "cool", :match_all => true) # Users that are tagged with just awesome and cool
# File lib/semantically_taggable/semantically_taggable/core.rb, line 96 def tagged_with(tags, options = {}) scheme_name = options.delete(:on) raise ArgumentError, 'tagged_with requires :on' unless scheme_name scheme = SemanticallyTaggable::Scheme.by_name(scheme_name) tag_list = SemanticallyTaggable::TagList.from(tags) return {} if tag_list.empty? joins = [] conditions = [] if options.delete(:exclude) conditions << %{ #{table_name}.#{primary_key} NOT IN (#{scheme_taggings_for_these_tags(scheme, tag_list)}) } elsif options.delete(:any) conditions << %{ #{table_name}.#{primary_key} IN (#{scheme_taggings_for_these_tags(scheme, tag_list)}) } else tags = scheme.tags.named_any(tag_list) return scoped(:conditions => "1 = 0") unless tags.length == tag_list.length tags.each do |tag| safe_tag = tag.name.gsub(/[^a-zA-Z0-9]/, '') prefix = "#{safe_tag}_#{rand(1024)}" taggings_alias = "#{undecorated_table_name}_taggings_#{prefix}" tagging_join = "JOIN #{SemanticallyTaggable::Tagging.table_name} #{taggings_alias}" + " ON #{taggings_alias}.taggable_id = #{table_name}.#{primary_key}" + " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name)}" + (scheme.polyhierarchical ? " AND #{taggings_alias}.tag_id IN (SELECT #{tag.id} UNION SELECT child_tag_id FROM tag_parentages WHERE parent_tag_id = #{tag.id})" : " AND #{taggings_alias}.tag_id = #{tag.id}") joins << tagging_join end end taggings_alias = "#{undecorated_table_name}_taggings_group" if options.delete(:match_all) joins << "LEFT OUTER JOIN #{SemanticallyTaggable::Tagging.table_name} #{taggings_alias}" + " ON #{taggings_alias}.taggable_id = #{table_name}.#{primary_key}" + " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name)}" group_columns = SemanticallyTaggable::Tag.using_postgresql? ? grouped_column_names_for(self) : "#{table_name}.#{primary_key}" group = "#{group_columns} HAVING COUNT(#{taggings_alias}.taggable_id) = #{tags.size}" end scoped(:joins => joins.join(" "), :group => group, :conditions => conditions.join(" AND "), :order => options[:order], :readonly => false) end