Module: MakeTaggable::Taggable::Collection::ClassMethods
- Defined in:
- lib/make_taggable/taggable/collection.rb
Overview
Added to every taggable model.
Instance Method Summary collapse
-
#all_tag_counts(options = {}) ⇒ ActiveRecord::Relation
Every tag applied to this model, each carrying how often it was used as a
countattribute. -
#all_tags(options = {}) ⇒ ActiveRecord::Relation
Every tag applied to this model, without counting them.
-
#initialize_make_taggable_collection ⇒ void
Defines the counting methods for each context.
-
#make_taggable(*args) ⇒ void
Adds contexts and refreshes the counting methods.
-
#safe_to_sql(relation) ⇒ String
private
A relation's SQL with its bind parameters inlined, so it can be embedded in another query.
-
#tag_counts_on(context, options = {}) ⇒ ActiveRecord::Relation
Tags used in one context, each carrying how often it was used.
-
#tags_on(context, options = {}) ⇒ ActiveRecord::Relation
Tags used in one context, without counting them.
Instance Method Details
#all_tag_counts(options = {}) ⇒ ActiveRecord::Relation
Every tag applied to this model, each carrying how often it was used as a count attribute.
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/make_taggable/taggable/collection.rb', line 144 def all_tag_counts( = {}) = .dup .assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit, :on, :id ## Generate conditions: [:conditions] = sanitize_sql([:conditions]) if [:conditions] ## Generate scope: tagging_scope = MakeTaggable::Tagging.select( "#{MakeTaggable::Tagging.table_name}.tag_id, COUNT(#{MakeTaggable::Tagging.table_name}.tag_id) AS tags_count, #{last_applied_at_projection}" ) tag_scope = MakeTaggable.tag_model.select("#{MakeTaggable::Tag.table_name}.*, #{MakeTaggable::Tagging.table_name}.tags_count AS count").order([:order]).limit([:limit]) # Current model is STI descendant, so add type checking to the join condition unless descends_from_active_record? taggable_join = "INNER JOIN #{table_name} ON #{table_name}.#{primary_key} = #{MakeTaggable::Tagging.table_name}.taggable_id" taggable_join += sanitize_sql([" AND #{table_name}.#{inheritance_column} = ?", name]) tagging_scope = tagging_scope.joins(taggable_join) end # Conditions tagging_conditions().each { |condition| tagging_scope = tagging_scope.where(condition) } tag_scope = tag_scope.where([:conditions]) # GROUP BY and HAVING clauses: having = ["COUNT(#{MakeTaggable::Tagging.table_name}.tag_id) > 0"] having.push sanitize_sql(["COUNT(#{MakeTaggable::Tagging.table_name}.tag_id) >= ?", .delete(:at_least)]) if [:at_least] having.push sanitize_sql(["COUNT(#{MakeTaggable::Tagging.table_name}.tag_id) <= ?", .delete(:at_most)]) if [:at_most] having = having.compact.join(" AND ") group_columns = "#{MakeTaggable::Tagging.table_name}.tag_id" unless [:id] # Append the current scope to the scope, because we can't use scope(:find) in RoR 3.0 anymore: tagging_scope = generate_tagging_scope_in_clause(tagging_scope, table_name, primary_key) end tagging_scope = tagging_scope.group(group_columns).having(having) tag_scope_joins(tag_scope, tagging_scope) end |
#all_tags(options = {}) ⇒ ActiveRecord::Relation
Every tag applied to this model, without counting them.
Cheaper than #all_tag_counts, which has to join the taggables.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/make_taggable/taggable/collection.rb', line 102 def ( = {}) = .dup .assert_valid_keys :start_at, :end_at, :conditions, :order, :limit, :on ## Generate conditions: [:conditions] = sanitize_sql([:conditions]) if [:conditions] ## Generate scope: tagging_scope = MakeTaggable::Tagging.select( "#{MakeTaggable::Tagging.table_name}.tag_id, #{last_applied_at_projection}" ) tag_scope = MakeTaggable.tag_model.select("#{MakeTaggable::Tag.table_name}.*").order([:order]).limit([:limit]) # Joins and conditions tagging_conditions().each { |condition| tagging_scope = tagging_scope.where(condition) } tag_scope = tag_scope.where([:conditions]) group_columns = "#{MakeTaggable::Tagging.table_name}.tag_id" # Append the current scope to the scope, because we can't use scope(:find) in RoR 3.0 anymore: tagging_scope = generate_tagging_scope_in_clause(tagging_scope, table_name, primary_key).group(group_columns) tag_scope_joins(tag_scope, tagging_scope) end |
#initialize_make_taggable_collection ⇒ void
This method returns an undefined value.
Defines the counting methods for each context.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/make_taggable/taggable/collection.rb', line 30 def initialize_make_taggable_collection tag_types.map(&:to_s).each do |tag_type| class_eval <<-RUBY, __FILE__, __LINE__ + 1 def self.#{tag_type.singularize}_counts(options={}) tag_counts_on('#{tag_type}', options) end def #{tag_type.singularize}_counts(options = {}) tag_counts_on('#{tag_type}', options) end def top_#{tag_type}(limit = 10) tag_counts_on('#{tag_type}', order: 'count desc', limit: limit.to_i) end def self.top_#{tag_type}(limit = 10) tag_counts_on('#{tag_type}', order: 'count desc', limit: limit.to_i) end RUBY end end |
#make_taggable(*args) ⇒ void
This method returns an undefined value.
Adds contexts and refreshes the counting methods.
58 59 60 61 |
# File 'lib/make_taggable/taggable/collection.rb', line 58 def make_taggable(*args) super initialize_make_taggable_collection end |
#safe_to_sql(relation) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
A relation's SQL with its bind parameters inlined, so it can be embedded in another query.
194 195 196 |
# File 'lib/make_taggable/taggable/collection.rb', line 194 def safe_to_sql(relation) connection.unprepared_statement { relation.to_sql } end |
#tag_counts_on(context, options = {}) ⇒ ActiveRecord::Relation
Tags used in one context, each carrying how often it was used.
73 74 75 |
# File 'lib/make_taggable/taggable/collection.rb', line 73 def tag_counts_on(context, = {}) all_tag_counts(.merge({on: context.to_s})) end |
#tags_on(context, options = {}) ⇒ ActiveRecord::Relation
Tags used in one context, without counting them.
84 85 86 |
# File 'lib/make_taggable/taggable/collection.rb', line 84 def (context, = {}) (.merge({on: context.to_s})) end |