large_text_field 0.3.0.pre.1
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +43 -0
- data/Rakefile +52 -0
- data/db/migrate/20110217210640_add_large_text_fields.rb +16 -0
- data/lib/large_text_field.rb +12 -0
- data/lib/large_text_field/engine.rb +15 -0
- data/lib/large_text_field/named_text_value.rb +17 -0
- data/lib/large_text_field/owner.rb +111 -0
- data/lib/large_text_field/version.rb +3 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/models/library.rb +22 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +52 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +39 -0
- data/test/dummy/config/environments/production.rb +69 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/db/migrate/20160217033529_create_libraries.rb +11 -0
- data/test/dummy/db/schema.rb +29 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/test.log +4233 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/test/fixtures/text_field_owners.yml +11 -0
- data/test/fixtures/large_text_field/named_text_values.yml +11 -0
- data/test/large_text_field_test.rb +7 -0
- data/test/test_helper.rb +37 -0
- data/test/unit/dummy/library_test.rb +23 -0
- data/test/unit/large_text_field/name_text_value_test.rb +47 -0
- data/test/unit/large_text_field/owner_test.rb +315 -0
- metadata +143 -0
@@ -0,0 +1,6 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
3
|
+
|
4
|
+
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
5
|
+
require File.expand_path('../../config/boot', __FILE__)
|
6
|
+
require 'rails/commands'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
|
2
|
+
|
3
|
+
# This model initially had no columns defined. If you add columns to the
|
4
|
+
# model remove the '{}' from the fixture names and add the columns immediately
|
5
|
+
# below each fixture, per the syntax in the comments below
|
6
|
+
#
|
7
|
+
one: {}
|
8
|
+
# column: value
|
9
|
+
#
|
10
|
+
two: {}
|
11
|
+
# column: value
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
|
2
|
+
|
3
|
+
# This model initially had no columns defined. If you add columns to the
|
4
|
+
# model remove the '{}' from the fixture names and add the columns immediately
|
5
|
+
# below each fixture, per the syntax in the comments below
|
6
|
+
#
|
7
|
+
one: {}
|
8
|
+
# column: value
|
9
|
+
#
|
10
|
+
two: {}
|
11
|
+
# column: value
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
|
3
|
+
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
4
|
+
require "rails/test_help"
|
5
|
+
require "invoca/utils"
|
6
|
+
require "rr"
|
7
|
+
require "shoulda"
|
8
|
+
require "minitest/unit"
|
9
|
+
require "pry"
|
10
|
+
|
11
|
+
def large_description
|
12
|
+
<<-EOF
|
13
|
+
The Royal Library of Alexandria or Ancient Library of Alexandria in Alexandria, Egypt, was one of the
|
14
|
+
largest and most significant libraries of the ancient world. It was dedicated to the Muses, the nine
|
15
|
+
goddesses of the arts.[1] It flourished under the patronage of the Ptolemaic dynasty and functioned
|
16
|
+
as a major center of scholarship from its construction in the 3rd century BCE until the Roman conquest
|
17
|
+
of Egypt in 30 BCE, with collections of works, lecture halls, meeting rooms, and gardens. The library
|
18
|
+
was part of a larger research institution called the Musaeum of Alexandria, where many of the most
|
19
|
+
famous thinkers of the ancient world studied.
|
20
|
+
|
21
|
+
The library was created by Ptolemy I Soter, who was a Macedonian general and the successor of Alexander
|
22
|
+
the Great.[2] Most of the books were kept as papyrus scrolls. It is unknown how many such scrolls were
|
23
|
+
housed at any given time.
|
24
|
+
|
25
|
+
The library is famous for having been burned down, resulting in the loss of many scrolls and books; its
|
26
|
+
destruction has become a symbol for the loss of cultural knowledge. A few sources differ on who is
|
27
|
+
responsible for the destruction and when it occurred. There is mythology regarding this main burning
|
28
|
+
but the library may in truth have suffered several fires or other acts of destruction over many years.
|
29
|
+
Possible occasions for the partial or complete destruction of the Library of Alexandria include a fire
|
30
|
+
set by Julius Caesar in 48 BCE and an attack by Aurelian in the CE 270s.
|
31
|
+
|
32
|
+
After the main library was fully destroyed, ancient scholars used a "daughter library" in a temple known
|
33
|
+
as the Serapeum, located in another part of the city. According to Socrates of Constantinople, Coptic Pope
|
34
|
+
Theophilus destroyed the Serapeum in AD 391, although it's not certain that it still contained an offshoot
|
35
|
+
of the library then.
|
36
|
+
EOF
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module LargeTextField
|
4
|
+
class LibraryTest < ActiveSupport::TestCase
|
5
|
+
should "be able to construct a library" do
|
6
|
+
l = Library.new(name: "Alexandria Public Library")
|
7
|
+
l.save!
|
8
|
+
|
9
|
+
l.description = large_description
|
10
|
+
l.save!
|
11
|
+
|
12
|
+
assert_equal large_description, l.description
|
13
|
+
|
14
|
+
l = Library.find(l.id)
|
15
|
+
assert_equal large_description, l.description
|
16
|
+
end
|
17
|
+
|
18
|
+
should "be able to dup a class that has no current large text field" do
|
19
|
+
l = Library.new(name: "Alexandria Public Library")
|
20
|
+
l.dup
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module LargeTextField
|
2
|
+
class NamedTextValueTest < ActiveSupport::TestCase
|
3
|
+
should belong_to(:owner)
|
4
|
+
|
5
|
+
should "use large_text_fields as the table name" do
|
6
|
+
assert_equal "large_text_fields", LargeTextField::NamedTextValue.table_name
|
7
|
+
end
|
8
|
+
|
9
|
+
should "have field name and value attributes" do
|
10
|
+
library = Library.create!(name: "Smithsonian")
|
11
|
+
ntv = LargeTextField::NamedTextValue.new(field_name: "puppy", value: "Millie", owner: library)
|
12
|
+
assert_equal "puppy", ntv.field_name
|
13
|
+
assert_equal "Millie", ntv.value
|
14
|
+
assert_equal "Smithsonian", ntv.owner.name
|
15
|
+
ntv.save!
|
16
|
+
|
17
|
+
# Attributes survive persistance
|
18
|
+
ntv = LargeTextField::NamedTextValue.find(ntv.id)
|
19
|
+
assert_equal "puppy", ntv.field_name
|
20
|
+
assert_equal "Millie", ntv.value
|
21
|
+
assert_equal "Smithsonian", ntv.owner.name
|
22
|
+
end
|
23
|
+
|
24
|
+
context "unique index" do
|
25
|
+
should "raise a unique constraint failure on the same owner, and field name" do
|
26
|
+
library = Library.create!(name: "Smithsonian")
|
27
|
+
LargeTextField::NamedTextValue.create!(field_name: "puppy", value: "Millie", owner: library)
|
28
|
+
|
29
|
+
assert_raise(ActiveRecord::RecordNotUnique) do
|
30
|
+
LargeTextField::NamedTextValue.create!(field_name: "puppy", value: "Wiki", owner: library)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
should "allow different owners and field names" do
|
35
|
+
library = Library.create!(name: "Smithsonian")
|
36
|
+
library2 = Library.create!(name: "Alexandria")
|
37
|
+
LargeTextField::NamedTextValue.create!(field_name: "puppy", value: "Millie", owner: library)
|
38
|
+
|
39
|
+
# Different field name
|
40
|
+
LargeTextField::NamedTextValue.create!(field_name: "dog", value: "Wiki", owner: library)
|
41
|
+
|
42
|
+
# Different owner instance
|
43
|
+
LargeTextField::NamedTextValue.create!(field_name: "puppy", value: "Millie", owner: library2)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,315 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module LargeTextField
|
4
|
+
class OwnerTest < ActiveSupport::TestCase
|
5
|
+
context "updating in large_text_field_save hook" do
|
6
|
+
{ 'empty string' => '', 'non empty string' => 'this is some text' }.each do |name, value|
|
7
|
+
should "be able to assign #{name}" do
|
8
|
+
begin
|
9
|
+
Library.default_notes = value
|
10
|
+
@library = Library.create!(name: "Smithsonian")
|
11
|
+
assert_equal value, @library.notes
|
12
|
+
assert_equal value, @library.reload.notes
|
13
|
+
ensure
|
14
|
+
Library.default_notes = "none_set"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
should "raise error on saving nil value" do
|
20
|
+
begin
|
21
|
+
Library.default_notes = :nil
|
22
|
+
assert_raises RuntimeError do
|
23
|
+
@library = Library.create!(name: "Smithsonian")
|
24
|
+
end
|
25
|
+
ensure
|
26
|
+
Library.default_notes = "none_set"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "a large text field" do
|
32
|
+
setup do
|
33
|
+
@library = Library.create!(name: "Smithsonian")
|
34
|
+
assert_equal "", @library.description
|
35
|
+
end
|
36
|
+
|
37
|
+
should "declare the association when it is first described and other meta data when it is first defined" do
|
38
|
+
assert_equal :has_many, Library.reflections['large_text_fields'].macro
|
39
|
+
|
40
|
+
assert_equal({ maximum: nil, singularize_errors: true }, Library.large_text_field_options['description'])
|
41
|
+
end
|
42
|
+
|
43
|
+
should "read from a file" do
|
44
|
+
@library = Library.create!(name: "Smithsonian")
|
45
|
+
tmp_file = nil
|
46
|
+
begin
|
47
|
+
tmp_file = Tempfile.new('large_text_field_test')
|
48
|
+
tmp_file.write("this is a string from the file")
|
49
|
+
tmp_file.close
|
50
|
+
|
51
|
+
test_file = File.open(tmp_file.path)
|
52
|
+
|
53
|
+
@library.description = test_file
|
54
|
+
assert_equal 'this is a string from the file', @library.description
|
55
|
+
|
56
|
+
@library.save!
|
57
|
+
assert_equal 'this is a string from the file', @library.reload.description
|
58
|
+
ensure
|
59
|
+
tmp_file.unlink
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
should "allow get and set with saves and deletes" do
|
64
|
+
@library.description = "badger " * 200
|
65
|
+
assert_equal "badger " * 200, @library.description
|
66
|
+
|
67
|
+
@library.save!
|
68
|
+
@library.reload
|
69
|
+
assert_equal "badger " * 200, @library.description
|
70
|
+
|
71
|
+
@library.description = "mushroom " * 200
|
72
|
+
assert_equal "mushroom " * 200, @library.description
|
73
|
+
|
74
|
+
@library.save!
|
75
|
+
@library.reload
|
76
|
+
assert_equal "mushroom " * 200, @library.description
|
77
|
+
|
78
|
+
@library.description = ''
|
79
|
+
assert_equal '', @library.description
|
80
|
+
|
81
|
+
@library.save!
|
82
|
+
@library.reload
|
83
|
+
assert_equal '', @library.description
|
84
|
+
end
|
85
|
+
|
86
|
+
should "allow for concurrent sets and deletes" do
|
87
|
+
@library.description = "first"
|
88
|
+
@library.catalog = "second"
|
89
|
+
|
90
|
+
assert_equal "first", @library.description
|
91
|
+
assert_equal "second", @library.catalog
|
92
|
+
|
93
|
+
@library.save!
|
94
|
+
@library.reload
|
95
|
+
|
96
|
+
assert_equal "first", @library.description
|
97
|
+
assert_equal "second", @library.catalog
|
98
|
+
|
99
|
+
@library.description = "third"
|
100
|
+
@library.catalog = ''
|
101
|
+
|
102
|
+
assert_equal "third", @library.description
|
103
|
+
assert_equal '', @library.catalog
|
104
|
+
|
105
|
+
@library.save!
|
106
|
+
|
107
|
+
assert_equal "third", @library.description
|
108
|
+
assert_equal '', @library.catalog
|
109
|
+
end
|
110
|
+
|
111
|
+
should "forget about changes if they are not saved" do
|
112
|
+
@library.description = "first"
|
113
|
+
@library.reload
|
114
|
+
assert_equal '', @library.description
|
115
|
+
|
116
|
+
@library.description = "first"
|
117
|
+
@library.save!
|
118
|
+
@library.reload
|
119
|
+
|
120
|
+
@library.description = ''
|
121
|
+
@library.reload
|
122
|
+
assert_equal "first", @library.description
|
123
|
+
end
|
124
|
+
|
125
|
+
should "validate the maximum length" do
|
126
|
+
@library.notes = "a" * (LargeTextField::MAX_LENGTH + 1)
|
127
|
+
assert !@library.valid?
|
128
|
+
assert_equal(["Notes are too long (maximum is 5,000,000 characters)"], @library.errors.full_messages)
|
129
|
+
end
|
130
|
+
|
131
|
+
should "singularize the errors if requested" do
|
132
|
+
@library.description = "a" * (LargeTextField::MAX_LENGTH + 1)
|
133
|
+
assert !@library.valid?
|
134
|
+
assert_equal(["Description is too long (maximum is 5,000,000 characters)"], @library.errors.full_messages)
|
135
|
+
end
|
136
|
+
|
137
|
+
should "allow a custom maximum length to be provided" do
|
138
|
+
@library.catalog = "1" * 501
|
139
|
+
assert_equal false, @library.valid?
|
140
|
+
assert_equal ["Catalog is too long (maximum is 500 characters)"], @library.errors.full_messages
|
141
|
+
end
|
142
|
+
|
143
|
+
should "prevent a non-Integer to be provided for a custom maximum" do
|
144
|
+
assert_raise(ArgumentError) do
|
145
|
+
Library.large_text_field :not_number_maximum, maximum: "i am not a number"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
should "prevent a custom maximum length to be provided that is not in the allowable range" do
|
150
|
+
assert_raise ArgumentError do
|
151
|
+
Library.large_text_field :bigger_than_allowed, maximum: LargeTextField::MAX_LENGTH + 1
|
152
|
+
end
|
153
|
+
|
154
|
+
assert_raise ArgumentError do
|
155
|
+
Library.large_text_field :smaller_than_allowed, maximum: -1
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
should "not save fields that are set to blank" do
|
160
|
+
@library = Library.new(name: 'Millie')
|
161
|
+
assert_equal 0, @library.large_text_fields.count
|
162
|
+
|
163
|
+
@library.description = "first"
|
164
|
+
@library.notes = ""
|
165
|
+
|
166
|
+
@library.save!
|
167
|
+
@library.reload
|
168
|
+
|
169
|
+
assert_equal "first", @library.description
|
170
|
+
assert_equal "", @library.notes
|
171
|
+
|
172
|
+
assert_equal 1, @library.large_text_fields.count
|
173
|
+
end
|
174
|
+
|
175
|
+
should "delete fields when they are set to blank" do
|
176
|
+
assert_equal 0, @library.large_text_fields.count
|
177
|
+
|
178
|
+
@library.description = "first"
|
179
|
+
|
180
|
+
@library.save!
|
181
|
+
@library.reload
|
182
|
+
|
183
|
+
assert_equal "first", @library.description
|
184
|
+
|
185
|
+
assert_equal 1, @library.large_text_fields.count
|
186
|
+
|
187
|
+
@library.description = ""
|
188
|
+
@library.save!
|
189
|
+
@library.reload
|
190
|
+
|
191
|
+
assert_equal "", @library.description
|
192
|
+
|
193
|
+
assert_equal 0, @library.large_text_fields.count
|
194
|
+
end
|
195
|
+
|
196
|
+
should "be able to update deleted fields" do
|
197
|
+
assert_equal 0, @library.large_text_fields.count
|
198
|
+
|
199
|
+
@library.description = "first"
|
200
|
+
|
201
|
+
@library.save!
|
202
|
+
|
203
|
+
assert_equal "first", @library.description
|
204
|
+
|
205
|
+
assert_equal 1, @library.large_text_fields.count
|
206
|
+
|
207
|
+
@library.description = ""
|
208
|
+
@library.save!
|
209
|
+
|
210
|
+
assert_equal "", @library.description
|
211
|
+
|
212
|
+
assert_equal 0, @library.large_text_fields.count
|
213
|
+
@library.description = "first"
|
214
|
+
|
215
|
+
@library.save!
|
216
|
+
|
217
|
+
assert_equal "first", @library.description
|
218
|
+
end
|
219
|
+
|
220
|
+
should "be cloned with the rest of the record" do
|
221
|
+
@library.description = "first"
|
222
|
+
@library.catalog = "second"
|
223
|
+
@library.save!
|
224
|
+
|
225
|
+
@clone = @library.dup
|
226
|
+
assert_equal "first", @clone.description
|
227
|
+
assert_equal "second", @clone.catalog
|
228
|
+
@clone.save!
|
229
|
+
|
230
|
+
assert_equal "first", @clone.description
|
231
|
+
assert_equal "second", @clone.catalog
|
232
|
+
|
233
|
+
# Should not have stolen from the owner...
|
234
|
+
@library.save!
|
235
|
+
@library.reload
|
236
|
+
|
237
|
+
assert_equal "first", @library.description
|
238
|
+
assert_equal "second", @library.catalog
|
239
|
+
|
240
|
+
# should be destroyed when destroyed
|
241
|
+
text_field_ids = @clone.large_text_fields.*.id
|
242
|
+
@clone.destroy
|
243
|
+
text_field_ids.each { |id| assert !LargeTextField::NamedTextValue.find_by_id(id) }
|
244
|
+
end
|
245
|
+
|
246
|
+
should "be able to be eager loaded" do
|
247
|
+
@library.description = "first"
|
248
|
+
@library.catalog = "second"
|
249
|
+
@library.save!
|
250
|
+
|
251
|
+
new_value = Library.includes(:large_text_fields).find(@library.id)
|
252
|
+
|
253
|
+
dont_allow(Library.connection).select
|
254
|
+
assert_equal "first", new_value.description
|
255
|
+
assert_equal "second", new_value.catalog
|
256
|
+
end
|
257
|
+
|
258
|
+
should "support strings or symbols for get/set methods" do
|
259
|
+
@library.set_text_field(:description, "first")
|
260
|
+
assert_equal "first", @library.description
|
261
|
+
assert_equal "first", @library.get_text_field(:description)
|
262
|
+
assert_equal "first", @library.get_text_field('description')
|
263
|
+
|
264
|
+
@library.set_text_field('description', "second")
|
265
|
+
assert_equal "second", @library.description
|
266
|
+
assert_equal "second", @library.get_text_field(:description)
|
267
|
+
assert_equal "second", @library.get_text_field('description')
|
268
|
+
end
|
269
|
+
|
270
|
+
should "detect changes when @text_field_hash hash is/not empty" do
|
271
|
+
@library = Library.new(name: "Smithsonian")
|
272
|
+
|
273
|
+
assert !@library.instance_variable_defined?("@text_field_hash")
|
274
|
+
assert !@library.description_changed?
|
275
|
+
@library.description = "a new note"
|
276
|
+
assert @library.description_changed?
|
277
|
+
@library.save!
|
278
|
+
@library.reload
|
279
|
+
|
280
|
+
assert !@library.description_changed?
|
281
|
+
@library.description = "a new note"
|
282
|
+
assert !@library.description_changed?
|
283
|
+
@library.description = "now with more chicken taste"
|
284
|
+
assert @library.description_changed?
|
285
|
+
end
|
286
|
+
|
287
|
+
should "only validate_large_text_fields if loaded" do
|
288
|
+
@library = Library.new
|
289
|
+
assert !@library.instance_variable_defined?("@text_field_hash")
|
290
|
+
assert @library.valid?
|
291
|
+
assert !@library.instance_variable_defined?("@text_field_hash")
|
292
|
+
end
|
293
|
+
|
294
|
+
should "reload changes when they come from a different model" do
|
295
|
+
@library = Library.create!(name: "Cambridge University Library", description: "in england")
|
296
|
+
@second_version = Library.find(@library.id)
|
297
|
+
|
298
|
+
@second_version.update_attributes!(description: "The main research library of the University of Cambridge in England")
|
299
|
+
|
300
|
+
assert_equal "The main research library of the University of Cambridge in England", @library.reload.description
|
301
|
+
end
|
302
|
+
|
303
|
+
should "delete large text fields when the owner is destroyed"do
|
304
|
+
assert_equal 0, LargeTextField::NamedTextValue.count
|
305
|
+
|
306
|
+
@library = Library.create!(name: "Cambridge University Library", description: "in england")
|
307
|
+
assert_equal 1, LargeTextField::NamedTextValue.count
|
308
|
+
|
309
|
+
@library.destroy
|
310
|
+
assert_equal 0, LargeTextField::NamedTextValue.count
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
315
|
+
end
|