my_annotations 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.rvmrc +1 -0
- data/AUTHORS.rdoc +5 -0
- data/CHANGELOG.rdoc +64 -0
- data/INDEX.rdoc +17 -0
- data/generators/annotations_migration/annotations_migration_generator.rb +32 -0
- data/generators/annotations_migration/templates/migration_v1.rb +60 -0
- data/generators/annotations_migration/templates/migration_v2.rb +9 -0
- data/generators/annotations_migration/templates/migration_v3.rb +74 -0
- data/generators/annotations_migration/templates/migration_v4.rb +13 -0
- data/install.rb +1 -0
- data/lib/annotations/acts_as_annotatable.rb +271 -0
- data/lib/annotations/acts_as_annotation_source.rb +117 -0
- data/lib/annotations/acts_as_annotation_value.rb +115 -0
- data/lib/annotations/config.rb +148 -0
- data/lib/annotations/routing.rb +8 -0
- data/lib/annotations/util.rb +82 -0
- data/lib/annotations_version_fu.rb +119 -0
- data/lib/app/controllers/annotations_controller.rb +162 -0
- data/lib/app/controllers/application_controller.rb +2 -0
- data/lib/app/helpers/application_helper.rb +2 -0
- data/lib/app/models/annotation.rb +413 -0
- data/lib/app/models/annotation_attribute.rb +37 -0
- data/lib/app/models/annotation_value_seed.rb +48 -0
- data/lib/app/models/number_value.rb +23 -0
- data/lib/app/models/text_value.rb +23 -0
- data/my_annotations.gemspec +4 -9
- data/rails/init.rb +8 -0
- data/test/acts_as_annotatable_test.rb +186 -0
- data/test/acts_as_annotation_source_test.rb +84 -0
- data/test/acts_as_annotation_value_test.rb +17 -0
- data/test/annotation_attribute_test.rb +22 -0
- data/test/annotation_test.rb +213 -0
- data/test/annotation_value_seed_test.rb +14 -0
- data/test/annotation_version_test.rb +39 -0
- data/test/annotations_controller_test.rb +27 -0
- data/test/app_root/app/controllers/application_controller.rb +9 -0
- data/test/app_root/app/models/book.rb +5 -0
- data/test/app_root/app/models/chapter.rb +5 -0
- data/test/app_root/app/models/group.rb +3 -0
- data/test/app_root/app/models/tag.rb +6 -0
- data/test/app_root/app/models/user.rb +3 -0
- data/test/app_root/app/views/annotations/edit.html.erb +12 -0
- data/test/app_root/app/views/annotations/index.html.erb +1 -0
- data/test/app_root/app/views/annotations/new.html.erb +11 -0
- data/test/app_root/app/views/annotations/show.html.erb +3 -0
- data/test/app_root/config/boot.rb +115 -0
- data/test/app_root/config/environment.rb +16 -0
- data/test/app_root/config/environments/mysql.rb +0 -0
- data/test/app_root/config/routes.rb +4 -0
- data/test/app_root/db/migrate/001_create_test_models.rb +38 -0
- data/test/app_root/db/migrate/002_annotations_migration_v1.rb +60 -0
- data/test/app_root/db/migrate/003_annotations_migration_v2.rb +9 -0
- data/test/app_root/db/migrate/004_annotations_migration_v3.rb +72 -0
- data/test/config_test.rb +383 -0
- data/test/fixtures/annotation_attributes.yml +49 -0
- data/test/fixtures/annotation_value_seeds.csv +16 -0
- data/test/fixtures/annotation_versions.yml +259 -0
- data/test/fixtures/annotations.yml +239 -0
- data/test/fixtures/books.yml +13 -0
- data/test/fixtures/chapters.yml +27 -0
- data/test/fixtures/groups.yml +7 -0
- data/test/fixtures/number_value_versions.csv +2 -0
- data/test/fixtures/number_values.csv +2 -0
- data/test/fixtures/text_value_versions.csv +35 -0
- data/test/fixtures/text_values.csv +35 -0
- data/test/fixtures/users.yml +8 -0
- data/test/number_value_version_test.rb +40 -0
- data/test/routing_test.rb +27 -0
- data/test/test_helper.rb +41 -0
- data/test/text_value_version_test.rb +40 -0
- metadata +77 -7
data/test/config_test.rb
ADDED
@@ -0,0 +1,383 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class ConfigTest < ActiveSupport::TestCase
|
4
|
+
def setup
|
5
|
+
Annotations::Config::reset
|
6
|
+
|
7
|
+
Annotations::Config::attribute_names_for_values_to_be_downcased.concat([ "downcased_thing" ])
|
8
|
+
|
9
|
+
Annotations::Config::attribute_names_for_values_to_be_upcased.concat([ "upcased_thing" ])
|
10
|
+
|
11
|
+
Annotations::Config::strip_text_rules.update({ "tag" => [ '"', ',' ], "comma_stripped" => ',', "regex_strip" => /\d/ })
|
12
|
+
|
13
|
+
Annotations::Config::limits_per_source.update({ "rating" => 1 })
|
14
|
+
|
15
|
+
Annotations::Config::attribute_names_to_allow_duplicates.concat([ "allow_duplicates_for_this" ])
|
16
|
+
|
17
|
+
Annotations::Config::content_restrictions.update({ "rating" => { :in => 1..5, :error_message => "Please provide a rating between 1 and 5" },
|
18
|
+
"category" => { :in => [ "fruit", "nut", "fibre" ], :error_message => "Please select a valid category" } })
|
19
|
+
|
20
|
+
Annotations::Config::default_attribute_identifier_template = "http://x.com/attribute#%s"
|
21
|
+
|
22
|
+
Annotations::Config::attribute_name_transform_for_identifier = Proc.new { |name|
|
23
|
+
regex = /\.|-|:/
|
24
|
+
if name.match(regex)
|
25
|
+
name.gsub(regex, ' ').titleize.gsub(' ', '').camelize(:lower)
|
26
|
+
else
|
27
|
+
name.camelize(:lower)
|
28
|
+
end
|
29
|
+
}
|
30
|
+
|
31
|
+
Annotations::Config::value_factories["tag"] = Proc.new { |v|
|
32
|
+
case v
|
33
|
+
when String, Symbol
|
34
|
+
Tag.find_or_create_by_name(v.to_s)
|
35
|
+
else
|
36
|
+
v
|
37
|
+
end
|
38
|
+
}
|
39
|
+
|
40
|
+
Annotations::Config::valid_value_types["tag"] = "Tag"
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
def teardown
|
45
|
+
Annotations::Config.reset
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_values_downcased_or_upcased
|
49
|
+
source = users(:jane)
|
50
|
+
|
51
|
+
# Should downcase
|
52
|
+
|
53
|
+
ann1 = Annotation.create(:attribute_name => "downcased_thing",
|
54
|
+
:value => "UNIque",
|
55
|
+
:source_type => source.class.name,
|
56
|
+
:source_id => source.id,
|
57
|
+
:annotatable_type => "Book",
|
58
|
+
:annotatable_id => 1)
|
59
|
+
|
60
|
+
assert ann1.valid?
|
61
|
+
assert_equal "unique", ann1.value_content
|
62
|
+
|
63
|
+
# Should upcase
|
64
|
+
|
65
|
+
ann2 = Annotation.create(:attribute_name => "upcased_thing",
|
66
|
+
:value => "UNIque",
|
67
|
+
:source_type => source.class.name,
|
68
|
+
:source_id => source.id,
|
69
|
+
:annotatable_type => "Book",
|
70
|
+
:annotatable_id => 1)
|
71
|
+
|
72
|
+
assert ann2.valid?
|
73
|
+
assert_equal "UNIQUE", ann2.value_content
|
74
|
+
|
75
|
+
# Should not do anything
|
76
|
+
|
77
|
+
ann3 = Annotation.create(:attribute_name => "dont_do_anything",
|
78
|
+
:value => "UNIque",
|
79
|
+
:source_type => source.class.name,
|
80
|
+
:source_id => source.id,
|
81
|
+
:annotatable_type => "Book",
|
82
|
+
:annotatable_id => 1)
|
83
|
+
|
84
|
+
assert ann3.valid?
|
85
|
+
assert_equal "UNIque", ann3.value_content
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_strip_text_rules
|
89
|
+
source = users(:john)
|
90
|
+
|
91
|
+
# Strip 'tag'
|
92
|
+
|
93
|
+
ann1 = Annotation.create(:attribute_name => "Tag",
|
94
|
+
:value => 'v,al"ue',
|
95
|
+
:source_type => source.class.name,
|
96
|
+
:source_id => source.id,
|
97
|
+
:annotatable_type => "Book",
|
98
|
+
:annotatable_id => 1)
|
99
|
+
|
100
|
+
assert ann1.valid?
|
101
|
+
assert_equal "value", ann1.value_content
|
102
|
+
|
103
|
+
# Strip 'comma_stripped'
|
104
|
+
|
105
|
+
ann2 = Annotation.create(:attribute_name => "comma_stripped",
|
106
|
+
:value => 'v,al"ue',
|
107
|
+
:source_type => source.class.name,
|
108
|
+
:source_id => source.id,
|
109
|
+
:annotatable_type => "Book",
|
110
|
+
:annotatable_id => 1)
|
111
|
+
|
112
|
+
assert ann2.valid?
|
113
|
+
assert_equal 'val"ue', ann2.value_content
|
114
|
+
|
115
|
+
# Regexp strip
|
116
|
+
|
117
|
+
ann3 = Annotation.create(:attribute_name => "regex_strip",
|
118
|
+
:value => 'v1,al"ue23x4',
|
119
|
+
:source_type => source.class.name,
|
120
|
+
:source_id => source.id,
|
121
|
+
:annotatable_type => "Book",
|
122
|
+
:annotatable_id => 1)
|
123
|
+
|
124
|
+
assert ann3.valid?
|
125
|
+
assert_equal 'v,al"uex', ann3.value_content
|
126
|
+
|
127
|
+
# Don't strip!
|
128
|
+
|
129
|
+
ann4 = Annotation.create(:attribute_name => "dont_strip",
|
130
|
+
:value => 'v,al"ue',
|
131
|
+
:source_type => source.class.name,
|
132
|
+
:source_id => source.id,
|
133
|
+
:annotatable_type => "Book",
|
134
|
+
:annotatable_id => 1)
|
135
|
+
|
136
|
+
assert ann4.valid?
|
137
|
+
assert_equal 'v,al"ue', ann4.value_content
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_limits_per_source
|
141
|
+
source = users(:john)
|
142
|
+
|
143
|
+
bk1 = Book.create
|
144
|
+
|
145
|
+
anns = bk1.annotations << Annotation.new(:attribute_name => "rating",
|
146
|
+
:value => NumberValue.new(:number => 4),
|
147
|
+
:source_type => source.class.name,
|
148
|
+
:source_id => source.id)
|
149
|
+
|
150
|
+
assert anns.length > 0
|
151
|
+
assert_equal 4, bk1.annotations(true)[0].value_content
|
152
|
+
assert_equal 1, bk1.annotations(true).length
|
153
|
+
|
154
|
+
ann2 = Annotation.new(:attribute_name => "rating",
|
155
|
+
:value => 1,
|
156
|
+
:source_type => source.class.name,
|
157
|
+
:source_id => source.id,
|
158
|
+
:annotatable_type => "Book",
|
159
|
+
:annotatable_id => bk1.id)
|
160
|
+
|
161
|
+
assert ann2.invalid?
|
162
|
+
assert !ann2.save
|
163
|
+
assert_equal 1, bk1.annotations(true).length
|
164
|
+
|
165
|
+
ann3 = bk1.annotations(true)[0]
|
166
|
+
ann3.value = 3
|
167
|
+
assert ann3.valid?
|
168
|
+
assert ann3.save
|
169
|
+
assert_equal 1, bk1.annotations(true).length
|
170
|
+
|
171
|
+
# Check that two versions of the annotation now exist
|
172
|
+
assert_equal 2, bk1.annotations[0].versions.length
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_attribute_names_to_allow_duplicates
|
176
|
+
source = users(:john)
|
177
|
+
|
178
|
+
# First test the default case of not allowing duplicates...
|
179
|
+
|
180
|
+
bk1 = Book.create
|
181
|
+
|
182
|
+
ann1 = bk1.annotations << Annotation.new(:attribute_name => "no_duplicates_allowed",
|
183
|
+
:value => "Hello there",
|
184
|
+
:source_type => source.class.name,
|
185
|
+
:source_id => source.id)
|
186
|
+
|
187
|
+
assert_not_nil ann1
|
188
|
+
assert_equal 1, bk1.annotations.length
|
189
|
+
|
190
|
+
ann2 = bk1.annotations << Annotation.new(:attribute_name => "no_duplicates_allowed",
|
191
|
+
:value => "Hello there again",
|
192
|
+
:source_type => source.class.name,
|
193
|
+
:source_id => source.id)
|
194
|
+
|
195
|
+
assert_not_nil ann2
|
196
|
+
assert_equal 2, bk1.annotations(true).length
|
197
|
+
|
198
|
+
ann3 = bk1.annotations << Annotation.new(:attribute_name => "no_duplicates_allowed",
|
199
|
+
:value => "Hello there",
|
200
|
+
:source_type => source.class.name,
|
201
|
+
:source_id => source.id)
|
202
|
+
|
203
|
+
assert_equal false, ann3
|
204
|
+
assert_equal 2, bk1.annotations(true).length
|
205
|
+
|
206
|
+
|
207
|
+
# Then test the configured exceptions to the default rule...
|
208
|
+
|
209
|
+
bk2 = Book.create
|
210
|
+
|
211
|
+
ann4 = bk2.annotations << Annotation.new(:attribute_name => "allow_duplicates_for_this",
|
212
|
+
:value => "Hi there",
|
213
|
+
:source_type => source.class.name,
|
214
|
+
:source_id => source.id)
|
215
|
+
|
216
|
+
assert_not_nil ann4
|
217
|
+
assert_equal 1, bk2.annotations.length
|
218
|
+
|
219
|
+
ann5 = bk2.annotations << Annotation.new(:attribute_name => "allow_duplicates_for_this",
|
220
|
+
:value => "Hi there again",
|
221
|
+
:source_type => source.class.name,
|
222
|
+
:source_id => source.id)
|
223
|
+
|
224
|
+
assert_not_nil ann5
|
225
|
+
assert_equal 2, bk2.annotations(true).length
|
226
|
+
|
227
|
+
ann6 = bk2.annotations << Annotation.new(:attribute_name => "allow_duplicates_for_this",
|
228
|
+
:value => "Hi there",
|
229
|
+
:source_type => source.class.name,
|
230
|
+
:source_id => source.id)
|
231
|
+
|
232
|
+
assert_not_nil ann6
|
233
|
+
assert_equal 3, bk2.annotations(true).length
|
234
|
+
end
|
235
|
+
|
236
|
+
def test_content_restrictions
|
237
|
+
source1 = users(:john)
|
238
|
+
source2 = users(:jane)
|
239
|
+
|
240
|
+
# First test the default case of not restricting values...
|
241
|
+
|
242
|
+
bk1 = Book.create
|
243
|
+
|
244
|
+
ann1 = Annotation.new(:attribute_name => "allow_any_value",
|
245
|
+
:value => "Hello there",
|
246
|
+
:source_type => source1.class.name,
|
247
|
+
:source_id => source1.id,
|
248
|
+
:annotatable_type => "Book",
|
249
|
+
:annotatable_id => bk1.id)
|
250
|
+
|
251
|
+
assert ann1.valid?
|
252
|
+
assert ann1.save
|
253
|
+
assert_equal 1, bk1.annotations.length
|
254
|
+
|
255
|
+
|
256
|
+
# Then test the configured exceptions to the default rule...
|
257
|
+
|
258
|
+
bk2 = Book.create
|
259
|
+
|
260
|
+
ann2 = Annotation.new(:attribute_name => "rating",
|
261
|
+
:value => "2",
|
262
|
+
:source_type => source1.class.name,
|
263
|
+
:source_id => source1.id,
|
264
|
+
:annotatable_type => "Book",
|
265
|
+
:annotatable_id => bk2.id)
|
266
|
+
|
267
|
+
assert ann2.valid?
|
268
|
+
assert ann2.save
|
269
|
+
assert_equal 1, bk2.annotations.length
|
270
|
+
|
271
|
+
|
272
|
+
ann3 = Annotation.new(:attribute_name => "rating",
|
273
|
+
:value => "10",
|
274
|
+
:source_type => source2.class.name,
|
275
|
+
:source_id => source2.id,
|
276
|
+
:annotatable_type => "Book",
|
277
|
+
:annotatable_id => bk2.id)
|
278
|
+
|
279
|
+
assert ann3.invalid?
|
280
|
+
assert !ann3.save
|
281
|
+
assert ann3.errors.full_messages.include?("Please provide a rating between 1 and 5")
|
282
|
+
assert_equal 1, bk2.annotations(true).length
|
283
|
+
|
284
|
+
|
285
|
+
ann4 = Annotation.new(:attribute_name => "category",
|
286
|
+
:value => "fibre",
|
287
|
+
:source_type => source1.class.name,
|
288
|
+
:source_id => source1.id,
|
289
|
+
:annotatable_type => "Book",
|
290
|
+
:annotatable_id => bk2.id)
|
291
|
+
|
292
|
+
assert ann4.valid?
|
293
|
+
assert ann4.save
|
294
|
+
assert_equal 2, bk2.annotations(true).length
|
295
|
+
|
296
|
+
ann5 = Annotation.new(:attribute_name => "category",
|
297
|
+
:value => "home cooking",
|
298
|
+
:source_type => source2.class.name,
|
299
|
+
:source_id => source2.id,
|
300
|
+
:annotatable_type => "Book",
|
301
|
+
:annotatable_id => bk2.id)
|
302
|
+
|
303
|
+
assert ann5.invalid?
|
304
|
+
assert !ann5.save
|
305
|
+
assert ann5.errors.full_messages.include?("Please select a valid category")
|
306
|
+
assert_equal 2, bk2.annotations(true).length
|
307
|
+
end
|
308
|
+
|
309
|
+
def test_default_attribute_identifier_template
|
310
|
+
attrib1 = AnnotationAttribute.create(:name => "myAttribute")
|
311
|
+
assert attrib1.valid?
|
312
|
+
assert_equal "http://x.com/attribute#myAttribute", attrib1.identifier
|
313
|
+
|
314
|
+
attrib2 = AnnotationAttribute.create(:name => "http://www.example.org/annotations#details")
|
315
|
+
assert attrib2.valid?
|
316
|
+
assert_equal "http://www.example.org/annotations#details", attrib2.identifier
|
317
|
+
|
318
|
+
attrib3 = AnnotationAttribute.create(:name => "<www.example.org/annotations#details>")
|
319
|
+
assert attrib3.valid?
|
320
|
+
assert_equal "www.example.org/annotations#details", attrib3.identifier
|
321
|
+
|
322
|
+
attrib4 = AnnotationAttribute.create(:name => "hello_world-attribute:zero")
|
323
|
+
assert attrib4.valid?
|
324
|
+
assert_equal "http://x.com/attribute#helloWorldAttributeZero", attrib4.identifier
|
325
|
+
end
|
326
|
+
|
327
|
+
def test_value_factories
|
328
|
+
source = users(:john)
|
329
|
+
|
330
|
+
ann1 = Annotation.create(:attribute_name => "Tag",
|
331
|
+
:value => 'alignment',
|
332
|
+
:source_type => source.class.name,
|
333
|
+
:source_id => source.id,
|
334
|
+
:annotatable_type => "Book",
|
335
|
+
:annotatable_id => 1)
|
336
|
+
|
337
|
+
assert ann1.valid?
|
338
|
+
assert_kind_of Tag, ann1.value
|
339
|
+
assert_equal "alignment", ann1.value_content
|
340
|
+
|
341
|
+
ann2 = Annotation.new(:attribute_name => "tag",
|
342
|
+
:source_type => source.class.name,
|
343
|
+
:source_id => source.id,
|
344
|
+
:annotatable_type => "Book",
|
345
|
+
:annotatable_id => 1)
|
346
|
+
|
347
|
+
ann2.value = Tag.find_or_create_by_name("hello")
|
348
|
+
|
349
|
+
assert ann2.save
|
350
|
+
assert_equal 'hello', ann2.value_content
|
351
|
+
end
|
352
|
+
|
353
|
+
def test_valid_value_types
|
354
|
+
source = users(:john)
|
355
|
+
|
356
|
+
# Test valid one
|
357
|
+
|
358
|
+
ann1 = Annotation.new(:attribute_name => "Tag",
|
359
|
+
:value => 'smashing',
|
360
|
+
:source_type => source.class.name,
|
361
|
+
:source_id => source.id,
|
362
|
+
:annotatable_type => "Book",
|
363
|
+
:annotatable_id => 1)
|
364
|
+
|
365
|
+
assert ann1.valid?
|
366
|
+
assert ann1.save
|
367
|
+
assert_kind_of Tag, ann1.value
|
368
|
+
|
369
|
+
# Test invalid one
|
370
|
+
|
371
|
+
ann2 = Annotation.new(:attribute_name => "Tag",
|
372
|
+
:value => TextValue.new(:text => 'smashing'),
|
373
|
+
:source_type => source.class.name,
|
374
|
+
:source_id => source.id,
|
375
|
+
:annotatable_type => "Book",
|
376
|
+
:annotatable_id => 1)
|
377
|
+
|
378
|
+
|
379
|
+
assert ann2.invalid?
|
380
|
+
assert !ann2.save
|
381
|
+
assert ann2.errors.full_messages.include?("Annotation value is of an invalid type for attribute name: 'tag'. Provided value is a TextValue.")
|
382
|
+
end
|
383
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
aa_tag:
|
2
|
+
id: 1
|
3
|
+
name: Tag
|
4
|
+
identifier: "http://www.example.org/attribute#Tag"
|
5
|
+
|
6
|
+
aa_summary:
|
7
|
+
id: 2
|
8
|
+
name: Summary
|
9
|
+
identifier: "http://www.example.org/attribute#Summary"
|
10
|
+
|
11
|
+
aa_length:
|
12
|
+
id: 3
|
13
|
+
name: length
|
14
|
+
identifier: "http://www.example.org/attribute#Length"
|
15
|
+
|
16
|
+
aa_title:
|
17
|
+
id: 4
|
18
|
+
name: Title
|
19
|
+
identifier: "http://www.example.org/attribute#Title"
|
20
|
+
|
21
|
+
aa_complexity:
|
22
|
+
id: 5
|
23
|
+
name: complexity
|
24
|
+
identifier: "http://www.example.org/attribute#complexity"
|
25
|
+
|
26
|
+
aa_endingtype:
|
27
|
+
id: 6
|
28
|
+
name: endingType
|
29
|
+
identifier: "http://www.example.org/attribute#endingType"
|
30
|
+
|
31
|
+
aa_note:
|
32
|
+
id: 7
|
33
|
+
name: Note
|
34
|
+
identifier: "http://www.example.org/attribute#Note"
|
35
|
+
|
36
|
+
aa_author:
|
37
|
+
id: 8
|
38
|
+
name: Author
|
39
|
+
identifier: "http://www.example.org/attribute#Author"
|
40
|
+
|
41
|
+
aa_rating:
|
42
|
+
id: 9
|
43
|
+
name: rating
|
44
|
+
identifier: "http://www.example.org/attribute#rating"
|
45
|
+
|
46
|
+
aa_contextualtag:
|
47
|
+
id: 10
|
48
|
+
name: Contextual Tag
|
49
|
+
identifier: "http://www.example.org/attribute#ContextualTag"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
id,attribute_id,value_type,value_id
|
2
|
+
1,1,TextValue,1
|
3
|
+
2,1,TextValue,2
|
4
|
+
3,1,TextValue,3
|
5
|
+
4,1,TextValue,4
|
6
|
+
5,1,TextValue,5
|
7
|
+
6,1,TextValue,6
|
8
|
+
7,1,TextValue,7
|
9
|
+
8,1,TextValue,8
|
10
|
+
9,1,TextValue,9
|
11
|
+
10,1,TextValue,10
|
12
|
+
11,8,TextValue,11
|
13
|
+
12,8,TextValue,12
|
14
|
+
13,8,TextValue,13
|
15
|
+
14,8,TextValue,14
|
16
|
+
15,8,TextValue,15
|
@@ -0,0 +1,259 @@
|
|
1
|
+
bh_summary_1_av1:
|
2
|
+
annotation: bh_summary_1
|
3
|
+
annotatable_type: Book
|
4
|
+
annotatable_id: 1
|
5
|
+
attribute_id: 2
|
6
|
+
value_type: TextValue
|
7
|
+
value_id: 16
|
8
|
+
source_type: User
|
9
|
+
source_id: 1
|
10
|
+
version: 1
|
11
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
12
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
13
|
+
|
14
|
+
bh_length_1_av1:
|
15
|
+
annotation: bh_length_1
|
16
|
+
annotatable_type: Book
|
17
|
+
annotatable_id: 1
|
18
|
+
attribute_id: 3
|
19
|
+
value_type: NumberValue
|
20
|
+
value_id: 1
|
21
|
+
source_type: Group
|
22
|
+
source_id: 2
|
23
|
+
version: 1
|
24
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
25
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
26
|
+
|
27
|
+
bh_title_1_av1:
|
28
|
+
annotation: bh_title_1
|
29
|
+
annotatable_type: Book
|
30
|
+
annotatable_id: 1
|
31
|
+
attribute_id: 4
|
32
|
+
value_type: TextValue
|
33
|
+
value_id: 17
|
34
|
+
source_type: User
|
35
|
+
source_id: 1
|
36
|
+
version: 1
|
37
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
38
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
39
|
+
|
40
|
+
bh_rating_1_av1:
|
41
|
+
annotation: bh_rating_1
|
42
|
+
annotatable_type: Rating
|
43
|
+
annotatable_id: 1
|
44
|
+
attribute_id: 9
|
45
|
+
value_type: TextValue
|
46
|
+
value_id: 18
|
47
|
+
source_type: User
|
48
|
+
source_id: 2
|
49
|
+
version: 1
|
50
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
51
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
52
|
+
|
53
|
+
bh_tag_1_av1:
|
54
|
+
annotation: bh_tag_1
|
55
|
+
annotatable_type: Book
|
56
|
+
annotatable_id: 1
|
57
|
+
attribute_id: 1
|
58
|
+
value_type: TextValue
|
59
|
+
value_id: 19
|
60
|
+
source_type: Group
|
61
|
+
source_id: 2
|
62
|
+
version: 1
|
63
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
64
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
65
|
+
|
66
|
+
bh_tag_2_av1:
|
67
|
+
annotation: bh_tag_2
|
68
|
+
annotatable_type: Book
|
69
|
+
annotatable_id: 1
|
70
|
+
attribute_id: 1
|
71
|
+
value_type: TextValue
|
72
|
+
value_id: 20
|
73
|
+
source_type: User
|
74
|
+
source_id: 2
|
75
|
+
version: 1
|
76
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
77
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
78
|
+
|
79
|
+
br_summary_1_av1:
|
80
|
+
annotation: br_summary_1
|
81
|
+
annotatable_type: Book
|
82
|
+
annotatable_id: 2
|
83
|
+
attribute_id: 2
|
84
|
+
value_type: TextValue
|
85
|
+
value_id: 21
|
86
|
+
source_type: User
|
87
|
+
source_id: 1
|
88
|
+
version: 1
|
89
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
90
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
91
|
+
|
92
|
+
br_summary_2_av1:
|
93
|
+
annotation: br_summary_2
|
94
|
+
annotatable_type: Book
|
95
|
+
annotatable_id: 2
|
96
|
+
attribute_id: 2
|
97
|
+
value_type: TextValue
|
98
|
+
value_id: 22
|
99
|
+
source_type: Group
|
100
|
+
source_id: 1
|
101
|
+
version: 1
|
102
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
103
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
104
|
+
|
105
|
+
br_author_1_av1:
|
106
|
+
annotation: br_author_1
|
107
|
+
annotatable_type: Book
|
108
|
+
annotatable_id: 2
|
109
|
+
attribute_id: 8
|
110
|
+
value_type: TextValue
|
111
|
+
value_id: 23
|
112
|
+
source_type: User
|
113
|
+
source_id: 1
|
114
|
+
version: 1
|
115
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
116
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
117
|
+
|
118
|
+
br_tag_1_av1:
|
119
|
+
annotation: br_tag_1
|
120
|
+
annotatable_type: Book
|
121
|
+
annotatable_id: 2
|
122
|
+
attribute_id: 1
|
123
|
+
value_type: TextValue
|
124
|
+
value_id: 24
|
125
|
+
source_type: User
|
126
|
+
source_id: 2
|
127
|
+
version: 1
|
128
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
129
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
130
|
+
|
131
|
+
br_note_1_av1:
|
132
|
+
annotation: br_note_1
|
133
|
+
annotatable_type: Book
|
134
|
+
annotatable_id: 2
|
135
|
+
attribute_id: 7
|
136
|
+
value_type: TextValue
|
137
|
+
value_id: 25
|
138
|
+
source_type: User
|
139
|
+
source_id: 2
|
140
|
+
version: 1
|
141
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
142
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
143
|
+
|
144
|
+
bh_c10_endingtype_1_av1:
|
145
|
+
annotation: bh_c10_endingtype_1
|
146
|
+
annotatable_type: Chapter
|
147
|
+
annotatable_id: 2
|
148
|
+
attribute_id: 6
|
149
|
+
value_type: TextValue
|
150
|
+
value_id: 26
|
151
|
+
source_type: Group
|
152
|
+
source_id: 1
|
153
|
+
version: 1
|
154
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
155
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
156
|
+
|
157
|
+
bh_c10_title_1_av1:
|
158
|
+
annotation: bh_c10_title_1
|
159
|
+
annotatable_type: Chapter
|
160
|
+
annotatable_id: 2
|
161
|
+
attribute_id: 4
|
162
|
+
value_type: TextValue
|
163
|
+
value_id: 27
|
164
|
+
source_type: User
|
165
|
+
source_id: 2
|
166
|
+
version: 1
|
167
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
168
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
169
|
+
|
170
|
+
br_c2_title_1_av1:
|
171
|
+
annotation: br_c2_title_1
|
172
|
+
annotatable_type: Chapter
|
173
|
+
annotatable_id: 3
|
174
|
+
attribute_id: 4
|
175
|
+
value_type: TextValue
|
176
|
+
value_id: 28
|
177
|
+
source_type: User
|
178
|
+
source_id: 1
|
179
|
+
version: 1
|
180
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
181
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
182
|
+
|
183
|
+
br_c2_tag_1_av1:
|
184
|
+
annotation: br_c2_tag_1
|
185
|
+
annotatable_type: Chapter
|
186
|
+
annotatable_id: 3
|
187
|
+
attribute_id: 1
|
188
|
+
value_type: TextValue
|
189
|
+
value_id: 29
|
190
|
+
source_type: Group
|
191
|
+
source_id: 2
|
192
|
+
version: 1
|
193
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
194
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
195
|
+
|
196
|
+
br_c2_tag_2_av1:
|
197
|
+
annotation: br_c2_tag_2
|
198
|
+
annotatable_type: Chapter
|
199
|
+
annotatable_id: 3
|
200
|
+
attribute_id: 1
|
201
|
+
value_type: TextValue
|
202
|
+
value_id: 30
|
203
|
+
source_type: User
|
204
|
+
source_id: 1
|
205
|
+
version: 1
|
206
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
207
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
208
|
+
|
209
|
+
br_c2_title_2_av1:
|
210
|
+
annotation: br_c2_title_2
|
211
|
+
annotatable_type: Chapter
|
212
|
+
annotatable_id: 3
|
213
|
+
attribute_id: 4
|
214
|
+
value_type: TextValue
|
215
|
+
value_id: 31
|
216
|
+
source_type: User
|
217
|
+
source_id: 2
|
218
|
+
version: 1
|
219
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
220
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
221
|
+
|
222
|
+
br_c202_complexity_1_av1:
|
223
|
+
annotation: br_c202_complexity_1
|
224
|
+
annotatable_type: Chapter
|
225
|
+
annotatable_id: 4
|
226
|
+
attribute_id: 5
|
227
|
+
value_type: TextValue
|
228
|
+
value_id: 32
|
229
|
+
source_type: Group
|
230
|
+
source_id: 1
|
231
|
+
version: 1
|
232
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
233
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
234
|
+
|
235
|
+
br_c202_title_1_av1:
|
236
|
+
annotation: br_c202_title_1
|
237
|
+
annotatable_type: Chapter
|
238
|
+
annotatable_id: 4
|
239
|
+
attribute_id: 4
|
240
|
+
value_type: TextValue
|
241
|
+
value_id: 33
|
242
|
+
source_type: User
|
243
|
+
source_id: 1
|
244
|
+
version: 1
|
245
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
246
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|
247
|
+
|
248
|
+
br_c202_tag_1_av1:
|
249
|
+
annotation: br_c202_tag_1
|
250
|
+
annotatable_type: Chapter
|
251
|
+
annotatable_id: 4
|
252
|
+
attribute_id: 1
|
253
|
+
value_type: TextValue
|
254
|
+
value_id: 34
|
255
|
+
source_type: Group
|
256
|
+
source_id: 2
|
257
|
+
version: 1
|
258
|
+
created_at: <%= 1.minute.ago.to_s(:db) %>
|
259
|
+
updated_at: <%= 1.minute.ago.to_s(:db) %>
|