Code cleanup
This commit is contained in:
parent
81e9406c6d
commit
1e24b60906
|
@ -132,9 +132,15 @@ module Arel
|
|||
end
|
||||
|
||||
def visit_Arel_Nodes_NamedFunction o
|
||||
"#{o.name}(#{o.distinct ? 'DISTINCT ' : ''}#{o.expressions.map { |x|
|
||||
visit x
|
||||
}.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}"
|
||||
"#{
|
||||
o.name
|
||||
}(#{
|
||||
o.distinct ? 'DISTINCT ' : ''
|
||||
}#{
|
||||
o.expressions.map { |x| visit x }.join(', ')
|
||||
})#{
|
||||
o.alias ? " AS #{visit o.alias}" : ''
|
||||
}"
|
||||
end
|
||||
|
||||
def visit_Arel_Nodes_And o
|
||||
|
@ -146,13 +152,17 @@ module Arel
|
|||
end
|
||||
|
||||
def visit_Arel_Nodes_Values o
|
||||
"VALUES (#{o.expressions.zip(o.columns).map { |value, attr|
|
||||
"VALUES (#{
|
||||
o.expressions.zip(o.columns)
|
||||
.map { |value, attr|
|
||||
if Nodes::SqlLiteral === value
|
||||
visit_Arel_Nodes_SqlLiteral value
|
||||
else
|
||||
quote(value, attr && column_for(attr))
|
||||
end
|
||||
}.join ', '})"
|
||||
}
|
||||
.join ', '
|
||||
})"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,9 +26,11 @@ module Ransack
|
|||
viz = Visitor.new
|
||||
relation = @object.where(viz.accept(search.base))
|
||||
if search.sorts.any?
|
||||
relation = relation.except(:order).reorder(viz.accept(search.sorts))
|
||||
relation = relation.except(:order)
|
||||
.reorder(viz.accept(search.sorts))
|
||||
end
|
||||
opts[:distinct] ? relation.select("DISTINCT #{@klass.quoted_table_name}.*") : relation
|
||||
opts[:distinct] ?
|
||||
relation.select("DISTINCT #{@klass.quoted_table_name}.*") : relation
|
||||
end
|
||||
|
||||
def attribute_method?(str, klass = @klass)
|
||||
|
@ -39,10 +41,15 @@ module Ransack
|
|||
elsif (segments = str.split(/_/)).size > 1
|
||||
remainder = []
|
||||
found_assoc = nil
|
||||
while !found_assoc && remainder.unshift(segments.pop) && segments.size > 0 do
|
||||
assoc, poly_class = unpolymorphize_association(segments.join('_'))
|
||||
while !found_assoc && remainder.unshift(segments.pop) &&
|
||||
segments.size > 0 do
|
||||
assoc, poly_class = unpolymorphize_association(
|
||||
segments.join('_')
|
||||
)
|
||||
if found_assoc = get_association(assoc, klass)
|
||||
exists = attribute_method?(remainder.join('_'), poly_class || found_assoc.klass)
|
||||
exists = attribute_method?(
|
||||
remainder.join('_'), poly_class || found_assoc.klass
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -56,7 +63,9 @@ module Ransack
|
|||
|
||||
def type_for(attr)
|
||||
return nil unless attr && attr.valid?
|
||||
klassify(attr.parent).columns_hash[attr.arel_attribute.name.to_s].type
|
||||
klassify(attr.parent)
|
||||
.columns_hash[attr.arel_attribute.name.to_s]
|
||||
.type
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -69,15 +78,19 @@ module Ransack
|
|||
elsif (segments = str.split(/_/)).size > 1
|
||||
remainder = []
|
||||
found_assoc = nil
|
||||
while remainder.unshift(segments.pop) && segments.size > 0 && !found_assoc do
|
||||
while remainder.unshift(segments.pop) && segments.size > 0 &&
|
||||
!found_assoc do
|
||||
assoc, klass = unpolymorphize_association(segments.join('_'))
|
||||
if found_assoc = get_association(assoc, parent)
|
||||
join = build_or_find_association(found_assoc.name, parent, klass)
|
||||
parent, attr_name = get_parent_and_attribute_name(remainder.join('_'), join)
|
||||
join = build_or_find_association(
|
||||
found_assoc.name, parent, klass
|
||||
)
|
||||
parent, attr_name = get_parent_and_attribute_name(
|
||||
remainder.join('_'), join
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
[parent, attr_name]
|
||||
end
|
||||
|
||||
|
@ -114,9 +127,9 @@ module Ransack
|
|||
association_joins = buckets['association_join'] || []
|
||||
stashed_association_joins = buckets['stashed_join'] || []
|
||||
join_nodes = buckets['join_node'] || []
|
||||
string_joins = (buckets['string_join'] || []).map { |x|
|
||||
x.strip
|
||||
}.uniq
|
||||
string_joins = (buckets['string_join'] || [])
|
||||
.map { |x| x.strip }
|
||||
.uniq
|
||||
|
||||
join_list = relation.send :custom_join_sql, (string_joins + join_nodes)
|
||||
|
||||
|
@ -134,13 +147,16 @@ module Ransack
|
|||
end
|
||||
|
||||
def build_or_find_association(name, parent = @base, klass = nil)
|
||||
found_association = @join_dependency.join_associations.detect do |assoc|
|
||||
found_association = @join_dependency.join_associations
|
||||
.detect do |assoc|
|
||||
assoc.reflection.name == name &&
|
||||
assoc.parent == parent &&
|
||||
(!klass || assoc.reflection.klass == klass)
|
||||
end
|
||||
unless found_association
|
||||
@join_dependency.send(:build, Polyamorous::Join.new(name, @join_type, klass), parent)
|
||||
@join_dependency.send(
|
||||
:build, Polyamorous::Join.new(name, @join_type, klass), parent
|
||||
)
|
||||
found_association = @join_dependency.join_associations.last
|
||||
# Leverage the stashed association functionality in AR
|
||||
@object = @object.joins(found_association)
|
||||
|
|
|
@ -47,7 +47,8 @@ module Ransack
|
|||
|
||||
it 'can be accessed through associations' do
|
||||
s = Person.search(:children_reversed_name_eq => 'htimS cirA')
|
||||
s.result.to_sql.should match /#{quote_table_name("children_people")}.#{quote_column_name("name")} = 'Aric Smith'/
|
||||
s.result.to_sql.should match /#{quote_table_name("children_people")
|
||||
}.#{quote_column_name("name")} = 'Aric Smith'/
|
||||
end
|
||||
|
||||
it 'allows an "attribute" to be an InfixOperation' do
|
||||
|
@ -78,43 +79,62 @@ module Ransack
|
|||
end
|
||||
|
||||
it 'allows sort by "only_sort" field' do
|
||||
s = Person.search("s"=>{"0"=>{"dir"=>"asc", "name"=>"only_sort"}})
|
||||
s.result.to_sql.should match /ORDER BY #{quote_table_name("people")}.#{quote_column_name("only_sort")} ASC/
|
||||
s = Person.search(
|
||||
"s" => { "0"=> { "dir" => "asc", "name" => "only_sort" } }
|
||||
)
|
||||
s.result.to_sql.should match /ORDER BY #{quote_table_name("people")
|
||||
}.#{quote_column_name("only_sort")} ASC/
|
||||
end
|
||||
|
||||
it "doesn't sort by 'only_search' field" do
|
||||
s = Person.search("s"=>{"0"=>{"dir"=>"asc", "name"=>"only_search"}})
|
||||
s.result.to_sql.should_not match /ORDER BY #{quote_table_name("people")}.#{quote_column_name("only_search")} ASC/
|
||||
s = Person.search(
|
||||
"s" => { "0" => { "dir" => "asc", "name" => "only_search" } }
|
||||
)
|
||||
s.result.to_sql.should_not match /ORDER BY #{quote_table_name("people")
|
||||
}.#{quote_column_name("only_search")} ASC/
|
||||
end
|
||||
|
||||
it 'allows search by "only_search" field' do
|
||||
s = Person.search(:only_search_eq => 'htimS cirA')
|
||||
s.result.to_sql.should match /WHERE #{quote_table_name("people")}.#{quote_column_name("only_search")} = 'htimS cirA'/
|
||||
s.result.to_sql.should match /WHERE #{quote_table_name("people")
|
||||
}.#{quote_column_name("only_search")} = 'htimS cirA'/
|
||||
end
|
||||
|
||||
it "can't be searched by 'only_sort'" do
|
||||
s = Person.search(:only_sort_eq => 'htimS cirA')
|
||||
s.result.to_sql.should_not match /WHERE #{quote_table_name("people")}.#{quote_column_name("only_sort")} = 'htimS cirA'/
|
||||
s.result.to_sql.should_not match /WHERE #{quote_table_name("people")
|
||||
}.#{quote_column_name("only_sort")} = 'htimS cirA'/
|
||||
end
|
||||
|
||||
it 'allows sort by "only_admin" field, if auth_object: :admin' do
|
||||
s = Person.search({"s"=>{"0"=>{"dir"=>"asc", "name"=>"only_admin"}}}, {auth_object: :admin})
|
||||
s.result.to_sql.should match /ORDER BY #{quote_table_name("people")}.#{quote_column_name("only_admin")} ASC/
|
||||
s = Person.search(
|
||||
{ "s" => { "0" => { "dir" => "asc", "name" => "only_admin" } } },
|
||||
{ auth_object: :admin }
|
||||
)
|
||||
s.result.to_sql.should match /ORDER BY #{quote_table_name("people")
|
||||
}.#{quote_column_name("only_admin")} ASC/
|
||||
end
|
||||
|
||||
it "doesn't sort by 'only_admin' field, if auth_object: nil" do
|
||||
s = Person.search("s"=>{"0"=>{"dir"=>"asc", "name"=>"only_admin"}})
|
||||
s.result.to_sql.should_not match /ORDER BY #{quote_table_name("people")}.#{quote_column_name("only_admin")} ASC/
|
||||
s = Person.search(
|
||||
"s" => { "0" => { "dir" => "asc", "name" => "only_admin" } }
|
||||
)
|
||||
s.result.to_sql.should_not match /ORDER BY
|
||||
#{quote_table_name("people")}.#{quote_column_name("only_admin")} ASC/
|
||||
end
|
||||
|
||||
it 'allows search by "only_admin" field, if auth_object: :admin' do
|
||||
s = Person.search({:only_admin_eq => 'htimS cirA'}, {auth_object: :admin})
|
||||
s.result.to_sql.should match /WHERE #{quote_table_name("people")}.#{quote_column_name("only_admin")} = 'htimS cirA'/
|
||||
s = Person.search(
|
||||
{ :only_admin_eq => 'htimS cirA'}, { auth_object: :admin }
|
||||
)
|
||||
s.result.to_sql.should match /WHERE #{quote_table_name("people")
|
||||
}.#{quote_column_name("only_admin")} = 'htimS cirA'/
|
||||
end
|
||||
|
||||
it "can't be searched by 'only_admin', if auth_object: nil" do
|
||||
s = Person.search(:only_admin_eq => 'htimS cirA')
|
||||
s.result.to_sql.should_not match /WHERE #{quote_table_name("people")}.#{quote_column_name("only_admin")} = 'htimS cirA'/
|
||||
s.result.to_sql.should_not match /WHERE #{quote_table_name("people")
|
||||
}.#{quote_column_name("only_admin")} = 'htimS cirA'/
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@ module Ransack
|
|||
result = subject.evaluate(search)
|
||||
|
||||
result.should be_an ::ActiveRecord::Relation
|
||||
result.to_sql.should match /#{quote_column_name("name")} = 'Joe Blow'/
|
||||
result.to_sql.should match /#{
|
||||
quote_column_name("name")} = 'Joe Blow'/
|
||||
end
|
||||
|
||||
it 'SELECTs DISTINCT when :distinct => true' do
|
||||
|
|
|
@ -20,12 +20,17 @@ module Ransack
|
|||
|
||||
it 'avoids creating compound predicates if :compounds => false' do
|
||||
Ransack.configure do |config|
|
||||
config.add_predicate :test_predicate_without_compound, :compounds => false
|
||||
config.add_predicate(
|
||||
:test_predicate_without_compound,
|
||||
:compounds => false
|
||||
)
|
||||
end
|
||||
|
||||
Ransack.predicates.should have_key 'test_predicate_without_compound'
|
||||
Ransack.predicates.should_not have_key 'test_predicate_without_compound_any'
|
||||
Ransack.predicates.should_not have_key 'test_predicate_without_compound_all'
|
||||
Ransack.predicates
|
||||
.should have_key 'test_predicate_without_compound'
|
||||
Ransack.predicates
|
||||
.should_not have_key 'test_predicate_without_compound_any'
|
||||
Ransack.predicates
|
||||
.should_not have_key 'test_predicate_without_compound_all'
|
||||
end
|
||||
|
||||
it 'should have default value for search key' do
|
||||
|
@ -48,7 +53,11 @@ module Ransack
|
|||
|
||||
it 'adds predicates that take arrays, overriding compounds' do
|
||||
Ransack.configure do |config|
|
||||
config.add_predicate :test_array_predicate, :wants_array => true, :compounds => true
|
||||
config.add_predicate(
|
||||
:test_array_predicate,
|
||||
:wants_array => true,
|
||||
:compounds => true
|
||||
)
|
||||
end
|
||||
|
||||
Ransack.predicates['test_array_predicate'].wants_array.should eq true
|
||||
|
|
|
@ -91,8 +91,8 @@ module Ransack
|
|||
end
|
||||
|
||||
it 'returns ransackable attributes for associations with :associations' do
|
||||
attributes = Person.ransackable_attributes + Article.
|
||||
ransackable_attributes.map { |a| "articles_#{a}" }
|
||||
attributes = Person.ransackable_attributes +
|
||||
Article.ransackable_attributes.map { |a| "articles_#{a}" }
|
||||
html = @f.attribute_select(:associations => ['articles'])
|
||||
html.split(/\n/).should have(attributes.size).lines
|
||||
attributes.each do |attribute|
|
||||
|
|
|
@ -22,14 +22,17 @@ module Ransack
|
|||
describe 'eq' do
|
||||
it 'generates an equality condition for boolean true' do
|
||||
@s.awesome_eq = true
|
||||
field = "#{quote_table_name("people")}.#{quote_column_name("awesome")}"
|
||||
@s.result.to_sql.should match /#{field} = #{ActiveRecord::Base.connection.quoted_true}/
|
||||
field = "#{quote_table_name("people")}.#{
|
||||
quote_column_name("awesome")}"
|
||||
@s.result.to_sql.should match /#{field} = #{
|
||||
ActiveRecord::Base.connection.quoted_true}/
|
||||
end
|
||||
|
||||
it 'generates an equality condition for boolean false' do
|
||||
@s.awesome_eq = false
|
||||
field = "#{quote_table_name("people")}.#{quote_column_name("awesome")}"
|
||||
@s.result.to_sql.should match /#{field} = #{ActiveRecord::Base.connection.quoted_false}/
|
||||
@s.result.to_sql.should match /#{field} = #{
|
||||
ActiveRecord::Base.connection.quoted_false}/
|
||||
end
|
||||
|
||||
it 'does not generate a condition for nil' do
|
||||
|
|
|
@ -34,8 +34,8 @@ module Ransack
|
|||
it 'creates Conditions for multiple polymorphic belongs_to association attributes' do
|
||||
search = Search.new(Note,
|
||||
:notable_of_Person_type_name_or_notable_of_Article_type_title_eq => 'Ernie')
|
||||
condition = search.
|
||||
base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
|
||||
condition = search
|
||||
.base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
|
||||
condition.should be_a Nodes::Condition
|
||||
condition.predicate.name.should eq 'eq'
|
||||
condition.attributes.first.name.should eq 'notable_of_Person_type_name'
|
||||
|
@ -68,8 +68,16 @@ module Ransack
|
|||
it 'accepts "attributes" hashes for groupings' do
|
||||
search = Search.new(Person,
|
||||
:g => {
|
||||
'0' => { :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' },
|
||||
'1' => { :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert' },
|
||||
'0' => {
|
||||
:m => 'or',
|
||||
:name_eq => 'Ernie',
|
||||
:children_name_eq => 'Ernie'
|
||||
},
|
||||
'1' => {
|
||||
:m => 'or',
|
||||
:name_eq => 'Bert',
|
||||
:children_name_eq => 'Bert'
|
||||
},
|
||||
}
|
||||
)
|
||||
ors = search.groupings
|
||||
|
@ -85,16 +93,14 @@ module Ransack
|
|||
search = Search.new(Person,
|
||||
:c => {
|
||||
'0' => { :a => ['name'], :p => 'eq', :v => ['Ernie'] },
|
||||
'1' => {
|
||||
:a => ['children_name', 'parent_name'],
|
||||
:p => 'eq', :v => ['Ernie'], :m => 'or'
|
||||
}
|
||||
}
|
||||
'1' => { :a => ['children_name', 'parent_name'],
|
||||
:p => 'eq', :v => ['Ernie'], :m => 'or' }
|
||||
}
|
||||
)
|
||||
conditions = search.base.conditions
|
||||
conditions.should have(2).items
|
||||
conditions.map { |c| c.class }.
|
||||
should eq [Nodes::Condition, Nodes::Condition]
|
||||
conditions.map { |c| c.class }
|
||||
.should eq [Nodes::Condition, Nodes::Condition]
|
||||
end
|
||||
|
||||
it 'creates Conditions for custom predicates that take arrays' do
|
||||
|
@ -117,8 +123,12 @@ module Ransack
|
|||
end
|
||||
|
||||
describe '#result' do
|
||||
let(:people_name_field) { "#{quote_table_name("people")}.#{quote_column_name("name")}" }
|
||||
let(:children_people_name_field) { "#{quote_table_name("children_people")}.#{quote_column_name("name")}" }
|
||||
let(:people_name_field) {
|
||||
"#{quote_table_name("people")}.#{quote_column_name("name")}"
|
||||
}
|
||||
let(:children_people_name_field) {
|
||||
"#{quote_table_name("children_people")}.#{quote_column_name("name")}"
|
||||
}
|
||||
it 'evaluates conditions contextually' do
|
||||
search = Search.new(Person, :children_name_eq => 'Ernie')
|
||||
search.result.should be_an ActiveRecord::Relation
|
||||
|
@ -130,7 +140,8 @@ module Ransack
|
|||
search = Search.new(Person, :children_name_or_name_eq => 'Ernie')
|
||||
search.result.should be_an ActiveRecord::Relation
|
||||
where = search.result.where_values.first
|
||||
where.to_sql.should match /#{children_people_name_field} = 'Ernie' OR #{people_name_field} = 'Ernie'/
|
||||
where.to_sql.should match /#{children_people_name_field
|
||||
} = 'Ernie' OR #{people_name_field} = 'Ernie'/
|
||||
end
|
||||
|
||||
it 'evaluates polymorphic belongs_to association conditions contextually' do
|
||||
|
@ -153,7 +164,8 @@ module Ransack
|
|||
where = search.result.where_values.first
|
||||
where.to_sql.should match /#{children_people_name_field} = 'Ernie'/
|
||||
where.to_sql.should match /#{people_name_field} = 'Ernie'/
|
||||
where.to_sql.should match /#{quote_table_name("children_people_2")}.#{quote_column_name("name")} = 'Ernie'/
|
||||
where.to_sql.should match /#{quote_table_name("children_people_2")
|
||||
}.#{quote_column_name("name")} = 'Ernie'/
|
||||
end
|
||||
|
||||
it 'evaluates arrays of groupings' do
|
||||
|
@ -324,7 +336,9 @@ module Ransack
|
|||
end
|
||||
|
||||
it 'allows chaining to access nested conditions' do
|
||||
@s.groupings = [{ :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' }]
|
||||
@s.groupings = [
|
||||
{ :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie' }
|
||||
]
|
||||
@s.groupings.first.children_name_eq.should eq 'Ernie'
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue