Module: Searchlogic::ActiveRecord::NamedScopeTools
- Included in:
- ActiveRecord::Base
- Defined in:
- lib/searchlogic/active_record/named_scope_tools.rb
Overview
Adds methods that give extra information about a classes named scopes.
Instance Method Summary collapse
-
#in_searchlogic_delegation(&block) ⇒ Object
When searchlogic calls a named_scope on a foreigh model it will execute that scope and then call scope(:find).
-
#inner_joins(association_name) ⇒ Object
A convenience method for creating inner join sql to that your inner joins are consistent with how Active Record creates them.
-
#inner_polymorphic_join(target, options = {}) ⇒ Object
A convenience methods to create a join on a polymorphic associations target.
-
#left_outer_joins(association_name) ⇒ Object
See inner_joins.
-
#named_scope_arity(name) ⇒ Object
The arity for a named scope’s proc is important, because we use the arity to determine if the condition should be ignored when calling the search method.
-
#named_scope_options(name) ⇒ Object
Retrieves the options passed when creating the respective named scope.
Instance Method Details
#in_searchlogic_delegation(&block) ⇒ Object
When searchlogic calls a named_scope on a foreigh model it will execute that scope and then call scope(:find). When we get these options we want this to be in an exclusive scope, especially if we are calling a condition on the same originating model:
Company.users_company_name_equals("name")
If we aren’t in an exclusive scope we will get unexpected results for the :joins option. Lastly, we want the named_scopes generated by searchlogic to be symbols whenever possible. The reason for this is so that we can allow ActiveRecord to leverage its joins library that automatically aliases joins if they appear more than once in a query. If the joins are strings, AtiveRecord can’t do anything. Because the code that does this in ActiveRecord is pretty bad when it comes to being consisitent, searchlogic had to fix this in Searchloigc::ActiveRecord::Consistency. That said, part of this fix is to normalize joins into strings. We do not want to do this if we are calling scopes on foreigh models. Only when we are performing an action on it. This is what the searchlogic_delegation thread variable is all about. A flag to let search logic know not to convert joins to strings.
55 56 57 58 59 60 |
# File 'lib/searchlogic/active_record/named_scope_tools.rb', line 55 def in_searchlogic_delegation(&block) old = Thread.current["searchlogic_delegation"] Thread.current["searchlogic_delegation"] = true with_exclusive_scope(&block) Thread.current["searchlogic_delegation"] = old end |
#inner_joins(association_name) ⇒ Object
A convenience method for creating inner join sql to that your inner joins are consistent with how Active Record creates them. Basically a tool for you to use when writing your own named scopes. This way you know for sure that duplicate joins will be removed when chaining scopes together that use the same join.
Also, don’t worry about breaking up the joins or retriving multiple joins. ActiveRecord will remove dupilicate joins and Searchlogic assists ActiveRecord in breaking up your joins so that they are unique.
71 72 73 |
# File 'lib/searchlogic/active_record/named_scope_tools.rb', line 71 def inner_joins(association_name) ::ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, association_name, nil).join_associations.collect { |assoc| assoc.association_join } end |
#inner_polymorphic_join(target, options = {}) ⇒ Object
A convenience methods to create a join on a polymorphic associations target. Ex:
Audit.belong_to :auditable, :polymorphic => true User.has_many :audits, :as => :auditable
Audit.inner_polymorphic_join(:user, :as => :auditable) # =>
"INNER JOINER users ON users.id = audits.auditable_id AND audits.auditable_type = 'User'"
This is used internally by searchlogic to handle accessing conditions on polymorphic associations.
85 86 87 88 89 90 91 92 93 |
# File 'lib/searchlogic/active_record/named_scope_tools.rb', line 85 def inner_polymorphic_join(target, = {}) [:on] ||= table_name [:on_table_name] ||= connection.quote_table_name([:on]) [:target_table] ||= connection.quote_table_name(target.to_s.pluralize) [:as] ||= "owner" postgres = ::ActiveRecord::Base.connection.adapter_name == "PostgreSQL" "INNER JOIN #{[:target_table]} ON #{[:target_table]}.id = #{[:on_table_name]}.#{[:as]}_id AND " + "#{[:on_table_name]}.#{[:as]}_type = #{postgres ? "E" : ""}'#{target.to_s.camelize}'" end |
#left_outer_joins(association_name) ⇒ Object
See inner_joins. Does the same thing except creates LEFT OUTER joins.
96 97 98 |
# File 'lib/searchlogic/active_record/named_scope_tools.rb', line 96 def left_outer_joins(association_name) ::ActiveRecord::Associations::ClassMethods::JoinDependency.new(self, association_name, nil).join_associations.collect { |assoc| assoc.association_join } end |
#named_scope_arity(name) ⇒ Object
The arity for a named scope’s proc is important, because we use the arity to determine if the condition should be ignored when calling the search method. If the condition is false and the arity is 0, then we skip it all together. Ex:
User.named_scope :age_is_4, :conditions => {:age => 4}
User.search(:age_is_4 => false) == User.all
User.search(:age_is_4 => true) == User.all(:conditions => {:age => 4})
We also use it when trying to “copy” the underlying named scope for association conditions. This way our aliased scope accepts the same number of parameters for the underlying scope.
36 37 38 39 |
# File 'lib/searchlogic/active_record/named_scope_tools.rb', line 36 def named_scope_arity(name) = (name) .respond_to?(:arity) ? .arity : nil end |
#named_scope_options(name) ⇒ Object
Retrieves the options passed when creating the respective named scope. Ex:
named_scope :whatever, :conditions => {:column => value}
This method will return:
:conditions => {:column => value}
ActiveRecord hides this internally in a Proc, so we have to try and pull it out with this method.
15 16 17 18 19 20 21 22 23 |
# File 'lib/searchlogic/active_record/named_scope_tools.rb', line 15 def (name) key = scopes.key?(name.to_sym) ? name.to_sym : condition_scope_name(name) if key eval("options", scopes[key].binding) else nil end end |