ransack 0.5.8 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,4 +4,7 @@ rvm:
4
4
  - ree
5
5
  - rbx
6
6
  - rbx-2.0
7
- - ruby-head
7
+ - ruby-head
8
+
9
+ env:
10
+ - RAILS=3-2-stable
data/Gemfile CHANGED
@@ -37,4 +37,4 @@ else
37
37
  gem 'activerecord'
38
38
  gem 'actionpack'
39
39
  end
40
- end
40
+ end
@@ -4,6 +4,8 @@ ActiveRecord::Base.extend Ransack::Adapters::ActiveRecord::Base
4
4
  case ActiveRecord::VERSION::STRING
5
5
  when /^3\.0\./
6
6
  require 'ransack/adapters/active_record/3.0/context'
7
+ when /^3\.1\./
8
+ require 'ransack/adapters/active_record/3.1/context'
7
9
  else
8
10
  require 'ransack/adapters/active_record/context'
9
11
  end
@@ -10,6 +10,11 @@ module Ransack
10
10
  # Because the AR::Associations namespace is insane
11
11
  JoinDependency = ::ActiveRecord::Associations::ClassMethods::JoinDependency
12
12
  JoinBase = JoinDependency::JoinBase
13
+
14
+ def initialize(object, options = {})
15
+ super
16
+ @arel_visitor = Arel::Visitors.visitor_for @engine
17
+ end
13
18
 
14
19
  def evaluate(search, opts = {})
15
20
  viz = Visitor.new
@@ -0,0 +1,163 @@
1
+ require 'ransack/context'
2
+ require 'polyamorous'
3
+
4
+ module Ransack
5
+ module Adapters
6
+ module ActiveRecord
7
+ class Context < ::Ransack::Context
8
+ # Because the AR::Associations namespace is insane
9
+ JoinDependency = ::ActiveRecord::Associations::JoinDependency
10
+ JoinPart = JoinDependency::JoinPart
11
+
12
+ def initialize(object, options = {})
13
+ super
14
+ @arel_visitor = Arel::Visitors.visitor_for @engine
15
+ end
16
+
17
+ def evaluate(search, opts = {})
18
+ viz = Visitor.new
19
+ relation = @object.except(:order).where(viz.accept(search.base)).order(viz.accept(search.sorts))
20
+ opts[:distinct] ? relation.select("DISTINCT #{@klass.quoted_table_name}.*") : relation
21
+ end
22
+
23
+ def attribute_method?(str, klass = @klass)
24
+ exists = false
25
+
26
+ if ransackable_attribute?(str, klass)
27
+ exists = true
28
+ elsif (segments = str.split(/_/)).size > 1
29
+ remainder = []
30
+ found_assoc = nil
31
+ while !found_assoc && remainder.unshift(segments.pop) && segments.size > 0 do
32
+ assoc, poly_class = unpolymorphize_association(segments.join('_'))
33
+ if found_assoc = get_association(assoc, klass)
34
+ exists = attribute_method?(remainder.join('_'), poly_class || found_assoc.klass)
35
+ end
36
+ end
37
+ end
38
+
39
+ exists
40
+ end
41
+
42
+ def table_for(parent)
43
+ parent.table
44
+ end
45
+
46
+ def klassify(obj)
47
+ if Class === obj && ::ActiveRecord::Base > obj
48
+ obj
49
+ elsif obj.respond_to? :klass
50
+ obj.klass
51
+ elsif obj.respond_to? :active_record
52
+ obj.active_record
53
+ else
54
+ raise ArgumentError, "Don't know how to klassify #{obj}"
55
+ end
56
+ end
57
+
58
+ def type_for(attr)
59
+ return nil unless attr && attr.valid?
60
+ name = attr.arel_attribute.name.to_s
61
+ table = attr.arel_attribute.relation.table_name
62
+
63
+ unless @engine.connection_pool.table_exists?(table)
64
+ raise "No table named #{table} exists"
65
+ end
66
+
67
+ @engine.connection_pool.columns_hash[table][name].type
68
+ end
69
+
70
+ private
71
+
72
+ def get_parent_and_attribute_name(str, parent = @base)
73
+ attr_name = nil
74
+
75
+ if ransackable_attribute?(str, klassify(parent))
76
+ attr_name = str
77
+ elsif (segments = str.split(/_/)).size > 1
78
+ remainder = []
79
+ found_assoc = nil
80
+ while remainder.unshift(segments.pop) && segments.size > 0 && !found_assoc do
81
+ assoc, klass = unpolymorphize_association(segments.join('_'))
82
+ if found_assoc = get_association(assoc, parent)
83
+ join = build_or_find_association(found_assoc.name, parent, klass)
84
+ parent, attr_name = get_parent_and_attribute_name(remainder.join('_'), join)
85
+ end
86
+ end
87
+ end
88
+
89
+ [parent, attr_name]
90
+ end
91
+
92
+ def get_association(str, parent = @base)
93
+ klass = klassify parent
94
+ ransackable_association?(str, klass) &&
95
+ klass.reflect_on_all_associations.detect {|a| a.name.to_s == str}
96
+ end
97
+
98
+ def join_dependency(relation)
99
+ if relation.respond_to?(:join_dependency) # Squeel will enable this
100
+ relation.join_dependency
101
+ else
102
+ build_join_dependency(relation)
103
+ end
104
+ end
105
+
106
+ def build_join_dependency(relation)
107
+ buckets = relation.joins_values.group_by do |join|
108
+ case join
109
+ when String
110
+ 'string_join'
111
+ when Hash, Symbol, Array
112
+ 'association_join'
113
+ when ::ActiveRecord::Associations::JoinDependency::JoinAssociation
114
+ 'stashed_join'
115
+ when Arel::Nodes::Join
116
+ 'join_node'
117
+ else
118
+ raise 'unknown class: %s' % join.class.name
119
+ end
120
+ end
121
+
122
+ association_joins = buckets['association_join'] || []
123
+ stashed_association_joins = buckets['stashed_join'] || []
124
+ join_nodes = buckets['join_node'] || []
125
+ string_joins = (buckets['string_join'] || []).map { |x|
126
+ x.strip
127
+ }.uniq
128
+
129
+ join_list = relation.send :custom_join_ast, relation.table.from(relation.table), string_joins
130
+
131
+ join_dependency = JoinDependency.new(
132
+ relation.klass,
133
+ association_joins,
134
+ join_list
135
+ )
136
+
137
+ join_nodes.each do |join|
138
+ join_dependency.table_aliases[join.left.name.downcase] = 1
139
+ end
140
+
141
+ join_dependency.graft(*stashed_association_joins)
142
+ end
143
+
144
+ def build_or_find_association(name, parent = @base, klass = nil)
145
+ found_association = @join_dependency.join_associations.detect do |assoc|
146
+ assoc.reflection.name == name &&
147
+ assoc.parent == parent &&
148
+ (!klass || assoc.reflection.klass == klass)
149
+ end
150
+ unless found_association
151
+ @join_dependency.send(:build, Polyamorous::Join.new(name, @join_type, klass), parent)
152
+ found_association = @join_dependency.join_associations.last
153
+ # Leverage the stashed association functionality in AR
154
+ @object = @object.joins(found_association)
155
+ end
156
+
157
+ found_association
158
+ end
159
+
160
+ end
161
+ end
162
+ end
163
+ end
@@ -1,157 +1,31 @@
1
1
  require 'ransack/context'
2
+ require 'ransack/adapters/active_record/3.1/context'
2
3
  require 'polyamorous'
3
4
 
4
5
  module Ransack
5
6
  module Adapters
6
7
  module ActiveRecord
7
8
  class Context < ::Ransack::Context
8
- # Because the AR::Associations namespace is insane
9
- JoinDependency = ::ActiveRecord::Associations::JoinDependency
10
- JoinPart = JoinDependency::JoinPart
11
-
12
- def evaluate(search, opts = {})
13
- viz = Visitor.new
14
- relation = @object.except(:order).where(viz.accept(search.base)).order(viz.accept(search.sorts))
15
- opts[:distinct] ? relation.select("DISTINCT #{@klass.quoted_table_name}.*") : relation
16
- end
17
-
18
- def attribute_method?(str, klass = @klass)
19
- exists = false
20
-
21
- if ransackable_attribute?(str, klass)
22
- exists = true
23
- elsif (segments = str.split(/_/)).size > 1
24
- remainder = []
25
- found_assoc = nil
26
- while !found_assoc && remainder.unshift(segments.pop) && segments.size > 0 do
27
- assoc, poly_class = unpolymorphize_association(segments.join('_'))
28
- if found_assoc = get_association(assoc, klass)
29
- exists = attribute_method?(remainder.join('_'), poly_class || found_assoc.klass)
30
- end
31
- end
32
- end
33
-
34
- exists
35
- end
36
-
37
- def table_for(parent)
38
- parent.table
39
- end
40
-
41
- def klassify(obj)
42
- if Class === obj && ::ActiveRecord::Base > obj
43
- obj
44
- elsif obj.respond_to? :klass
45
- obj.klass
46
- elsif obj.respond_to? :active_record
47
- obj.active_record
48
- else
49
- raise ArgumentError, "Don't know how to klassify #{obj}"
50
- end
51
- end
52
-
9
+
10
+ # Redefine a few things that have changed with 3.2.
11
+
12
+ def initialize(object, options = {})
13
+ super
14
+ @arel_visitor = @engine.connection.visitor
15
+ end
16
+
53
17
  def type_for(attr)
54
18
  return nil unless attr && attr.valid?
55
19
  name = attr.arel_attribute.name.to_s
56
20
  table = attr.arel_attribute.relation.table_name
57
21
 
58
- unless @engine.connection_pool.table_exists?(table)
22
+ unless @engine.connection.table_exists?(table)
59
23
  raise "No table named #{table} exists"
60
24
  end
61
25
 
62
- @engine.connection_pool.columns_hash[table][name].type
63
- end
64
-
65
- private
66
-
67
- def get_parent_and_attribute_name(str, parent = @base)
68
- attr_name = nil
69
-
70
- if ransackable_attribute?(str, klassify(parent))
71
- attr_name = str
72
- elsif (segments = str.split(/_/)).size > 1
73
- remainder = []
74
- found_assoc = nil
75
- while remainder.unshift(segments.pop) && segments.size > 0 && !found_assoc do
76
- assoc, klass = unpolymorphize_association(segments.join('_'))
77
- if found_assoc = get_association(assoc, parent)
78
- join = build_or_find_association(found_assoc.name, parent, klass)
79
- parent, attr_name = get_parent_and_attribute_name(remainder.join('_'), join)
80
- end
81
- end
82
- end
83
-
84
- [parent, attr_name]
26
+ @engine.connection.schema_cache.columns_hash[table][name].type
85
27
  end
86
-
87
- def get_association(str, parent = @base)
88
- klass = klassify parent
89
- ransackable_association?(str, klass) &&
90
- klass.reflect_on_all_associations.detect {|a| a.name.to_s == str}
91
- end
92
-
93
- def join_dependency(relation)
94
- if relation.respond_to?(:join_dependency) # Squeel will enable this
95
- relation.join_dependency
96
- else
97
- build_join_dependency(relation)
98
- end
99
- end
100
-
101
- def build_join_dependency(relation)
102
- buckets = relation.joins_values.group_by do |join|
103
- case join
104
- when String
105
- 'string_join'
106
- when Hash, Symbol, Array
107
- 'association_join'
108
- when ::ActiveRecord::Associations::JoinDependency::JoinAssociation
109
- 'stashed_join'
110
- when Arel::Nodes::Join
111
- 'join_node'
112
- else
113
- raise 'unknown class: %s' % join.class.name
114
- end
115
- end
116
-
117
- association_joins = buckets['association_join'] || []
118
- stashed_association_joins = buckets['stashed_join'] || []
119
- join_nodes = buckets['join_node'] || []
120
- string_joins = (buckets['string_join'] || []).map { |x|
121
- x.strip
122
- }.uniq
123
-
124
- join_list = relation.send :custom_join_ast, relation.table.from(relation.table), string_joins
125
-
126
- join_dependency = JoinDependency.new(
127
- relation.klass,
128
- association_joins,
129
- join_list
130
- )
131
-
132
- join_nodes.each do |join|
133
- join_dependency.table_aliases[join.left.name.downcase] = 1
134
- end
135
-
136
- join_dependency.graft(*stashed_association_joins)
137
- end
138
-
139
- def build_or_find_association(name, parent = @base, klass = nil)
140
- found_association = @join_dependency.join_associations.detect do |assoc|
141
- assoc.reflection.name == name &&
142
- assoc.parent == parent &&
143
- (!klass || assoc.reflection.klass == klass)
144
- end
145
- unless found_association
146
- @join_dependency.send(:build, Polyamorous::Join.new(name, @join_type, klass), parent)
147
- found_association = @join_dependency.join_associations.last
148
- # Leverage the stashed association functionality in AR
149
- @object = @object.joins(found_association)
150
- end
151
-
152
- found_association
153
- end
154
-
28
+
155
29
  end
156
30
  end
157
31
  end
@@ -34,7 +34,6 @@ module Ransack
34
34
  @join_type = options[:join_type] || Arel::OuterJoin
35
35
  @base = @join_dependency.join_base
36
36
  @engine = @base.arel_engine
37
- @arel_visitor = Arel::Visitors.visitor_for @engine
38
37
  @default_table = Arel::Table.new(@base.table_name, :as => @base.aliased_table_name, :engine => @engine)
39
38
  @bind_pairs = Hash.new do |hash, key|
40
39
  parent, attr_name = get_parent_and_attribute_name(key.to_s)
@@ -1,3 +1,3 @@
1
1
  module Ransack
2
- VERSION = "0.5.8"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -20,7 +20,13 @@ Sham.define do
20
20
  end
21
21
 
22
22
  RSpec.configure do |config|
23
- config.before(:suite) { Schema.create }
23
+ config.before(:suite) do
24
+ puts '=' * 80
25
+ puts "Running specs against ActiveRecord #{ActiveRecord::VERSION::STRING} and ARel #{Arel::VERSION}..."
26
+ puts '=' * 80
27
+ Schema.create
28
+ end
29
+
24
30
  config.before(:all) { Sham.reset(:before_all) }
25
31
  config.before(:each) { Sham.reset(:before_each) }
26
32
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ransack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.8
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-14 00:00:00.000000000 Z
12
+ date: 2012-01-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
16
- requirement: &70316894493020 !ruby/object:Gem::Requirement
16
+ requirement: &70226024755600 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70316894493020
24
+ version_requirements: *70226024755600
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: actionpack
27
- requirement: &70316894492520 !ruby/object:Gem::Requirement
27
+ requirement: &70226024754660 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '3.0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70316894492520
35
+ version_requirements: *70226024754660
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: polyamorous
38
- requirement: &70316894492020 !ruby/object:Gem::Requirement
38
+ requirement: &70226024753760 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.5.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70316894492020
46
+ version_requirements: *70226024753760
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec
49
- requirement: &70316894491540 !ruby/object:Gem::Requirement
49
+ requirement: &70226024753240 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 2.6.0
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70316894491540
57
+ version_requirements: *70226024753240
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: machinist
60
- requirement: &70316894491000 !ruby/object:Gem::Requirement
60
+ requirement: &70226024752660 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 1.0.6
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70316894491000
68
+ version_requirements: *70226024752660
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: faker
71
- requirement: &70316894490480 !ruby/object:Gem::Requirement
71
+ requirement: &70226024768120 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 0.9.5
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70316894490480
79
+ version_requirements: *70226024768120
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: sqlite3
82
- requirement: &70316894489760 !ruby/object:Gem::Requirement
82
+ requirement: &70226024767020 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: 1.3.3
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70316894489760
90
+ version_requirements: *70226024767020
91
91
  description: Ransack is the successor to the MetaSearch gem. It improves and expands
92
92
  upon MetaSearch's functionality, but does not have a 100%-compatible API.
93
93
  email:
@@ -106,6 +106,7 @@ files:
106
106
  - lib/ransack/adapters/active_record.rb
107
107
  - lib/ransack/adapters/active_record/3.0/compat.rb
108
108
  - lib/ransack/adapters/active_record/3.0/context.rb
109
+ - lib/ransack/adapters/active_record/3.1/context.rb
109
110
  - lib/ransack/adapters/active_record/base.rb
110
111
  - lib/ransack/adapters/active_record/context.rb
111
112
  - lib/ransack/configuration.rb