Skip to content

Commit

Permalink
Add support for attribute alias.
Browse files Browse the repository at this point in the history
  • Loading branch information
martndemus authored and jonatack committed Sep 25, 2015
1 parent c9d2297 commit 549342a
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 10 deletions.
7 changes: 7 additions & 0 deletions lib/ransack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
module Ransack
extend Configuration
class UntraversableAssociationError < StandardError; end;

SUPPORTS_ATTRIBUTE_ALIAS =
begin
ActiveRecord::Base.respond_to?(:attribute_aliases)
rescue NameError
false
end
end

Ransack.configure do |config|
Expand Down
6 changes: 5 additions & 1 deletion lib/ransack/adapters/active_record/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ def ransacker(name, opts = {}, &block)
# For overriding with a whitelist array of strings.
#
def ransackable_attributes(auth_object = nil)
column_names + _ransackers.keys
if Ransack::SUPPORTS_ATTRIBUTE_ALIAS
column_names + _ransackers.keys + attribute_aliases.keys
else
column_names + _ransackers.keys
end
end

# Ransackable_associations, by default, returns the names
Expand Down
24 changes: 18 additions & 6 deletions lib/ransack/nodes/bindable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,26 @@ def reset_binding!

private

def get_arel_attribute
if ransacker
ransacker.attr_from(self)
else
context.table_for(parent)[attr_name]
end
def get_arel_attribute
if ransacker
ransacker.attr_from(self)
else
get_attribute
end
end

def get_attribute
if is_alias_attribute?
context.table_for(parent)[context.klass.attribute_aliases[attr_name]]
else
context.table_for(parent)[attr_name]
end
end

def is_alias_attribute?
Ransack::SUPPORTS_ATTRIBUTE_ALIAS &&
context.klass.attribute_aliases.key?(attr_name)
end
end
end
end
12 changes: 12 additions & 0 deletions spec/ransack/adapters/active_record/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,14 @@ def self.simple_escaping?
expect(s.result.to_a).to eq [p]
end

it "should translate attribute aliased column names",
:if => Ransack::SUPPORTS_ATTRIBUTE_ALIAS do
s = Person.ransack(:full_name_eq => 'Nicolas Cage')
expect(s.result.to_sql).to match(
/WHERE #{quote_table_name("people")}.#{quote_column_name("name")}/
)
end

it 'allows sort by "only_sort" field' do
s = Person.ransack(
"s" => { "0" => { "dir" => "asc", "name" => "only_sort" } }
Expand Down Expand Up @@ -382,6 +390,10 @@ def self.simple_escaping?
it { should include 'only_search' }
it { should_not include 'only_sort' }
it { should_not include 'only_admin' }

if Ransack::SUPPORTS_ATTRIBUTE_ALIAS
it { should include 'full_name' }
end
end

context 'with auth_object :admin' do
Expand Down
11 changes: 11 additions & 0 deletions spec/ransack/search_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,17 @@ module Ransack
expect(condition.value).to eq 'Ernie'
end


it 'creates conditions for aliased attributes',
:if => Ransack::SUPPORTS_ATTRIBUTE_ALIAS do
search = Search.new(Person, full_name_eq: 'Ernie')
condition = search.base[:full_name_eq]
expect(condition).to be_a Nodes::Condition
expect(condition.predicate.name).to eq 'eq'
expect(condition.attributes.first.name).to eq 'full_name'
expect(condition.value).to eq 'Ernie'
end

it 'preserves default scope and conditions for associations' do
search = Search.new(Person, published_articles_title_eq: 'Test')
expect(search.result.to_sql).to include 'default_scope'
Expand Down
7 changes: 4 additions & 3 deletions spec/support/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class Person < ActiveRecord::Base
of_age ? where("age >= ?", 18) : where("age < ?", 18)
}

alias_attribute :full_name, :name

ransacker :reversed_name, :formatter => proc { |v| v.reverse } do |parent|
parent.table[:name]
end
Expand Down Expand Up @@ -89,9 +91,9 @@ class Person < ActiveRecord::Base

def self.ransackable_attributes(auth_object = nil)
if auth_object == :admin
column_names + _ransackers.keys - ['only_sort']
super - ['only_sort']
else
column_names + _ransackers.keys - ['only_sort', 'only_admin']
super - ['only_sort', 'only_admin']
end
end

Expand All @@ -102,7 +104,6 @@ def self.ransortable_attributes(auth_object = nil)
column_names + _ransackers.keys - ['only_search', 'only_admin']
end
end

end

class Article < ActiveRecord::Base
Expand Down

1 comment on commit 549342a

@jonatack
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixes issue #589, closes PR #592.

Please sign in to comment.