Add Rails 4 compatibility to master

This commit is contained in:
jonatack 2013-08-06 19:00:52 +02:00
parent fc5fbcf8b4
commit 5a522b4f4a
10 changed files with 103 additions and 46 deletions

View File

@ -1,11 +1,11 @@
source "http://rubygems.org"
source "https://rubygems.org"
gemspec
gem 'rake'
rails = ENV['RAILS'] || '3-2-stable'
rails = ENV['RAILS'] || '4-0-stable'
gem 'arel', '3.0.2'
gem 'arel'
case rails
when /\// # A path

View File

@ -7,6 +7,8 @@ when /^3\.0\./
require 'ransack/adapters/active_record/3.0/context'
when /^3\.1\./
require 'ransack/adapters/active_record/3.1/context'
when /^3\.2\./
require 'ransack/adapters/active_record/3.2/context'
else
require 'ransack/adapters/active_record/context'
end

View File

@ -10,12 +10,18 @@ module Ransack
# Because the AR::Associations namespace is insane
JoinDependency = ::ActiveRecord::Associations::ClassMethods::JoinDependency
JoinBase = JoinDependency::JoinBase
# Redefine a few things for ActiveRecord 3.0.
def initialize(object, options = {})
super
@arel_visitor = Arel::Visitors.visitor_for @engine
end
def relation_for(object)
object.scoped
end
def evaluate(search, opts = {})
viz = Visitor.new
relation = @object.where(viz.accept(search.base))
@ -48,18 +54,6 @@ module Ransack
parent.table
end
def klassify(obj)
if Class === obj && ::ActiveRecord::Base > obj
obj
elsif obj.respond_to? :klass
obj.klass
elsif obj.respond_to? :active_record
obj.active_record
else
raise ArgumentError, "Don't know how to klassify #{obj}"
end
end
def type_for(attr)
return nil unless attr && attr.valid?
klassify(attr.parent).columns_hash[attr.arel_attribute.name.to_s].type

View File

@ -1,4 +1,5 @@
require 'ransack/context'
require 'ransack/adapters/active_record/compat'
require 'polyamorous'
module Ransack
@ -8,12 +9,18 @@ module Ransack
# Because the AR::Associations namespace is insane
JoinDependency = ::ActiveRecord::Associations::JoinDependency
JoinPart = JoinDependency::JoinPart
# Redefine a few things for ActiveRecord 3.1.
def initialize(object, options = {})
super
@arel_visitor = Arel::Visitors.visitor_for @engine
end
def relation_for(object)
object.scoped
end
def evaluate(search, opts = {})
viz = Visitor.new
relation = @object.where(viz.accept(search.base))
@ -46,18 +53,6 @@ module Ransack
parent.table
end
def klassify(obj)
if Class === obj && ::ActiveRecord::Base > obj
obj
elsif obj.respond_to? :klass
obj.klass
elsif obj.respond_to? :active_record
obj.active_record
else
raise ArgumentError, "Don't know how to klassify #{obj}"
end
end
def type_for(attr)
return nil unless attr && attr.valid?
name = attr.arel_attribute.name.to_s

View File

@ -0,0 +1,44 @@
require 'ransack/context'
require 'ransack/adapters/active_record/3.1/context'
require 'ransack/adapters/active_record/compat'
require 'polyamorous'
module Ransack
module Adapters
module ActiveRecord
class Context < ::Ransack::Context
# Redefine a few things for ActiveRecord 3.2.
def initialize(object, options = {})
super
@arel_visitor = @engine.connection.visitor
end
def relation_for(object)
object.scoped
end
def type_for(attr)
return nil unless attr && attr.valid?
name = attr.arel_attribute.name.to_s
table = attr.arel_attribute.relation.table_name
schema_cache = @engine.connection.schema_cache
raise "No table named #{table} exists" unless schema_cache.table_exists?(table)
schema_cache.columns_hash[table][name].type
end
def evaluate(search, opts = {})
viz = Visitor.new
relation = @object.where(viz.accept(search.base))
if search.sorts.any?
relation = relation.except(:order).reorder(viz.accept(search.sorts))
end
opts[:distinct] ? relation.uniq : relation
end
end
end
end
end

View File

@ -1,5 +1,5 @@
require 'ransack/context'
require 'ransack/adapters/active_record/3.1/context'
require 'ransack/adapters/active_record/3.2/context'
require 'ransack/adapters/active_record/compat'
require 'polyamorous'
@ -8,21 +8,23 @@ module Ransack
module ActiveRecord
class Context < ::Ransack::Context
# Redefine a few things that have changed with 3.2.
def initialize(object, options = {})
super
@arel_visitor = @engine.connection.visitor
end
def relation_for(object)
object.all
end
def type_for(attr)
return nil unless attr && attr.valid?
name = attr.arel_attribute.name.to_s
table = attr.arel_attribute.relation.table_name
schema_cache = @engine.connection.schema_cache
raise "No table named #{table} exists" unless schema_cache.table_exists?(table)
schema_cache.columns_hash[table][name].type
schema_cache = @engine.connection.schema_cache
raise "No table named #{table} exists" unless schema_cache.table_exists?(table)
schema_cache.columns_hash(table)[name].type
end
def evaluate(search, opts = {})
@ -31,7 +33,7 @@ module Ransack
if search.sorts.any?
relation = relation.except(:order).reorder(viz.accept(search.sorts))
end
opts[:distinct] ? relation.uniq : relation
opts[:distinct] ? relation.distinct : relation
end
end

View File

@ -28,7 +28,7 @@ module Ransack
end
def initialize(object, options = {})
@object = object.scoped
@object = relation_for(object)
@klass = @object.klass
@join_dependency = join_dependency(@object)
@join_type = options[:join_type] || Arel::OuterJoin
@ -44,6 +44,20 @@ module Ransack
end
end
def klassify(obj)
if Class === obj && ::ActiveRecord::Base > obj
obj
elsif obj.respond_to? :klass
obj.klass
elsif obj.respond_to? :active_record # Rails 3
obj.active_record
elsif obj.respond_to? :base_klass # Rails 4
obj.base_klass
else
raise ArgumentError, "Don't know how to klassify #{obj}"
end
end
# Convert a string representing a chain of associations and an attribute
# into the attribute itself
def contextualize(str)

View File

@ -23,7 +23,7 @@ module Ransack
attribute_names = attributes_str.split(/_and_|_or_/)
combinator = attributes_str.match(/_and_/) ? :and : :or
defaults = base_ancestors.map do |klass|
:"ransack.attributes.#{klass.model_name.underscore}.#{original_name}"
:"ransack.attributes.#{klass.model_name.singular}.#{original_name}"
end
translated_names = attribute_names.map do |attr|
@ -50,7 +50,7 @@ module Ransack
raise ArgumentError, "A context is required to translate associations"
end
defaults = key.blank? ? [:"#{context.klass.i18n_scope}.models.#{context.klass.model_name.underscore}"] : [:"ransack.associations.#{context.klass.model_name.underscore}.#{key}"]
defaults = key.blank? ? [:"#{context.klass.i18n_scope}.models.#{context.klass.model_name.singular}"] : [:"ransack.associations.#{context.klass.model_name.singular}.#{key}"]
defaults << context.traverse(key).model_name.human
options = {:count => 1, :default => defaults}
I18n.translate(defaults.shift, options)
@ -65,20 +65,20 @@ module Ransack
interpolations = {}
interpolations[:attr_fallback_name] = I18n.translate(
(associated_class ?
:"ransack.attributes.#{associated_class.model_name.underscore}.#{attr_name}" :
:"ransack.attributes.#{context.klass.model_name.underscore}.#{attr_name}"
:"ransack.attributes.#{associated_class.model_name.singular}.#{attr_name}" :
:"ransack.attributes.#{context.klass.model_name.singular}.#{attr_name}"
),
:default => [
(associated_class ?
:"#{associated_class.i18n_scope}.attributes.#{associated_class.model_name.underscore}.#{attr_name}" :
:"#{context.klass.i18n_scope}.attributes.#{context.klass.model_name.underscore}.#{attr_name}"
:"#{associated_class.i18n_scope}.attributes.#{associated_class.model_name.singular}.#{attr_name}" :
:"#{context.klass.i18n_scope}.attributes.#{context.klass.model_name.singular}.#{attr_name}"
),
:".attributes.#{attr_name}",
attr_name.humanize
]
)
defaults = [
:"ransack.attributes.#{context.klass.model_name.underscore}.#{name}"
:"ransack.attributes.#{context.klass.model_name.singular}.#{name}"
]
if include_associations && associated_class
defaults << '%{association_name} %{attr_fallback_name}'

View File

@ -14,8 +14,8 @@ Gem::Specification.new do |s|
s.rubyforge_project = "ransack"
s.add_dependency 'activerecord', '~> 3.0'
s.add_dependency 'actionpack', '~> 3.0'
s.add_dependency 'activerecord', '>= 3.0'
s.add_dependency 'actionpack', '>= 3.0'
s.add_dependency 'polyamorous', '~> 0.6.0'
s.add_development_dependency 'rspec', '~> 2.8.0'
s.add_development_dependency 'machinist', '~> 1.0.6'

View File

@ -6,6 +6,12 @@ module Ransack
describe Context do
subject { Context.new(Person) }
describe '#relation_for' do
it 'returns relation for given object' do
subject.object.should be_an ::ActiveRecord::Relation
end
end
describe '#evaluate' do
it 'evaluates search obects' do
search = Search.new(Person, :name_eq => 'Joe Blow')