diff --git a/lib/pg_search/scope_options.rb b/lib/pg_search/scope_options.rb index 5ce948c7..ad8fe3c8 100644 --- a/lib/pg_search/scope_options.rb +++ b/lib/pg_search/scope_options.rb @@ -14,14 +14,11 @@ def initialize(config) def apply(scope) scope = include_table_aliasing_for_rank(scope) - rank_table_alias = scope.pg_search_rank_table_alias(:include_counter) - - scope - .joins(rank_join(rank_table_alias)) - .order("#{rank_table_alias}.rank DESC, #{order_within_rank}") - .extend(DisableEagerLoading) - .extend(WithPgSearchRank) - .extend(WithPgSearchHighlight[feature_for(:tsearch)]) + if config.associations.any? + apply_with_inner_join(scope) + else + apply_without_inner_join(scope) + end end # workaround for https://github.com/Casecommons/pg_search/issues/14 @@ -63,6 +60,39 @@ def with_pg_search_rank scope = scope.select("#{table_name}.*") unless scope.select_values.any? scope.select("#{pg_search_rank_table_alias}.rank AS pg_search_rank") end + + def where_pg_search_rank(value) + scope = self + scope.where("#{PgSearch::Configuration.alias(table_name)}.rank#{value}") + end + end + + module WithPgSearchRankNoInnerJoin + def self.[](rank_value) + Module.new do + include WithPgSearchRankNoInnerJoin + define_method(:rank_value) { rank_value } + end + end + + def rank_field + "#{rank_value} AS pg_search_rank" + end + + def rank_value + raise TypeError.new("You need to instantiate this module with []") + end + + def with_pg_search_rank + scope = self + scope = scope.select("#{table_name}.*") unless scope.select_values.any? + scope.select(rank_field) + end + + def where_pg_search_rank(value) + scope = self + scope.where("#{rank_value}#{value}") + end end module PgSearchRankTableAliasing @@ -94,6 +124,26 @@ def pg_search_scope_application_count_plus_plus delegate :connection, :quoted_table_name, :to => :model + def apply_with_inner_join(scope) + rank_table_alias = scope.pg_search_rank_table_alias(:include_counter) + + scope + .joins(rank_join(rank_table_alias)) + .order("#{rank_table_alias}.rank DESC, #{order_within_rank}") + .extend(DisableEagerLoading) + .extend(WithPgSearchRank) + .extend(WithPgSearchHighlight[feature_for(:tsearch)]) + end + + def apply_without_inner_join(scope) + scope + .where(conditions) + .order("#{rank_order}, #{order_within_rank}") + .extend(DisableEagerLoading) + .extend(WithPgSearchRankNoInnerJoin[rank]) + .extend(WithPgSearchHighlight[feature_for(:tsearch)]) + end + def subquery model .unscoped @@ -170,6 +220,10 @@ def rank_join(rank_table_alias) "INNER JOIN (#{subquery.to_sql}) AS #{rank_table_alias} ON #{primary_key} = #{rank_table_alias}.pg_search_id" end + def rank_order + "#{rank} DESC" + end + def include_table_aliasing_for_rank(scope) if scope.included_modules.include?(PgSearchRankTableAliasing) scope diff --git a/spec/integration/pg_search_spec.rb b/spec/integration/pg_search_spec.rb index 872babb8..ccec83e3 100644 --- a/spec/integration/pg_search_spec.rb +++ b/spec/integration/pg_search_spec.rb @@ -344,7 +344,7 @@ twice = ModelWithPgSearch.create!(:content => 'foo foo') records = ModelWithPgSearch.search_content('foo') - .where("#{PgSearch::Configuration.alias(ModelWithPgSearch.table_name)}.rank > 0.07") + .where_pg_search_rank(' > 0.07') expect(records).to eq [twice] end