ransack 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,11 +1,15 @@
1
1
  source "http://rubygems.org"
2
2
  gemspec
3
3
 
4
- gem 'arel', :git => 'git://github.com/rails/arel.git'
5
- gem 'rack', :git => 'git://github.com/rack/rack.git'
6
-
7
- git 'git://github.com/rails/rails.git' do
4
+ if ENV['RAILS_VERSION'] == 'release'
8
5
  gem 'activesupport'
9
6
  gem 'activerecord'
10
7
  gem 'actionpack'
11
- end
8
+ else
9
+ gem 'arel', :git => 'git://github.com/rails/arel.git'
10
+ git 'git://github.com/rails/rails.git' do
11
+ gem 'activesupport'
12
+ gem 'activerecord'
13
+ gem 'actionpack'
14
+ end
15
+ end
data/lib/ransack.rb CHANGED
@@ -2,6 +2,8 @@ require 'ransack/configuration'
2
2
 
3
3
  module Ransack
4
4
  extend Configuration
5
+
6
+ class UntraversableAssociationError < StandardError; end;
5
7
  end
6
8
 
7
9
  Ransack.configure do |config|
@@ -19,7 +19,6 @@ module Ransack
19
19
  Ransacker.new(self, name, opts, &block)
20
20
  end
21
21
 
22
- # TODO: Let's actually do some authorization. Whitelist-only.
23
22
  def ransackable_attributes(auth_object)
24
23
  column_names + _ransackers.keys
25
24
  end
@@ -69,8 +69,7 @@ module Ransack
69
69
  found_assoc = nil
70
70
  while remainder.unshift(segments.pop) && segments.size > 0 && !found_assoc do
71
71
  assoc, klass = unpolymorphize_association(segments.join('_'))
72
- if ransackable_association?(assoc, klassify(parent))
73
- found_assoc = get_association(assoc, parent)
72
+ if found_assoc = get_association(assoc, parent)
74
73
  join = build_or_find_association(found_assoc.name, parent, klass)
75
74
  parent, attr_name = get_parent_and_attribute_name(remainder.join('_'), join)
76
75
  end
@@ -80,16 +79,10 @@ module Ransack
80
79
  [parent, attr_name]
81
80
  end
82
81
 
83
- def ransackable_attribute?(str, klass)
84
- klass.ransackable_attributes(auth_object).include? str
85
- end
86
-
87
- def ransackable_association?(str, klass)
88
- klass.ransackable_associations(auth_object).include? str
89
- end
90
-
91
82
  def get_association(str, parent = @base)
92
- klassify(parent).reflect_on_all_associations.detect {|a| a.name.to_s == str}
83
+ klass = klassify parent
84
+ ransackable_association?(str, klass) &&
85
+ klass.reflect_on_all_associations.detect {|a| a.name.to_s == str}
93
86
  end
94
87
 
95
88
  def join_dependency(relation)
@@ -74,8 +74,7 @@ module Ransack
74
74
  found_assoc = nil
75
75
  while remainder.unshift(segments.pop) && segments.size > 0 && !found_assoc do
76
76
  assoc, klass = unpolymorphize_association(segments.join('_'))
77
- if ransackable_association?(assoc, klassify(parent))
78
- found_assoc = get_association(assoc, parent)
77
+ if found_assoc = get_association(assoc, parent)
79
78
  join = build_or_find_association(found_assoc.name, parent, klass)
80
79
  parent, attr_name = get_parent_and_attribute_name(remainder.join('_'), join)
81
80
  end
@@ -85,16 +84,10 @@ module Ransack
85
84
  [parent, attr_name]
86
85
  end
87
86
 
88
- def ransackable_attribute?(str, klass)
89
- klass.ransackable_attributes(auth_object).include? str
90
- end
91
-
92
- def ransackable_association?(str, klass)
93
- klass.ransackable_associations(auth_object).include? str
94
- end
95
-
96
87
  def get_association(str, parent = @base)
97
- klassify(parent).reflect_on_all_associations.detect {|a| a.name.to_s == str}
88
+ klass = klassify parent
89
+ ransackable_association?(str, klass) &&
90
+ klass.reflect_on_all_associations.detect {|a| a.name.to_s == str}
98
91
  end
99
92
 
100
93
  def join_dependency(relation)
@@ -65,12 +65,14 @@ module Ransack
65
65
  association_parts = []
66
66
  found_assoc = nil
67
67
  while !found_assoc && segments.size > 0 && association_parts << segments.shift do
68
+ # Strip the _of_Model_type text from the association name, but hold
69
+ # onto it in klass, for use as the next base
68
70
  assoc, klass = unpolymorphize_association(association_parts.join('_'))
69
71
  if found_assoc = get_association(assoc, base)
70
72
  base = traverse(segments.join('_'), klass || found_assoc.klass)
71
73
  end
72
74
  end
73
- raise ArgumentError, "No association matches #{str}" unless found_assoc
75
+ raise UntraversableAssociationError, "No association matches #{str}" unless found_assoc
74
76
  end
75
77
 
76
78
  klassify(base)
@@ -104,9 +106,21 @@ module Ransack
104
106
  end
105
107
  end
106
108
 
109
+ def ransackable_attribute?(str, klass)
110
+ klass.ransackable_attributes(auth_object).include? str
111
+ end
112
+
113
+ def ransackable_association?(str, klass)
114
+ klass.ransackable_associations(auth_object).include? str
115
+ end
116
+
107
117
  def searchable_attributes(str = '')
108
118
  traverse(str).ransackable_attributes(auth_object)
109
119
  end
110
120
 
121
+ def searchable_associations(str = '')
122
+ traverse(str).ransackable_associations(auth_object)
123
+ end
124
+
111
125
  end
112
126
  end
@@ -22,19 +22,8 @@ module Ransack
22
22
  options[:include_blank] = true unless options.has_key?(:include_blank)
23
23
  bases = [''] + association_array(options[:associations])
24
24
  if bases.size > 1
25
- collection = bases.map do |base|
26
- [
27
- Translate.association(base, :context => object.context),
28
- object.context.searchable_attributes(base).map do |c|
29
- [
30
- attr_from_base_and_column(base, c),
31
- Translate.attribute(attr_from_base_and_column(base, c), :context => object.context)
32
- ]
33
- end
34
- ]
35
- end
36
25
  @template.grouped_collection_select(
37
- @object_name, :name, collection, :last, :first, :first, :last,
26
+ @object_name, :name, attribute_collection_for_bases(bases), :last, :first, :first, :last,
38
27
  objectify_options(options), @default_options.merge(html_options)
39
28
  )
40
29
  else
@@ -55,20 +44,9 @@ module Ransack
55
44
  raise ArgumentError, "sort_select must be called inside a search FormBuilder!" unless object.respond_to?(:context)
56
45
  options[:include_blank] = true unless options.has_key?(:include_blank)
57
46
  bases = [''] + association_array(options[:associations])
58
- if bases.any?
59
- collection = bases.map do |base|
60
- [
61
- Translate.association(base, :context => object.context),
62
- object.context.searchable_attributes(base).map do |c|
63
- [
64
- attr_from_base_and_column(base, c),
65
- Translate.attribute(attr_from_base_and_column(base, c), :context => object.context)
66
- ]
67
- end
68
- ]
69
- end
47
+ if bases.size > 1
70
48
  @template.grouped_collection_select(
71
- @object_name, :name, collection, :last, :first, :first, :last,
49
+ @object_name, :name, attribute_collection_for_bases(bases), :last, :first, :first, :last,
72
50
  objectify_options(options), @default_options.merge(html_options)
73
51
  ) + @template.collection_select(
74
52
  @object_name, :dir, [['asc', object.translate('asc')], ['desc', object.translate('desc')]], :first, :last,
@@ -159,7 +137,7 @@ module Ransack
159
137
  obj.map do |key, value|
160
138
  case value
161
139
  when Array, Hash
162
- bases_array(value, key.to_s)
140
+ association_array(value, key.to_s)
163
141
  else
164
142
  [key.to_s, [key, value].join('_')]
165
143
  end
@@ -173,6 +151,24 @@ module Ransack
173
151
  [base, column].reject {|v| v.blank?}.join('_')
174
152
  end
175
153
 
154
+ def attribute_collection_for_bases(bases)
155
+ bases.map do |base|
156
+ begin
157
+ [
158
+ Translate.association(base, :context => object.context),
159
+ object.context.searchable_attributes(base).map do |c|
160
+ [
161
+ attr_from_base_and_column(base, c),
162
+ Translate.attribute(attr_from_base_and_column(base, c), :context => object.context)
163
+ ]
164
+ end
165
+ ]
166
+ rescue UntraversableAssociationError => e
167
+ nil
168
+ end
169
+ end.compact
170
+ end
171
+
176
172
  end
177
173
  end
178
174
  end
@@ -1,3 +1,3 @@
1
1
  module Ransack
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ransack
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.1
5
+ version: 0.3.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Ernie Miller
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-18 00:00:00 Z
13
+ date: 2011-05-30 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -147,7 +147,6 @@ files:
147
147
  - spec/blueprints/tags.rb
148
148
  - spec/console.rb
149
149
  - spec/helpers/ransack_helper.rb
150
- - spec/playground.rb
151
150
  - spec/ransack/adapters/active_record/base_spec.rb
152
151
  - spec/ransack/adapters/active_record/context_spec.rb
153
152
  - spec/ransack/configuration_spec.rb
@@ -194,7 +193,6 @@ test_files:
194
193
  - spec/blueprints/tags.rb
195
194
  - spec/console.rb
196
195
  - spec/helpers/ransack_helper.rb
197
- - spec/playground.rb
198
196
  - spec/ransack/adapters/active_record/base_spec.rb
199
197
  - spec/ransack/adapters/active_record/context_spec.rb
200
198
  - spec/ransack/configuration_spec.rb
data/spec/playground.rb DELETED
@@ -1,37 +0,0 @@
1
- $VERBOSE = false
2
- require 'bundler'
3
- Bundler.setup
4
- require 'machinist/active_record'
5
- require 'sham'
6
- require 'faker'
7
-
8
- Dir[File.expand_path('../../spec/{helpers,support,blueprints}/*.rb', __FILE__)].each do |f|
9
- require f
10
- end
11
-
12
- Sham.define do
13
- name { Faker::Name.name }
14
- title { Faker::Lorem.sentence }
15
- body { Faker::Lorem.paragraph }
16
- salary {|index| 30000 + (index * 1000)}
17
- tag_name { Faker::Lorem.words(3).join(' ') }
18
- note { Faker::Lorem.words(7).join(' ') }
19
- end
20
-
21
- Schema.create
22
-
23
- require 'ransack'
24
-
25
- Article.joins{person.comments}.where{person.comments.body =~ '%hello%'}.to_sql
26
- # => "SELECT \"articles\".* FROM \"articles\" INNER JOIN \"people\" ON \"people\".\"id\" = \"articles\".\"person_id\" INNER JOIN \"comments\" ON \"comments\".\"person_id\" = \"people\".\"id\" WHERE \"comments\".\"body\" LIKE '%hello%'"
27
-
28
- Person.where{(id + 1) == 2}.first
29
- # => #<Person id: 1, parent_id: nil, name: "Aric Smith", salary: 31000>
30
-
31
- Person.where{(salary - 40000) < 0}.to_sql
32
- # => "SELECT \"people\".* FROM \"people\" WHERE \"people\".\"salary\" - 40000 < 0"
33
-
34
- p = Person.select{[id, name, salary, (salary + 1000).as('salary_after_increase')]}.first
35
- # => #<Person id: 1, name: "Aric Smith", salary: 31000>
36
-
37
- p.salary_after_increase # =>