ar_jdbc_pg_array 0.1.0-java
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.
- data/.gitignore +6 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE +20 -0
- data/README.md +48 -0
- data/Rakefile +7 -0
- data/ar_jdbc_pg_array.gemspec +24 -0
- data/lib/ar_jdbc_pg_array.rb +12 -0
- data/lib/ar_jdbc_pg_array/allways_save.rb +38 -0
- data/lib/ar_jdbc_pg_array/parser.rb +174 -0
- data/lib/ar_jdbc_pg_array/querying.rb +72 -0
- data/lib/ar_jdbc_pg_array/querying_arel.rb +172 -0
- data/lib/ar_jdbc_pg_array/references_by.rb +154 -0
- data/lib/ar_jdbc_pg_array/schema.rb +248 -0
- data/lib/ar_jdbc_pg_array/schema_arel.rb +47 -0
- data/lib/ar_jdbc_pg_array/schema_cacheable.rb +6 -0
- data/lib/ar_jdbc_pg_array/schema_fix_will_change.rb +13 -0
- data/spec/fixtures/bulk.rb +5 -0
- data/spec/fixtures/bulks.yml +36 -0
- data/spec/fixtures/item.rb +4 -0
- data/spec/fixtures/items.yml +22 -0
- data/spec/fixtures/schema.rb +30 -0
- data/spec/fixtures/tag.rb +2 -0
- data/spec/fixtures/tags.yml +15 -0
- data/spec/fixtures/unrelated.rb +21 -0
- data/spec/fixtures/unrelateds.yml +3 -0
- data/spec/pg_array_spec.rb +380 -0
- data/spec/spec_helper.rb +55 -0
- metadata +186 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Dirty
|
3
|
+
private
|
4
|
+
def attribute_will_change!(attr)
|
5
|
+
val = changed_attributes[attr] = clone_attribute_value(:read_attribute, attr)
|
6
|
+
if Array === val && !(Array === @attributes[attr])
|
7
|
+
send(attr) unless @attributes_cache.has_key?(attr)
|
8
|
+
@attributes[attr] = @attributes_cache[attr]
|
9
|
+
end
|
10
|
+
val
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
first:
|
2
|
+
id: 1
|
3
|
+
ints: [ 1 ]
|
4
|
+
strings: [ one ]
|
5
|
+
times: [2011-03-01, 2011-05-05]
|
6
|
+
floats: [1.0, 2.3]
|
7
|
+
decimals: [1.0, 2.3]
|
8
|
+
second:
|
9
|
+
id: 2
|
10
|
+
ints: [ 2 ]
|
11
|
+
strings: [ two ]
|
12
|
+
times: [2010-01-01, 2010-02-01]
|
13
|
+
floats: [2.0, 2.3]
|
14
|
+
decimals: [2.0, 2.3]
|
15
|
+
third:
|
16
|
+
id: 3
|
17
|
+
ints: [ 2, 3 ]
|
18
|
+
strings: [ two, three ]
|
19
|
+
times: [2010-03-01, 2010-04-01]
|
20
|
+
floats: [2.0, 2.5]
|
21
|
+
decimals: [2.0, 2.5]
|
22
|
+
fourth:
|
23
|
+
id: 4
|
24
|
+
ints: [ ]
|
25
|
+
strings: [ ]
|
26
|
+
times: [ ]
|
27
|
+
floats: [ ]
|
28
|
+
decimals: [ ]
|
29
|
+
fifth:
|
30
|
+
id: 5
|
31
|
+
type: "Bulk1"
|
32
|
+
ints: [ 10 ]
|
33
|
+
strings: [ "#{1+1}", "\\#{1+1}\"'\\z\x01", "\t\n" ]
|
34
|
+
times: [ ]
|
35
|
+
floats: [ ]
|
36
|
+
decimals: [ ]
|
@@ -0,0 +1,22 @@
|
|
1
|
+
i1:
|
2
|
+
id: 1
|
3
|
+
tag_ids: [ 1 ]
|
4
|
+
i2:
|
5
|
+
id: 2
|
6
|
+
tag_ids: [ 3 ]
|
7
|
+
i3:
|
8
|
+
id: 3
|
9
|
+
tag_ids: [ 1, 3 ]
|
10
|
+
i4:
|
11
|
+
id: 4
|
12
|
+
tag_ids: [ 3, 1 ]
|
13
|
+
i5:
|
14
|
+
id: 5
|
15
|
+
tag_ids: [ 1, 2 ]
|
16
|
+
i6:
|
17
|
+
id: 6
|
18
|
+
tag_ids: [ 1, 2, 3 ]
|
19
|
+
i7:
|
20
|
+
id: 7
|
21
|
+
tag_ids: [ ]
|
22
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
create_table "tags", :force => true do |t|
|
3
|
+
t.string :name
|
4
|
+
t.timestamps
|
5
|
+
end
|
6
|
+
|
7
|
+
create_table "items", :force => true do |t|
|
8
|
+
t.string :value
|
9
|
+
t.integer_array :tag_ids, :default => [1, 2]
|
10
|
+
t.string_array :tag_names, :default => %w{as so}
|
11
|
+
t.text :for_yaml
|
12
|
+
end
|
13
|
+
|
14
|
+
create_table "bulks", :force => true do |t|
|
15
|
+
t.string :type, :default => "Bulk"
|
16
|
+
t.string :value, :default => "'"
|
17
|
+
t.integer_array :ints, :default => [1, 2]
|
18
|
+
t.string_array :strings, :default => %w{as so}
|
19
|
+
t.timestamp_array :times, :default => %w{2010-01-01 2010-02-01}
|
20
|
+
t.float_array :floats, :default => [1.0, 1.2]
|
21
|
+
t.decimal_array :decimals, :default => [1.0, 1.2]
|
22
|
+
t.text_array :texts, :default => [nil, 'Text', 'NULL', 'Text with nil', 'Text with , nil, !"\\', 'nil']
|
23
|
+
t.integer_array :empty_def, :default => []
|
24
|
+
end
|
25
|
+
|
26
|
+
create_table "unrelateds", :force => true do |t|
|
27
|
+
t.text :for_yaml
|
28
|
+
t.text :for_custom_serialize
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
one:
|
2
|
+
id: 1
|
3
|
+
name: one
|
4
|
+
created_at: <%= Date.today.to_s(:db) %>
|
5
|
+
updated_at: <%= Time.now.to_s(:db) %>
|
6
|
+
two:
|
7
|
+
id: 2
|
8
|
+
name: two
|
9
|
+
created_at: <%= Date.today.to_s(:db) %>
|
10
|
+
updated_at: <%= Time.now.to_s(:db) %>
|
11
|
+
three:
|
12
|
+
id: 3
|
13
|
+
name: three
|
14
|
+
created_at: <%= Date.today.to_s(:db) %>
|
15
|
+
updated_at: <%= Time.now.to_s(:db) %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'base64'
|
2
|
+
class Unrelated < ActiveRecord::Base
|
3
|
+
class MySerializer
|
4
|
+
def initialize(val)
|
5
|
+
@val = val
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.dump(obj)
|
9
|
+
Base64.encode64(Marshal.dump(obj))
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.load(str)
|
13
|
+
if str
|
14
|
+
Marshal.load(Base64.decode64(str))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
serialize :for_yaml
|
20
|
+
serialize :for_custom_serialize, MySerializer
|
21
|
+
end
|
@@ -0,0 +1,380 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe "PgArray" do
|
4
|
+
context "Array" do
|
5
|
+
before :all do
|
6
|
+
@ability_class = Class.new do
|
7
|
+
include CanCan::Ability
|
8
|
+
end
|
9
|
+
@acheck = Struct.new(:a)
|
10
|
+
end
|
11
|
+
|
12
|
+
before :each do
|
13
|
+
@ability = @ability_class.new
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should change type" do
|
17
|
+
[].pg.should be_an_instance_of(PGArrays::PgArray)
|
18
|
+
[].search_any.should be_an_instance_of(PGArrays::PgAny)
|
19
|
+
[].search_all.should be_an_instance_of(PGArrays::PgAll)
|
20
|
+
[].search_subarray.should be_an_instance_of(PGArrays::PgIncludes)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should provide search_any for cancan" do
|
24
|
+
ab.can :boom, @acheck, :a => [1, 2].search_any
|
25
|
+
ab.should be_able_to(:boom, the([1]))
|
26
|
+
ab.should be_able_to(:boom, the([1, 3]))
|
27
|
+
ab.should be_able_to(:boom, the([3, 1]))
|
28
|
+
ab.should be_able_to(:boom, the([1, 2]))
|
29
|
+
ab.should be_able_to(:boom, the([1, 2, 3]))
|
30
|
+
ab.should_not be_able_to(:boom, the([3]))
|
31
|
+
ab.should_not be_able_to(:boom, the([]))
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should provide search_all for cancan" do
|
35
|
+
ab.can :boom, @acheck, :a => [1, 2].search_all
|
36
|
+
ab.should_not be_able_to(:boom, the([1]))
|
37
|
+
ab.should_not be_able_to(:boom, the([1, 3]))
|
38
|
+
ab.should_not be_able_to(:boom, the([3, 1]))
|
39
|
+
ab.should be_able_to(:boom, the([1, 2]))
|
40
|
+
ab.should be_able_to(:boom, the([1, 2, 3]))
|
41
|
+
ab.should_not be_able_to(:boom, the([3]))
|
42
|
+
ab.should_not be_able_to(:boom, the([]))
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should provide search_subarray for cancan" do
|
46
|
+
ab.can :boom, @acheck, :a => [1, 2].search_subarray
|
47
|
+
ab.should be_able_to(:boom, the([1]))
|
48
|
+
ab.should_not be_able_to(:boom, the([1, 3]))
|
49
|
+
ab.should_not be_able_to(:boom, the([3, 1]))
|
50
|
+
ab.should be_able_to(:boom, the([1, 2]))
|
51
|
+
ab.should_not be_able_to(:boom, the([1, 2, 3]))
|
52
|
+
ab.should_not be_able_to(:boom, the([3]))
|
53
|
+
ab.should be_able_to(:boom, the([]))
|
54
|
+
end
|
55
|
+
|
56
|
+
def the(ar)
|
57
|
+
@acheck.new(ar)
|
58
|
+
end
|
59
|
+
|
60
|
+
def ab
|
61
|
+
@ability
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "AR" do
|
66
|
+
it "should adequatly insert fixtures" do
|
67
|
+
bulk = Bulk.find(1)
|
68
|
+
bulk.ints.should == [ 1 ]
|
69
|
+
bulk.strings.should == %w{one}
|
70
|
+
map_times(bulk.times).should ==
|
71
|
+
map_times(parse_times(%w{2011-03-01 2011-05-05}))
|
72
|
+
bulk.floats.should == [1.0, 2.3]
|
73
|
+
bulk.decimals.should == [1.0, 2.3]
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should be created with defaults" do
|
77
|
+
bulk = Bulk.new
|
78
|
+
bulk.ints.should == [1, 2]
|
79
|
+
bulk.strings.should == %w{as so}
|
80
|
+
bulk.floats.should == [1.0, 1.2]
|
81
|
+
bulk.decimals.should == [1.0, 1.2]
|
82
|
+
bulk.texts.should == [nil, 'Text', 'NULL', 'Text with nil', 'Text with , nil, !"\\', 'nil']
|
83
|
+
map_times(bulk.times).should ==
|
84
|
+
map_times(parse_times(%w{2010-01-01 2010-02-01}))
|
85
|
+
bulk.empty_def.should == []
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should be able to insert" do
|
89
|
+
bulki = Bulk.new
|
90
|
+
bulki.save
|
91
|
+
bulk = Bulk.find(bulki.id)
|
92
|
+
bulk.ints.should == [1, 2]
|
93
|
+
bulk.strings.should == %w{as so}
|
94
|
+
bulk.floats.should == [1.0, 1.2]
|
95
|
+
bulk.decimals.should == [1.0, 1.2]
|
96
|
+
bulk.texts.should == [nil, 'Text', 'NULL', 'Text with nil', 'Text with , nil, !"\\', 'nil']
|
97
|
+
map_times(bulk.times).should ==
|
98
|
+
map_times(parse_times(%w{2010-01-01 2010-02-01}))
|
99
|
+
bulk.empty_def.should == []
|
100
|
+
bulk.destroy
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should not alter defaults" do
|
104
|
+
bulk = Bulk.new
|
105
|
+
bulk.strings.push :foo
|
106
|
+
bulk = Bulk.new
|
107
|
+
bulk.strings.should == %w{as so}
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should save changes" do
|
111
|
+
bulk = Bulk.find(3)
|
112
|
+
for field in %w{ints strings floats decimals times}
|
113
|
+
bulk.send(field+'=', bulk.send(field).reverse)
|
114
|
+
end
|
115
|
+
bulk.save!
|
116
|
+
bulk = Bulk.find(:first, :conditions=>'3 = id')
|
117
|
+
bulk.ints.should == [3, 2]
|
118
|
+
bulk.strings.should == %w{three two}
|
119
|
+
bulk.floats.should == [2.5, 2]
|
120
|
+
bulk.decimals.should == [2.5, 2]
|
121
|
+
map_times(bulk.times).should == map_times(parse_times(%w{2010-04-01 2010-03-01}))
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should save right text" do
|
125
|
+
bulk = Bulk.find(5)
|
126
|
+
bulk.texts = ['Text with , nil, !\x01\\\'"',"Text with , nil, !\x01\n\\\'\""]
|
127
|
+
bulk.save!
|
128
|
+
bulk.texts = []
|
129
|
+
bulk = Bulk.find(:first, :conditions=>'5 = id')
|
130
|
+
bulk.texts.should == ['Text with , nil, !\x01\\\'"',"Text with , nil, !\x01\n\\\'\""]
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should save nested arrays" do
|
134
|
+
Bulk.transaction do
|
135
|
+
bulk = Bulk.find(3)
|
136
|
+
bulk.ints = [[1,2],[3,4]]
|
137
|
+
bulk.floats = [[1.0, 2.3e34],[3.43,6.21]]
|
138
|
+
bulk.times = [parse_times(%w{2010-04-01 2011-04-01}), parse_times(%w{2011-05-01 2010-05-01})]
|
139
|
+
bulk.save!
|
140
|
+
bulk = Bulk.find(:first, :conditions=>'3 = id')
|
141
|
+
bulk.ints.should == [[1,2],[3,4]]
|
142
|
+
bulk.floats.should == [[1.0, 2.3e34],[3.43,6.21]]
|
143
|
+
bulk.times.map{|ts| map_times(ts)}.should == [
|
144
|
+
map_times(parse_times(%w{2010-04-01 2011-04-01})),
|
145
|
+
map_times(parse_times(%w{2011-05-01 2010-05-01}))]
|
146
|
+
raise ActiveRecord::Rollback
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should save right nested text" do
|
151
|
+
Bulk.transaction do
|
152
|
+
bulk = Bulk.find(5)
|
153
|
+
bulk.texts = [['Text with , nil, !\x01\\\'"',"Text with , nil, !\x01\n\\\'\""], ['asdf', 'fdsa']]
|
154
|
+
bulk.save!
|
155
|
+
bulk.texts = []
|
156
|
+
bulk = Bulk.find(:first, :conditions=>'5 = id')
|
157
|
+
bulk.texts.should == [['Text with , nil, !\x01\\\'"',"Text with , nil, !\x01\n\\\'\""], ['asdf', 'fdsa']]
|
158
|
+
raise ActiveRecord::Rollback
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should be safe for eval" do
|
163
|
+
bulk = Bulk.find(5)
|
164
|
+
bulk.strings.should == ["\#{1+1}", "\\\#{1+1}\"'\\z\x01", "\t\n"]
|
165
|
+
#$stderr.puts ActiveRecord::ConnectionAdapters::PostgreSQLColumn::ESCAPE_ARRAY.inspect
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should allow to use sql" do
|
169
|
+
bulks_where(['ints && ?', [1,2].pg]).should == bulks_where(:id=>[1,2,3])
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should allow to use finders" do
|
173
|
+
bulks_where(:ints => [2].search_any).should == bulks_where(:id=>[2,3])
|
174
|
+
bulks_where(:ints => [2,3].search_any).should == bulks_where(:id=>[2,3])
|
175
|
+
bulks_where(:ints => [1,2].search_any).should == bulks_where(:id=>[1,2,3])
|
176
|
+
|
177
|
+
bulks_where(:ints => [2].search_all).should == bulks_where(:id=>[2,3])
|
178
|
+
bulks_where(:ints => [2,3].search_all).should == bulks_where(:id=>[3])
|
179
|
+
bulks_where(:ints => [1,2].search_all).should == []
|
180
|
+
|
181
|
+
bulks_where(:ints => [2].search_subarray).should == bulks_where(:id=>[2,4])
|
182
|
+
bulks_where(:ints => [2,3].search_subarray).should == bulks_where(:id=>[2,3,4])
|
183
|
+
bulks_where(:ints => [1,2].search_subarray).should == bulks_where(:id=>[1,2,4])
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should be cached in @attributes_cache" do
|
187
|
+
bulk = Bulk.find(1)
|
188
|
+
ar = bulk.ints
|
189
|
+
bulk.ints.should.equal?(ar)
|
190
|
+
ard = ar.dup
|
191
|
+
arn = (bulk.ints << 1)
|
192
|
+
arn.should equal(ar)
|
193
|
+
bulk.ints.should equal(ar)
|
194
|
+
bulk.ints.should == (ard + [1])
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'should allways save changed value' do
|
198
|
+
bulk = Bulk.find(1)
|
199
|
+
old = bulk.ints.dup
|
200
|
+
bulk.ints << 2
|
201
|
+
new = bulk.ints.dup
|
202
|
+
bulk.save
|
203
|
+
bulk.reload
|
204
|
+
bulk.ints.should == new
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should not break yaml serialization on model with array' do
|
208
|
+
item = Item.find(1)
|
209
|
+
item.for_yaml = {:a => :b}
|
210
|
+
item.save.should be_true
|
211
|
+
copy = Item.find(1)
|
212
|
+
copy.for_yaml.should == {:a => :b}
|
213
|
+
copy.for_yaml = ['a', 'b']
|
214
|
+
copy.save.should be_true
|
215
|
+
copy = Item.find(1)
|
216
|
+
copy.for_yaml.should == ['a', 'b']
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'should not break yaml serialization on unrelated model' do
|
220
|
+
item = Unrelated.find(1)
|
221
|
+
item.for_yaml.should == {'a' => 'b'}
|
222
|
+
item.for_yaml = {:a => :b}
|
223
|
+
item.save.should be_true
|
224
|
+
copy = Unrelated.find(1)
|
225
|
+
copy.for_yaml.should == {:a => :b}
|
226
|
+
copy.for_yaml = ['a', 'b']
|
227
|
+
copy.save.should be_true
|
228
|
+
copy = Unrelated.find(1)
|
229
|
+
copy.for_yaml.should == ['a', 'b']
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'should not break custom serialization on model with array' do
|
233
|
+
obj = Unrelated::MySerializer.new(%w{hello world})
|
234
|
+
model = Unrelated.create!(:for_custom_serialize => obj)
|
235
|
+
model.for_custom_serialize.to_yaml.should == obj.to_yaml
|
236
|
+
model2 = Unrelated.find(model.id)
|
237
|
+
model2.for_custom_serialize.to_yaml.should == obj.to_yaml
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'should be workable with sti' do
|
241
|
+
obj = Bulk1.where(:ints => [10].pg).first
|
242
|
+
obj.should be_instance_of Bulk1
|
243
|
+
obj.floats = [1.1, 2.2]
|
244
|
+
obj.save
|
245
|
+
obj1 = Bulk.find(obj.id)
|
246
|
+
obj1.should be_instance_of Bulk1
|
247
|
+
obj1.floats.should == [1.1, 2.2]
|
248
|
+
obj2 = Bulk1.new
|
249
|
+
obj2.save
|
250
|
+
obj2.destroy
|
251
|
+
end
|
252
|
+
|
253
|
+
def map_times(times)
|
254
|
+
times.map{|t| t.strftime("%F %T")}
|
255
|
+
end
|
256
|
+
|
257
|
+
def parse_times(times)
|
258
|
+
times.map{|t| DateTime.parse(t)}
|
259
|
+
end
|
260
|
+
|
261
|
+
def bulks_where(cond)
|
262
|
+
Bulk.where(cond).order('id').all
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
context "CanCan" do
|
267
|
+
before :all do
|
268
|
+
@ability_class = Class.new do
|
269
|
+
include CanCan::Ability
|
270
|
+
end
|
271
|
+
@all_items = Item.all
|
272
|
+
end
|
273
|
+
|
274
|
+
before :each do
|
275
|
+
@ability = @ability_class.new
|
276
|
+
end
|
277
|
+
|
278
|
+
it "should provide search_any for cancan" do
|
279
|
+
should_match_ids_with_ability [2, 3, 4, 6], :tag_ids => [3].search_any
|
280
|
+
should_match_ids_with_ability [1, 3, 4, 5, 6], :tag_ids => [1, 2].search_any
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should provide search_all for cancan" do
|
284
|
+
should_match_ids_with_ability [2, 3, 4, 6], :tag_ids => [3].search_all
|
285
|
+
should_match_ids_with_ability [5, 6], :tag_ids => [1, 2].search_all
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should provide search_subarray for cancan" do
|
289
|
+
should_match_ids_with_ability [2, 7], :tag_ids => [3].search_subarray
|
290
|
+
should_match_ids_with_ability [1, 5, 7], :tag_ids => [1, 2].search_subarray
|
291
|
+
end
|
292
|
+
|
293
|
+
def should_match_ids_with_ability(ids, ability)
|
294
|
+
act = (ability[:tag_ids].class.name + ids.join('_')).to_sym
|
295
|
+
ab.can act, Item, ability
|
296
|
+
items = accessible_items(act)
|
297
|
+
items.should == items_where(:id=>ids)
|
298
|
+
should_be_able_all items, act
|
299
|
+
should_not_be_able_except items, act
|
300
|
+
end
|
301
|
+
|
302
|
+
def ab
|
303
|
+
@ability
|
304
|
+
end
|
305
|
+
|
306
|
+
def accessible_items(act)
|
307
|
+
Item.accessible_by(ab, act).order('id').all
|
308
|
+
end
|
309
|
+
|
310
|
+
def items_where(cond)
|
311
|
+
Item.where(cond).order('id').all
|
312
|
+
end
|
313
|
+
|
314
|
+
def should_be_able_all(items, act)
|
315
|
+
items.each{|item| ab.should be_able_to(act, item)}
|
316
|
+
end
|
317
|
+
|
318
|
+
def should_not_be_able_except(items, act)
|
319
|
+
(@all_items - items).each{|item| ab.should_not be_able_to(act, items)}
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
context "references_by" do
|
324
|
+
it "should fetch tags in saved order" do
|
325
|
+
Item.find(3).tags.should == [Tag.find(1), Tag.find(3)]
|
326
|
+
Item.find(4).tags.should == [Tag.find(3), Tag.find(1)]
|
327
|
+
end
|
328
|
+
|
329
|
+
it "should save tags references" do
|
330
|
+
item = Item.find(3)
|
331
|
+
item.tags= [Tag.find(1), '3', 2]
|
332
|
+
item.tags.should == [Tag.find(1), Tag.find(3), Tag.find(2)]
|
333
|
+
item.save!
|
334
|
+
item.reload
|
335
|
+
item.tags.should == [Tag.find(1), Tag.find(3), Tag.find(2)]
|
336
|
+
item.tags= [1,3]
|
337
|
+
item.save!
|
338
|
+
item.reload
|
339
|
+
item.tags.should == [Tag.find(1), Tag.find(3)]
|
340
|
+
end
|
341
|
+
|
342
|
+
it "should define named scopes for tags" do
|
343
|
+
Item.tags_include(3).order('id').all.should == items_where(:id=>[2,3,4,6])
|
344
|
+
Item.tags_include(1,3).order('id').all.should == items_where(:id=>[3,4,6])
|
345
|
+
Item.tags_have_all(3).order('id').all.should == items_where(:id=>[2,3,4,6])
|
346
|
+
Item.tags_have_all(1,3).order('id').all.should == items_where(:id=>[3,4,6])
|
347
|
+
Item.tags_have_any(3).order('id').all.should == items_where(:id=>[2,3,4,6])
|
348
|
+
Item.tags_have_any(1,3).order('id').all.should == items_where(:id=>[1,2,3,4,5,6])
|
349
|
+
Item.tags_included_into(3).order('id').all.should == items_where(:id=>[2,7])
|
350
|
+
Item.tags_included_into(1,3).order('id').all.should == items_where(:id=>[1,2,3,4,7])
|
351
|
+
end
|
352
|
+
|
353
|
+
def items_where(cond)
|
354
|
+
Item.where(cond).order('id').all
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
context "schema" do
|
359
|
+
it "should allow to add column" do
|
360
|
+
lambda do
|
361
|
+
ActiveRecord::Schema.define do
|
362
|
+
change_table :items do |t|
|
363
|
+
t.integer_array :ints, :default=>[], :null=>false
|
364
|
+
end
|
365
|
+
add_column :items, :floats, :float_array, :default=>[0], :null=>false
|
366
|
+
end
|
367
|
+
end.should_not raise_error
|
368
|
+
end
|
369
|
+
|
370
|
+
it "should not break other add_column" do
|
371
|
+
lambda do
|
372
|
+
ActiveRecord::Schema.define do
|
373
|
+
add_column :items, :float1, :float
|
374
|
+
add_column :items, :float2, :float, :null=>true
|
375
|
+
add_column :items, :float3, :float, :default=>0, :null=>false
|
376
|
+
end
|
377
|
+
end.should_not raise_error
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|