ansr 0.0.1 → 0.0.3

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.
Files changed (83) hide show
  1. checksums.yaml +15 -0
  2. data/README.md +35 -0
  3. data/ansr.gemspec +2 -1
  4. data/ansr_blacklight/Gemfile +3 -0
  5. data/ansr_blacklight/README.md +37 -0
  6. data/ansr_blacklight/ansr_blacklight.gemspec +28 -0
  7. data/ansr_blacklight/lib/ansr_blacklight.rb +57 -0
  8. data/ansr_blacklight/lib/ansr_blacklight/arel.rb +6 -0
  9. data/ansr_blacklight/lib/ansr_blacklight/arel/big_table.rb +57 -0
  10. data/ansr_blacklight/lib/ansr_blacklight/arel/visitors.rb +6 -0
  11. data/ansr_blacklight/lib/ansr_blacklight/arel/visitors/query_builder.rb +217 -0
  12. data/ansr_blacklight/lib/ansr_blacklight/arel/visitors/to_no_sql.rb +14 -0
  13. data/ansr_blacklight/lib/ansr_blacklight/base.rb +21 -0
  14. data/ansr_blacklight/lib/ansr_blacklight/connection_adapters/no_sql_adapter.rb +38 -0
  15. data/ansr_blacklight/lib/ansr_blacklight/model/querying.rb +29 -0
  16. data/ansr_blacklight/lib/ansr_blacklight/relation.rb +50 -0
  17. data/ansr_blacklight/lib/ansr_blacklight/relation/solr_projection_methods.rb +55 -0
  18. data/ansr_blacklight/lib/ansr_blacklight/request_builders.rb +141 -0
  19. data/ansr_blacklight/lib/ansr_blacklight/solr.rb +4 -0
  20. data/ansr_blacklight/lib/ansr_blacklight/solr/request.rb +46 -0
  21. data/ansr_blacklight/lib/ansr_blacklight/solr/response.rb +94 -0
  22. data/ansr_blacklight/lib/ansr_blacklight/solr/response/group.rb +32 -0
  23. data/ansr_blacklight/lib/ansr_blacklight/solr/response/group_response.rb +50 -0
  24. data/ansr_blacklight/lib/ansr_blacklight/solr/response/more_like_this.rb +14 -0
  25. data/ansr_blacklight/lib/ansr_blacklight/solr/response/pagination_methods.rb +35 -0
  26. data/ansr_blacklight/lib/ansr_blacklight/solr/response/spelling.rb +92 -0
  27. data/ansr_blacklight/spec/fixtures/config.yml +0 -0
  28. data/ansr_blacklight/spec/lib/loaded_relation_spec.rb +223 -0
  29. data/ansr_blacklight/spec/lib/queryable_relation_spec.rb +133 -0
  30. data/ansr_blacklight/spec/lib/relation/faceting_spec.rb +475 -0
  31. data/ansr_blacklight/spec/lib/relation/grouping_spec.rb +159 -0
  32. data/ansr_blacklight/spec/spec_helper.rb +72 -0
  33. data/ansr_dpla/Gemfile +3 -0
  34. data/ansr_dpla/Gemfile.lock +138 -0
  35. data/ansr_dpla/README.md +2 -2
  36. data/ansr_dpla/ansr_dpla.gemspec +2 -2
  37. data/ansr_dpla/lib/ansr_dpla.rb +3 -0
  38. data/ansr_dpla/lib/ansr_dpla/api.rb +3 -3
  39. data/ansr_dpla/lib/ansr_dpla/arel.rb +1 -2
  40. data/ansr_dpla/lib/ansr_dpla/arel/big_table.rb +4 -0
  41. data/ansr_dpla/lib/ansr_dpla/arel/visitors.rb +6 -0
  42. data/ansr_dpla/lib/ansr_dpla/arel/visitors/query_builder.rb +188 -0
  43. data/ansr_dpla/lib/ansr_dpla/arel/visitors/to_no_sql.rb +9 -0
  44. data/ansr_dpla/lib/ansr_dpla/connection_adapters/no_sql_adapter.rb +58 -0
  45. data/ansr_dpla/lib/ansr_dpla/model/base.rb +7 -0
  46. data/ansr_dpla/lib/ansr_dpla/model/querying.rb +6 -10
  47. data/ansr_dpla/lib/ansr_dpla/relation.rb +61 -0
  48. data/ansr_dpla/lib/ansr_dpla/request.rb +5 -0
  49. data/ansr_dpla/spec/lib/api_spec.rb +8 -5
  50. data/ansr_dpla/spec/lib/item_spec.rb +2 -2
  51. data/ansr_dpla/spec/lib/relation/facet_spec.rb +27 -19
  52. data/ansr_dpla/spec/lib/relation/select_spec.rb +10 -8
  53. data/ansr_dpla/spec/lib/relation/where_spec.rb +1 -1
  54. data/ansr_dpla/spec/lib/relation_spec.rb +31 -29
  55. data/ansr_dpla/test/system.rb +4 -2
  56. data/lib/ansr.rb +7 -0
  57. data/lib/ansr/arel.rb +3 -0
  58. data/lib/ansr/arel/big_table.rb +43 -3
  59. data/lib/ansr/arel/configured_field.rb +19 -0
  60. data/lib/ansr/arel/nodes.rb +41 -0
  61. data/lib/ansr/arel/visitors.rb +7 -0
  62. data/lib/ansr/arel/visitors/context.rb +13 -0
  63. data/lib/ansr/arel/visitors/query_builder.rb +47 -0
  64. data/lib/ansr/arel/visitors/to_no_sql.rb +41 -0
  65. data/lib/ansr/base.rb +29 -1
  66. data/lib/ansr/configurable.rb +6 -12
  67. data/lib/ansr/connection_adapters.rb +5 -0
  68. data/lib/ansr/connection_adapters/no_sql_adapter.rb +80 -0
  69. data/lib/ansr/dummy_associations.rb +105 -0
  70. data/lib/ansr/facets.rb +103 -0
  71. data/lib/ansr/model.rb +17 -107
  72. data/lib/ansr/model/connection_handler.rb +6 -0
  73. data/lib/ansr/relation.rb +40 -23
  74. data/lib/ansr/relation/group.rb +31 -0
  75. data/lib/ansr/relation/predicate_builder.rb +106 -0
  76. data/lib/ansr/relation/query_methods.rb +192 -45
  77. data/lib/ansr/sanitization.rb +5 -18
  78. data/lib/ansr/utils.rb +89 -0
  79. data/lib/ansr/version.rb +1 -1
  80. metadata +73 -25
  81. data/ansr_dpla/lib/ansr_dpla/arel/connection.rb +0 -81
  82. data/ansr_dpla/lib/ansr_dpla/arel/query_builder.rb +0 -131
  83. data/lib/ansr/model/connection.rb +0 -103
@@ -6,14 +6,16 @@ describe Ansr::Relation do
6
6
  @faceted = read_fixture('kittens_faceted.jsonld')
7
7
  @empty = read_fixture('empty.jsonld')
8
8
  @mock_api = double('api')
9
- Item.config({:api_key => :foo})
9
+ Item.config{ |x| x[:api_key] = :foo}
10
10
  Item.engine.api= @mock_api
11
11
  end
12
12
 
13
+ subject { Ansr::Dpla::Relation.new(Item, Item.table) }
14
+
13
15
  describe '#select' do
14
16
  describe 'with a block given' do
15
17
  it "should build an array" do
16
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
18
+ test = subject.where(q:'kittens')
17
19
  @mock_api.should_receive(:items).with(:q => 'kittens').and_return(@kittens)
18
20
  actual = test.select {|d| true}
19
21
  expect(actual).to be_a(Array)
@@ -25,22 +27,22 @@ describe Ansr::Relation do
25
27
  end
26
28
  describe 'with a String or Symbol key given' do
27
29
  it 'should change the requested document fields' do
28
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
29
- @mock_api.should_receive(:items).with(:q => 'kittens', :fields=>'name').and_return('')
30
+ test = subject.where(q:'kittens')
31
+ @mock_api.should_receive(:items).with(:q => 'kittens', :fields=>:name).and_return('')
30
32
  test = test.select('name')
31
33
  test.load
32
34
  end
33
35
  end
34
36
  describe 'with a list of keys' do
35
37
  it "should add all the requested document fields" do
36
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
37
- @mock_api.should_receive(:items).with(:q => 'kittens', :fields=>'name,foo').and_return('')
38
+ test = subject.where(q:'kittens')
39
+ @mock_api.should_receive(:items).with(:q => 'kittens', :fields=>[:name,:foo]).and_return('')
38
40
  test = test.select(['name','foo'])
39
41
  test.load
40
42
  end
41
43
  it "should add all the requested document fields and proxy them" do
42
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
43
- @mock_api.should_receive(:items).with(:q => 'kittens', :fields=>'object').and_return(@kittens)
44
+ test = subject.where(q:'kittens')
45
+ @mock_api.should_receive(:items).with(:q => 'kittens', :fields=>:object).and_return(@kittens)
44
46
  test = test.select('object AS my_object')
45
47
  test.load
46
48
  expect(test.to_a.first['object']).to be_nil
@@ -6,7 +6,7 @@ describe Ansr::Relation do
6
6
  @faceted = read_fixture('kittens_faceted.jsonld')
7
7
  @empty = read_fixture('empty.jsonld')
8
8
  @mock_api = double('api')
9
- Item.config({:api_key => :foo})
9
+ Item.config{ |x| x[:api_key] = :foo}
10
10
  Item.engine.api= @mock_api
11
11
  end
12
12
  describe '#where' do
@@ -1,15 +1,17 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Ansr::Relation do
3
+ describe Ansr::Dpla::Relation do
4
4
  before do
5
5
  @kittens = read_fixture('kittens.jsonld')
6
6
  @faceted = read_fixture('kittens_faceted.jsonld')
7
7
  @empty = read_fixture('empty.jsonld')
8
8
  @mock_api = double('api')
9
- Item.config({:api_key => :foo})
9
+ Item.config {|x| x[:api_key] = :foo }
10
10
  Item.engine.api= @mock_api
11
11
  end
12
12
 
13
+ subject { Ansr::Dpla::Relation.new(Item, Item.table) }
14
+
13
15
  describe "#initialize" do
14
16
  it "should identify the correct resource for the model" do
15
17
  class Foo
@@ -18,21 +20,21 @@ describe Ansr::Relation do
18
20
  end
19
21
  end
20
22
 
21
- test = Ansr::Relation.new(Foo, Foo.table)
23
+ test = Ansr::Dpla::Relation.new(Foo, Foo.table)
22
24
  expect(test.resource).to eql(:foos)
23
25
  end
24
26
  end
25
27
 
26
28
  describe ".load" do
27
29
  it "should fetch the appropriate REST resource" do
28
- test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens')
30
+ test = subject.where(:q=>'kittens')
29
31
  @mock_api.should_receive(:items).with(:q => 'kittens').and_return('')
30
32
  test.load
31
33
  end
32
34
 
33
35
  describe "Relation attributes" do
34
36
  it "should set attributes correctly from a response" do
35
- test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens')
37
+ test = subject.where(:q=>'kittens')
36
38
  @mock_api.stub(:items).and_return(@kittens)
37
39
  test.load
38
40
  expect(test.count).to eql(144)
@@ -41,7 +43,7 @@ describe Ansr::Relation do
41
43
  end
42
44
 
43
45
  it "should set attributes correctly for an empty response" do
44
- test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens')
46
+ test = subject.where(:q=>'kittens')
45
47
  @mock_api.stub(:items).and_return(@empty)
46
48
  test.load
47
49
  expect(test.count).to eql(0)
@@ -62,21 +64,21 @@ describe Ansr::Relation do
62
64
  describe '.order' do
63
65
  describe 'with symbol parms' do
64
66
  it "should add sort clause to query" do
65
- test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens').order(:foo)
67
+ test = subject.where(:q=>'kittens').order(:foo)
66
68
  expect(test).to be_a(Ansr::Relation)
67
69
  @mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo).and_return('')
68
70
  test.load
69
71
  end
70
72
 
71
73
  it "should add multiple sort clauses to query" do
72
- test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens').order(:foo).order(:bar)
74
+ test = subject.where(:q=>'kittens').order(:foo).order(:bar)
73
75
  expect(test).to be_a(Ansr::Relation)
74
76
  @mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>[:foo,:bar]).and_return('')
75
77
  test.load
76
78
  end
77
79
 
78
80
  it "should sort in descending order if necessary" do
79
- test = Ansr::Relation.new(Item, Item.table).where(:q=>'kittens').order(:foo => :desc)
81
+ test = subject.where(:q=>'kittens').order(:foo => :desc)
80
82
  expect(test).to be_a(Ansr::Relation)
81
83
  @mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo, :sort_order=>:desc).and_return('')
82
84
  test.load
@@ -84,14 +86,14 @@ describe Ansr::Relation do
84
86
  end
85
87
  describe 'with String parms' do
86
88
  it "should add sort clause to query" do
87
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo")
89
+ test = subject.where(q:'kittens').order("foo")
88
90
  expect(test).to be_a(Ansr::Relation)
89
91
  @mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo).and_return('')
90
92
  test.load
91
93
  end
92
94
 
93
95
  it "should sort in descending order if necessary" do
94
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo DESC")
96
+ test = subject.where(q:'kittens').order("foo DESC")
95
97
  expect(test).to be_a(Ansr::Relation)
96
98
  @mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo, :sort_order=>:desc).and_return('')
97
99
  test.load
@@ -101,7 +103,7 @@ describe Ansr::Relation do
101
103
 
102
104
  describe '#reorder' do
103
105
  it "should replace existing order" do
104
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo DESC")
106
+ test = subject.where(q:'kittens').order("foo DESC")
105
107
  test = test.reorder("foo ASC")
106
108
  expect(test).to be_a(Ansr::Relation)
107
109
  @mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo).and_return('')
@@ -111,7 +113,7 @@ describe Ansr::Relation do
111
113
 
112
114
  describe '#reverse_order' do
113
115
  it "should replace existing DESC order" do
114
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo DESC")
116
+ test = subject.where(q:'kittens').order("foo DESC")
115
117
  test = test.reverse_order
116
118
  expect(test).to be_a(Ansr::Relation)
117
119
  @mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo).and_return('')
@@ -119,7 +121,7 @@ describe Ansr::Relation do
119
121
  end
120
122
 
121
123
  it "should replace existing ASC order" do
122
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo ASC")
124
+ test = subject.where(q:'kittens').order("foo ASC")
123
125
  test = test.reverse_order
124
126
  expect(test).to be_a(Ansr::Relation)
125
127
  @mock_api.should_receive(:items).with(:q => 'kittens',:sort_by=>:foo, :sort_order=>:desc).and_return('')
@@ -129,7 +131,7 @@ describe Ansr::Relation do
129
131
 
130
132
  describe '#unscope' do
131
133
  it 'should remove clauses only from spawned Relation' do
132
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo DESC")
134
+ test = subject.where(q:'kittens').order("foo DESC")
133
135
  test2 = test.unscope(:order)
134
136
  expect(test2).to be_a(Ansr::Relation)
135
137
  @mock_api.should_receive(:items).with(:q => 'kittens').and_return('')
@@ -139,7 +141,7 @@ describe Ansr::Relation do
139
141
  # ActiveRecord::QueryMethods.VALID_UNSCOPING_VALUES =>
140
142
  # Set.new([:where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having])
141
143
  it 'should reject bad scope keys' do
142
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').order("foo DESC")
144
+ test = subject.where(q:'kittens').order("foo DESC")
143
145
  expect { test.unscope(:foo) }.to raise_error
144
146
  end
145
147
  end
@@ -147,7 +149,7 @@ describe Ansr::Relation do
147
149
  describe '#select' do
148
150
  describe 'with a block given' do
149
151
  it "should build an array" do
150
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
152
+ test = subject.where(q:'kittens')
151
153
  @mock_api.should_receive(:items).with(:q => 'kittens').and_return(@kittens)
152
154
  actual = test.select {|d| true}
153
155
  expect(actual).to be_a(Array)
@@ -159,22 +161,22 @@ describe Ansr::Relation do
159
161
  end
160
162
  describe 'with a String or Symbol key given' do
161
163
  it 'should change the requested document fields' do
162
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
163
- @mock_api.should_receive(:items).with(:q => 'kittens', :fields=>'name').and_return('')
164
+ test = subject.where(q:'kittens')
165
+ @mock_api.should_receive(:items).with(:q => 'kittens', :fields=>:name).and_return('')
164
166
  test = test.select('name')
165
167
  test.load
166
168
  end
167
169
  end
168
170
  describe 'with a list of keys' do
169
171
  it "should add all the requested document fields" do
170
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
171
- @mock_api.should_receive(:items).with(:q => 'kittens', :fields=>'name,foo').and_return('')
172
+ test = subject.where(q:'kittens')
173
+ @mock_api.should_receive(:items).with(:q => 'kittens', :fields=>[:name,:foo]).and_return('')
172
174
  test = test.select(['name','foo'])
173
175
  test.load
174
176
  end
175
177
  it "should add all the requested document fields and proxy them" do
176
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
177
- @mock_api.should_receive(:items).with(:q => 'kittens', :fields=>'object').and_return(@kittens)
178
+ test = subject.where(q:'kittens')
179
+ @mock_api.should_receive(:items).with(:q => 'kittens', :fields=>:object).and_return(@kittens)
178
180
  test = test.select('object AS my_object')
179
181
  test.load
180
182
  expect(test.to_a.first['object']).to be_nil
@@ -185,13 +187,13 @@ describe Ansr::Relation do
185
187
 
186
188
  describe '#limit' do
187
189
  it "should add page_size to the query params" do
188
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
190
+ test = subject.where(q:'kittens')
189
191
  @mock_api.should_receive(:items).with(:q => 'kittens', :page_size=>17).and_return('')
190
192
  test = test.limit(17)
191
193
  test.load
192
194
  end
193
195
  it "should raise an error if limit > 500" do
194
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
196
+ test = subject.where(q:'kittens')
195
197
  test = test.limit(500)
196
198
  expect {test.load }.to raise_error
197
199
  end
@@ -199,13 +201,13 @@ describe Ansr::Relation do
199
201
 
200
202
  describe '#offset' do
201
203
  it "should add page to the query params when page_size is defaulted" do
202
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
204
+ test = subject.where(q:'kittens')
203
205
  @mock_api.should_receive(:items).with(:q => 'kittens', :page=>3).and_return('')
204
206
  test = test.offset(20)
205
207
  test.load
206
208
  end
207
209
  it 'should raise an error if an offset is requested that is not a multiple of the page size' do
208
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens').limit(12)
210
+ test = subject.where(q:'kittens').limit(12)
209
211
  expect{test.offset(17)}.to raise_error(/^Bad/)
210
212
  test.offset(24)
211
213
  end
@@ -218,7 +220,7 @@ describe Ansr::Relation do
218
220
 
219
221
  describe '#loaded?' do
220
222
  it 'should be false before and true after' do
221
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
223
+ test = subject.where(q:'kittens')
222
224
  @mock_api.stub(:items).with(:q => 'kittens').and_return('')
223
225
  expect(test.loaded?).to be_false
224
226
  test.load
@@ -240,7 +242,7 @@ describe Ansr::Relation do
240
242
 
241
243
  describe '#empty?' do
242
244
  it 'should not make another call if records are loaded' do
243
- test = Ansr::Relation.new(Item, Item.table).where(q:'kittens')
245
+ test = subject.where(q:'kittens')
244
246
  @mock_api.should_receive(:items).with(:q => 'kittens').once.and_return(@empty)
245
247
  test.load
246
248
  expect(test.loaded?).to be_true
@@ -5,7 +5,9 @@ require 'ansr_dpla'
5
5
  require 'item'
6
6
 
7
7
  # you config the model with a hash including an API key for dp.la/v2, or the path to a YAML file
8
- Item.config('config/dpla.yml')
8
+ open('config/dpla.yml') do |blob|
9
+ Item.config {|x| x.merge! YAML.load(blob)}
10
+ end
9
11
 
10
12
  # then you can find single items with known IDs
11
13
  puts Item.find("7eb617e559007e1ad6d95bd30a30b16b")
@@ -22,7 +24,7 @@ rel.to_a
22
24
  # the limit decorator adds a page size limit
23
25
  # the offset decorator adds a non-zero starting point in the response set
24
26
  # the filter decorator adds filter/facet fields and optionally values to query them on
25
- rel = Item.where(q: 'kittens').limit(2).filter('sourceResource.contributor').select('sourceResource.title')
27
+ rel = Item.where(q: 'kittens').limit(2).facet('sourceResource.contributor').select('sourceResource.title')
26
28
  rel.to_a.each do |item|
27
29
  puts "#{item["id"]} \"#{item['sourceResource.title']}\""
28
30
  end
@@ -1,14 +1,21 @@
1
1
  require 'active_support'
2
+ require 'active_record'
2
3
  module Ansr
3
4
  extend ActiveSupport::Autoload
4
5
  eager_autoload do
5
6
  autoload :Configurable
7
+ autoload :ConnectionAdapters
8
+ autoload :DummyAssociations
6
9
  autoload :Arel
10
+ autoload :Facets
7
11
  autoload :Base
8
12
  autoload :Model
9
13
  autoload :Sanitization
10
14
  autoload :Relation
15
+ autoload :OpenStructWithHashAccess, 'ansr/utils'
11
16
  autoload_under 'relation' do
17
+ autoload :Group
18
+ autoload :PredicateBuilder
12
19
  autoload :ArelMethods
13
20
  autoload :QueryMethods
14
21
  end
@@ -1,5 +1,8 @@
1
1
  module Ansr
2
2
  module Arel
3
+ autoload :ConfiguredField, 'ansr/arel/configured_field'
3
4
  require 'ansr/arel/big_table'
5
+ require 'ansr/arel/nodes'
6
+ require 'ansr/arel/visitors'
4
7
  end
5
8
  end
@@ -1,23 +1,63 @@
1
+ require 'arel'
1
2
  module Ansr
2
3
  module Arel
3
4
  class BigTable < ::Arel::Table
5
+ attr_writer :primary_key
4
6
  attr_reader :fields, :facets, :sorts
5
7
 
6
- include Ansr::Configurable
7
8
 
8
9
  attr_reader :klass
9
10
  alias :model :klass
10
11
 
12
+ def self.primary_key
13
+ @primary_key ||= 'id'
14
+ end
15
+
16
+ def self.primary_key=(key)
17
+ @primary_key = key
18
+ end
19
+
11
20
  def initialize(klass, engine=nil)
12
21
  super(klass.name, engine.nil? ? klass.engine : engine)
13
22
  @klass = klass.model
14
23
  @fields = []
15
24
  @facets = []
16
25
  @sorts = []
26
+ @field_configs = {}
27
+ end
28
+
29
+ def primary_key
30
+ @primary_key ||= self.class.primary_key
17
31
  end
18
32
 
19
- def view?
20
- Ansr::Model::ViewProxy === model()
33
+ def [] name
34
+ name = (name.respond_to? :name) ? name.name.to_sym : name.to_sym
35
+ (@field_configs.include? name) ? Ansr::Arel::ConfiguredField.new(self, name, @field_configs[name]) : ::Arel::Attribute.new( self, name)
36
+ end
37
+
38
+ def configure_fields
39
+ if block_given?
40
+ yield @field_configs
41
+ end
42
+ @field_configs
43
+ end
44
+ def fields
45
+ if block_given?
46
+ yield @fields
47
+ end
48
+ @fields
49
+ end
50
+ def facets
51
+ if block_given?
52
+ yield @facets
53
+ end
54
+ @facets
55
+ end
56
+ def sorts
57
+ if block_given?
58
+ yield @sorts
59
+ end
60
+ @sorts
21
61
  end
22
62
  end
23
63
  end
@@ -0,0 +1,19 @@
1
+ module Ansr::Arel
2
+ class ConfiguredField < ::Arel::Attributes::Attribute
3
+ attr_reader :config
4
+ def initialize(relation, name, config={})
5
+ super(relation, name)
6
+ @config = {local: {}, query: {}}.merge(config)
7
+ end
8
+ def query
9
+ @config[:query]
10
+ end
11
+ def local
12
+ @config[:local]
13
+ end
14
+ def method_missing(method, *args)
15
+ @config[method] = args if args.first
16
+ @config[method]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,41 @@
1
+ module Ansr::Arel::Nodes
2
+ class ConfiguredUnary < ::Arel::Nodes::Node
3
+ attr_reader :expr, :opts
4
+
5
+ def initialize(expr, opts={})
6
+ @expr = expr
7
+ @opts = opts
8
+ end
9
+
10
+ def method_missing(method, *args)
11
+ @opts[method] = args if args.first
12
+ @opts[method]
13
+ end
14
+
15
+ end
16
+
17
+ class Facet < ConfiguredUnary
18
+
19
+ def order(*val)
20
+ if val.first
21
+ val = val.first.downcase.to_sym if String === val
22
+ @opts[:order] = val if val == :asc or val == :desc
23
+ end
24
+ @opts[:order]
25
+ end
26
+
27
+ def prefix(*val)
28
+ @opts[:prefix] = val.first.to_s if val.first
29
+ @opts[:prefix]
30
+ end
31
+
32
+ def limit(*val)
33
+ @opts[:limit] = val.first.to_s if val.first
34
+ @opts[:limit]
35
+ end
36
+ end
37
+ class Filter < ConfiguredUnary; end
38
+ class Highlight < ConfiguredUnary; end
39
+ class ProjectionTraits < ConfiguredUnary; end
40
+ class Spellcheck < ConfiguredUnary; end
41
+ end