ransack 0.5.8 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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