columns_on_demand 4.3.0 → 6.0.0
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 +5 -5
- data/.travis.yml +14 -0
- data/Gemfile +2 -2
- data/MIT-LICENSE +1 -1
- data/README.md +4 -5
- data/columns_on_demand.gemspec +1 -10
- data/lib/columns_on_demand.rb +74 -102
- data/lib/columns_on_demand/version.rb +1 -1
- data/test/columns_on_demand_test.rb +92 -46
- data/test/schema.rb +6 -0
- data/test_all.sh +19 -0
- metadata +12 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1883a4021dfc69d3c3ce1b12c02f14cfb8d5ad40b7dcf0e382c638ebe20528f1
|
4
|
+
data.tar.gz: b9da84f7409d34203123dc0c9a2c9ed59ed65004cfb08994ad4f13be1e1bad83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25931accb7f33e305383400d6d780d119508298a3ae4baa66fdc374daaf459f47cee7fd7390de790af785075ef7a62b53bd6d79716269487e989952d6979a4c2
|
7
|
+
data.tar.gz: 5477645b767cbc9bf7f9acff349b6fd7c515980905921137f49f8e335c4ed937b89b2cd689f802fd5b296b5129ae1e73899303dd438265af22ca06e36335a3c7
|
data/.travis.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
---
|
2
|
+
sudo: false
|
3
|
+
language: ruby
|
4
|
+
cache: bundler
|
5
|
+
dist: bionic
|
6
|
+
rvm:
|
7
|
+
- 2.6
|
8
|
+
services:
|
9
|
+
- postgresql
|
10
|
+
- mysql
|
11
|
+
before_script:
|
12
|
+
- createdb -U postgres columns_on_demand_test
|
13
|
+
- mysqladmin -u root create columns_on_demand_test
|
14
|
+
script: ./test_all.sh
|
data/Gemfile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
-
# Declare your gem's dependencies in
|
3
|
+
# Declare your gem's dependencies in columns_on_demand.gemspec.
|
4
4
|
# Bundler will treat runtime dependencies like base dependencies, and
|
5
5
|
# development dependencies will be added by default to the :development group.
|
6
6
|
gemspec
|
@@ -11,4 +11,4 @@ gemspec
|
|
11
11
|
# your gem to rubygems.org.
|
12
12
|
|
13
13
|
gem 'rails', ENV['RAILS_VERSION']
|
14
|
-
gem '
|
14
|
+
gem 'sqlite3', ENV['SQLITE3_VERSION']
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -21,10 +21,7 @@ Compatibility
|
|
21
21
|
|
22
22
|
Supports mysql, mysql2, postgresql, and sqlite3.
|
23
23
|
|
24
|
-
Currently tested against Rails
|
25
|
-
|
26
|
-
Was also previously tested compatible with 2.3.14, 3.0.17, and 3.1.8 on Ruby 2.0.0
|
27
|
-
or 1.8.7 as appropriate, and may still work for them.
|
24
|
+
Currently tested against Rails 6.1.0.rc1, 6.0.3.4, 5.2.4.4, 5.1.7, and 5.0.7.2, with older gem versions compatible with earlier Rails versions.
|
28
25
|
|
29
26
|
|
30
27
|
Example
|
@@ -53,5 +50,7 @@ Thanks
|
|
53
50
|
|
54
51
|
* Tim Connor (@tlconnor)
|
55
52
|
* Tobias Matthies (@tobmatth)
|
53
|
+
* Phil Ross (@philr)
|
54
|
+
* Jens Schmidt (@w3dot0)
|
56
55
|
|
57
|
-
Copyright (c) 2008-
|
56
|
+
Copyright (c) 2008-2020 Will Bryant, Sekuda Ltd, released under the MIT license
|
data/columns_on_demand.gemspec
CHANGED
@@ -19,16 +19,7 @@ pages since they are not stored wholly in the record's page itself.
|
|
19
19
|
|
20
20
|
Although this plugin is mainly used for BLOB and TEXT columns, it will actually
|
21
21
|
work on all types - and is just as useful for large string fields etc.
|
22
|
-
|
23
|
-
|
24
|
-
Compatibility
|
25
|
-
=============
|
26
|
-
|
27
|
-
Supports mysql, mysql2, postgresql, and sqlite3.
|
28
|
-
|
29
|
-
Currently tested against Rails 3.2.18, 4.0.8, and 4.1.4, on Ruby 2.0.0.
|
30
22
|
EOF
|
31
|
-
gem.has_rdoc = false
|
32
23
|
gem.author = "Will Bryant"
|
33
24
|
gem.email = "will.bryant@gmail.com"
|
34
25
|
gem.homepage = "http://github.com/willbryant/columns_on_demand"
|
@@ -41,8 +32,8 @@ EOF
|
|
41
32
|
|
42
33
|
gem.add_dependency "activerecord"
|
43
34
|
gem.add_development_dependency "rake"
|
44
|
-
gem.add_development_dependency "mysql"
|
45
35
|
gem.add_development_dependency "mysql2"
|
46
36
|
gem.add_development_dependency "pg"
|
47
37
|
gem.add_development_dependency "sqlite3"
|
38
|
+
gem.add_development_dependency "byebug"
|
48
39
|
end
|
data/lib/columns_on_demand.rb
CHANGED
@@ -5,43 +5,18 @@ module ColumnsOnDemand
|
|
5
5
|
self.columns_to_load_on_demand = columns_to_load_on_demand.empty? ? blob_and_text_columns : columns_to_load_on_demand.collect(&:to_s)
|
6
6
|
|
7
7
|
extend ClassMethods
|
8
|
-
|
8
|
+
prepend InstanceMethods
|
9
9
|
|
10
10
|
class <<self
|
11
|
-
|
12
|
-
|
13
|
-
ActiveRecord::AttributeMethods::const_defined?(:Serialization) &&
|
14
|
-
ActiveRecord::AttributeMethods::Serialization::const_defined?(:Attribute))
|
15
|
-
alias_method_chain :define_read_method_for_serialized_attribute, :columns_on_demand
|
16
|
-
end
|
17
|
-
alias_method_chain :reset_column_information, :columns_on_demand
|
18
|
-
end
|
19
|
-
alias_method_chain :attributes, :columns_on_demand
|
20
|
-
alias_method_chain :attribute_names, :columns_on_demand
|
21
|
-
alias_method_chain :read_attribute, :columns_on_demand
|
22
|
-
alias_method_chain :read_attribute_before_type_cast, :columns_on_demand
|
23
|
-
if ActiveRecord::AttributeMethods::Read.instance_methods.include?(:_read_attribute)
|
24
|
-
alias_method_chain :_read_attribute, :columns_on_demand
|
25
|
-
end
|
26
|
-
alias_method_chain :missing_attribute, :columns_on_demand
|
27
|
-
alias_method_chain :reload, :columns_on_demand
|
28
|
-
if ActiveRecord::AttributeMethods::Dirty.instance_methods.include?(:attribute_changed_in_place?)
|
29
|
-
alias_method_chain :attribute_changed_in_place?, :columns_on_demand
|
30
|
-
elsif ActiveRecord::AttributeMethods::Dirty.instance_methods.include?(:changed_attributes)
|
31
|
-
alias_method_chain :changed_in_place?, :columns_on_demand
|
11
|
+
alias reset_column_information_without_columns_on_demand reset_column_information
|
12
|
+
alias reset_column_information reset_column_information_with_columns_on_demand
|
32
13
|
end
|
33
14
|
end
|
34
15
|
|
35
16
|
def reset_column_information_with_columns_on_demand
|
36
|
-
@columns_to_select = nil
|
17
|
+
@columns_to_select = @columns_to_load_by_default = nil
|
37
18
|
reset_column_information_without_columns_on_demand
|
38
19
|
end
|
39
|
-
|
40
|
-
def define_read_method_for_serialized_attribute_with_columns_on_demand(attr_name)
|
41
|
-
define_read_method_for_serialized_attribute_without_columns_on_demand(attr_name)
|
42
|
-
scope = method_defined?(:generated_attribute_methods) ? generated_attribute_methods : self
|
43
|
-
scope.module_eval("def #{attr_name}_with_columns_on_demand; ensure_loaded('#{attr_name}'); #{attr_name}_without_columns_on_demand; end; alias_method_chain :#{attr_name}, :columns_on_demand", __FILE__, __LINE__)
|
44
|
-
end
|
45
20
|
|
46
21
|
def blob_and_text_columns
|
47
22
|
columns.inject([]) do |blob_and_text_columns, column|
|
@@ -54,13 +29,17 @@ module ColumnsOnDemand
|
|
54
29
|
module ClassMethods
|
55
30
|
# this is the method API as called by ActiveRecord 2.x. we also call it ourselves above in our ActiveRecord 3 extensions.
|
56
31
|
def default_select(qualified)
|
57
|
-
@columns_to_select ||=
|
32
|
+
@columns_to_select ||= columns_to_load_by_default.collect {|attr_name| connection.quote_column_name(attr_name)}
|
58
33
|
if qualified
|
59
34
|
quoted_table_name + '.' + @columns_to_select.join(", #{quoted_table_name}.")
|
60
35
|
else
|
61
36
|
@columns_to_select.join(", ")
|
62
37
|
end
|
63
38
|
end
|
39
|
+
|
40
|
+
def columns_to_load_by_default
|
41
|
+
@columns_to_load_by_default ||= Set.new(columns.collect(&:name) - columns_to_load_on_demand)
|
42
|
+
end
|
64
43
|
end
|
65
44
|
|
66
45
|
module InstanceMethods
|
@@ -72,13 +51,17 @@ module ColumnsOnDemand
|
|
72
51
|
!columns_to_load_on_demand.include?(attr_name) || @attributes.key?(attr_name) || new_record? || columns_loaded.include?(attr_name)
|
73
52
|
end
|
74
53
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
54
|
+
def attributes
|
55
|
+
loaded_attributes = @attributes.keys
|
56
|
+
if loaded_attributes.size == self.class.columns_to_load_by_default.size &&
|
57
|
+
loaded_attributes.size == (self.class.columns_to_load_by_default & loaded_attributes).size
|
58
|
+
load_attributes(*columns_to_load_on_demand.reject {|attr_name| column_loaded?(attr_name)})
|
59
|
+
end
|
60
|
+
super
|
78
61
|
end
|
79
62
|
|
80
|
-
def
|
81
|
-
(
|
63
|
+
def attribute_names
|
64
|
+
(super + columns_to_load_on_demand).uniq.sort
|
82
65
|
end
|
83
66
|
|
84
67
|
def load_attributes(*attr_names)
|
@@ -87,42 +70,13 @@ module ColumnsOnDemand
|
|
87
70
|
values = self.class.connection.select_rows(
|
88
71
|
"SELECT #{attr_names.collect {|attr_name| self.class.connection.quote_column_name(attr_name)}.join(", ")}" +
|
89
72
|
" FROM #{self.class.quoted_table_name}" +
|
90
|
-
" WHERE #{self.class.connection.quote_column_name(self.class.primary_key)} = #{self.class.
|
73
|
+
" WHERE #{self.class.connection.quote_column_name(self.class.primary_key)} = #{self.class.connection.quote(id)}")
|
91
74
|
row = values.first || raise(ActiveRecord::RecordNotFound, "Couldn't find #{self.class.name} with ID=#{id}")
|
92
75
|
|
93
76
|
attr_names.each_with_index do |attr_name, i|
|
94
77
|
columns_loaded << attr_name
|
95
78
|
value = row[i]
|
96
|
-
|
97
|
-
if @attributes.respond_to?(:write_from_database)
|
98
|
-
# activerecord 4.2 or later, which make it easy to replicate the normal typecasting and deserialization logic
|
99
|
-
@attributes.write_from_database(attr_name, value)
|
100
|
-
|
101
|
-
elsif coder = self.class.serialized_attributes[attr_name]
|
102
|
-
# activerecord 4.1 or earlier, with a serialized column
|
103
|
-
# for some database adapters, @column_types_override gets populated with type data from query used to load the record originally.
|
104
|
-
# this is fine, but unfortunately some special-case "decorate_columns" code in ActiveRecord will wrap those types in serialization
|
105
|
-
# objects, and it does this for each column listed in @serialized_column_names *even if they are not present in the query results*.
|
106
|
-
# as a result it unfortunately overrides the normal @column_type with a @column_type_override with a nil @column, which explodes
|
107
|
-
# when it tries to run the typecast. make it use the normal @column_type value, since we know that we've loading the regular column.
|
108
|
-
@column_types_override.delete(attr_name) if @column_types_override
|
109
|
-
|
110
|
-
if ActiveRecord.const_defined?(:AttributeMethods) &&
|
111
|
-
ActiveRecord::AttributeMethods::const_defined?(:Serialization) &&
|
112
|
-
ActiveRecord::AttributeMethods::Serialization::const_defined?(:Attribute)
|
113
|
-
# in 3.2 @attributes has a special Attribute struct to help cache both serialized and unserialized forms
|
114
|
-
@attributes[attr_name] = ActiveRecord::AttributeMethods::Serialization::Attribute.new(coder, value, :serialized)
|
115
|
-
elsif ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 1
|
116
|
-
# from 3.1 it has the deserialized form
|
117
|
-
@attributes[attr_name] = coder.load value
|
118
|
-
else
|
119
|
-
# in 2.3 an 3.0, @attributes has the serialized form
|
120
|
-
@attributes[attr_name] = value
|
121
|
-
end
|
122
|
-
else
|
123
|
-
# activerecord 4.1 or earlier, with a regular unserialized column
|
124
|
-
@attributes[attr_name] = value
|
125
|
-
end
|
79
|
+
@attributes.write_from_database(attr_name, value)
|
126
80
|
end
|
127
81
|
end
|
128
82
|
|
@@ -130,39 +84,49 @@ module ColumnsOnDemand
|
|
130
84
|
load_attributes(attr_name.to_s) unless column_loaded?(attr_name.to_s)
|
131
85
|
end
|
132
86
|
|
133
|
-
def
|
134
|
-
column_loaded?(attr_name) &&
|
87
|
+
def changed_in_place?(attr_name)
|
88
|
+
column_loaded?(attr_name) && super(attr_name)
|
89
|
+
end
|
90
|
+
|
91
|
+
def attribute_changed_in_place?(attr_name)
|
92
|
+
column_loaded?(attr_name) && super(attr_name)
|
93
|
+
end
|
94
|
+
|
95
|
+
def read_attribute(attr_name, &block)
|
96
|
+
ensure_loaded(attr_name)
|
97
|
+
super(attr_name, &block)
|
135
98
|
end
|
136
99
|
|
137
|
-
def
|
138
|
-
|
100
|
+
def read_attribute_before_type_cast(attr_name)
|
101
|
+
ensure_loaded(attr_name)
|
102
|
+
super(attr_name)
|
139
103
|
end
|
140
104
|
|
141
|
-
def
|
105
|
+
def _read_attribute(attr_name, &block)
|
142
106
|
ensure_loaded(attr_name)
|
143
|
-
|
107
|
+
super(attr_name, &block)
|
144
108
|
end
|
145
109
|
|
146
|
-
def
|
110
|
+
def write_attribute(attr_name, value)
|
147
111
|
ensure_loaded(attr_name)
|
148
|
-
|
112
|
+
super(attr_name, value)
|
149
113
|
end
|
150
114
|
|
151
|
-
def
|
115
|
+
def _write_attribute(attr_name, value)
|
152
116
|
ensure_loaded(attr_name)
|
153
|
-
|
117
|
+
super(attr_name, value)
|
154
118
|
end
|
155
119
|
|
156
|
-
def
|
120
|
+
def missing_attribute(attr_name, *args)
|
157
121
|
if columns_to_load_on_demand.include?(attr_name)
|
158
122
|
load_attributes(attr_name)
|
159
123
|
else
|
160
|
-
|
124
|
+
super(attr_name, *args)
|
161
125
|
end
|
162
126
|
end
|
163
127
|
|
164
|
-
def
|
165
|
-
|
128
|
+
def reload(*args)
|
129
|
+
super(*args).tap do
|
166
130
|
columns_loaded.clear
|
167
131
|
columns_to_load_on_demand.each do |attr_name|
|
168
132
|
if @attributes.respond_to?(:reset)
|
@@ -177,37 +141,45 @@ module ColumnsOnDemand
|
|
177
141
|
end
|
178
142
|
end
|
179
143
|
|
180
|
-
module
|
181
|
-
def
|
182
|
-
if (selects.empty? || selects == [table[Arel.star]] || selects == ['*']) && klass < ColumnsOnDemand::InstanceMethods
|
183
|
-
build_select_without_columns_on_demand(arel, [default_select(true)])
|
184
|
-
else
|
185
|
-
build_select_without_columns_on_demand(arel, selects)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
module RelationMethodsArity1
|
191
|
-
def build_select_with_columns_on_demand(arel)
|
144
|
+
module RelationMethods
|
145
|
+
def build_select(arel)
|
192
146
|
if (select_values.empty? || select_values == [table[Arel.star]] || select_values == ['*']) && klass < ColumnsOnDemand::InstanceMethods
|
193
147
|
arel.project(*arel_columns([default_select(true)]))
|
194
148
|
else
|
195
|
-
|
149
|
+
super(arel)
|
196
150
|
end
|
197
151
|
end
|
198
152
|
end
|
199
153
|
end
|
200
154
|
|
201
155
|
ActiveRecord::Base.send(:extend, ColumnsOnDemand::BaseMethods)
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
156
|
+
ActiveRecord::Relation.send(:prepend, ColumnsOnDemand::RelationMethods)
|
157
|
+
|
158
|
+
# work around ActiveRecord 5.0 and 5.1 converting uninitialized attributes to value nil on save
|
159
|
+
# (due to dirty.rb mapping @attributes). this is not only a problem for columns_on_demand as it
|
160
|
+
# means that a MissingAttributeError will never be raised after save, but we suffer more.
|
161
|
+
# ActiveRecord 4.2's Attribute doesn't have forgetting_assignment (or this problem).
|
162
|
+
if ActiveRecord.const_defined?(:Attribute) && ActiveRecord::Attribute.uninitialized(nil, nil).try(:forgetting_assignment).try(:initialized?)
|
163
|
+
module ActiveRecord
|
164
|
+
class Attribute # :nodoc:
|
165
|
+
class Uninitialized < Attribute # :nodoc:
|
166
|
+
def forgetting_assignment
|
167
|
+
dup
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
210
171
|
end
|
172
|
+
end
|
211
173
|
|
212
|
-
|
174
|
+
# same for 5.2
|
175
|
+
if ActiveModel.const_defined?(:Attribute) && ActiveModel::Attribute.uninitialized(nil, nil).try(:forgetting_assignment).try(:initialized?)
|
176
|
+
module ActiveModel
|
177
|
+
class Attribute # :nodoc:
|
178
|
+
class Uninitialized < Attribute # :nodoc:
|
179
|
+
def forgetting_assignment
|
180
|
+
dup
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
213
185
|
end
|
@@ -43,7 +43,11 @@ class ColumnsOnDemandTest < ActiveSupport::TestCase
|
|
43
43
|
end
|
44
44
|
|
45
45
|
fixtures :all
|
46
|
-
|
46
|
+
if respond_to?(:use_transactional_tests=)
|
47
|
+
self.use_transactional_tests = true
|
48
|
+
else
|
49
|
+
self.use_transactional_fixtures = true
|
50
|
+
end
|
47
51
|
|
48
52
|
test "it lists explicitly given columns for loading on demand" do
|
49
53
|
assert_equal ["file_data", "processing_log", "original_filename"], Explicit.columns_to_load_on_demand
|
@@ -54,11 +58,11 @@ class ColumnsOnDemandTest < ActiveSupport::TestCase
|
|
54
58
|
end
|
55
59
|
|
56
60
|
test "it selects all the other columns for loading eagerly" do
|
57
|
-
assert_match
|
58
|
-
assert_match
|
61
|
+
assert_match(/\W*id\W*, \W*results\W*, \W*processed_at\W*/, Explicit.default_select(false))
|
62
|
+
assert_match(/\W*explicits\W*.results/, Explicit.default_select(true))
|
59
63
|
|
60
|
-
assert_match
|
61
|
-
assert_match
|
64
|
+
assert_match(/\W*id\W*, \W*original_filename\W*, \W*processed_at\W*/, Implicit.default_select(false))
|
65
|
+
assert_match(/\W*implicits\W*.original_filename/, Implicit.default_select(true))
|
62
66
|
end
|
63
67
|
|
64
68
|
test "it doesn't load the columns_to_load_on_demand straight away when finding the records" do
|
@@ -92,10 +96,10 @@ class ColumnsOnDemandTest < ActiveSupport::TestCase
|
|
92
96
|
|
93
97
|
record = Implicit.first
|
94
98
|
assert_not_loaded record, "file_data"
|
95
|
-
|
99
|
+
assert_nil record.file_data
|
96
100
|
assert_loaded record, "file_data"
|
97
101
|
assert_no_queries do
|
98
|
-
|
102
|
+
assert_nil record.file_data
|
99
103
|
end
|
100
104
|
end
|
101
105
|
|
@@ -132,6 +136,25 @@ class ColumnsOnDemandTest < ActiveSupport::TestCase
|
|
132
136
|
assert !attributes["processing_log"].blank?
|
133
137
|
end
|
134
138
|
end
|
139
|
+
|
140
|
+
test "it doesn't load the column when generating #attributes if not included in the select() list" do
|
141
|
+
attributes = Implicit.select("id, original_filename").first.attributes
|
142
|
+
assert_equal "somefile.txt", attributes["original_filename"]
|
143
|
+
assert !attributes.has_key?("file_data")
|
144
|
+
end
|
145
|
+
|
146
|
+
test "it loads the column when generating #attributes if included in the select() list" do
|
147
|
+
attributes = Implicit.select("id, original_filename, file_data").first.attributes
|
148
|
+
assert_equal "somefile.txt", attributes["original_filename"]
|
149
|
+
assert_equal "This is the file data!", attributes["file_data"]
|
150
|
+
end
|
151
|
+
|
152
|
+
test "it loads the column when changing its value" do
|
153
|
+
record = Implicit.first
|
154
|
+
record.file_data = 'This is the new file data!'
|
155
|
+
assert_equal "This is the file data!", record.file_data_was
|
156
|
+
assert_equal ["This is the file data!", "This is the new file data!"], record.changes[:file_data]
|
157
|
+
end
|
135
158
|
|
136
159
|
test "it loads the column when generating #to_json" do
|
137
160
|
ActiveRecord::Base.include_root_in_json = true
|
@@ -156,8 +179,31 @@ class ColumnsOnDemandTest < ActiveSupport::TestCase
|
|
156
179
|
|
157
180
|
assert_not_loaded record, "file_data"
|
158
181
|
assert_equal "New file data", record.file_data
|
182
|
+
assert_not_equal old_object_id, record.file_data.object_id
|
159
183
|
end
|
160
184
|
|
185
|
+
test "it does not think the column has been loaded if a reloaded instance that has not loaded the attribute is saved" do
|
186
|
+
record = Implicit.first
|
187
|
+
record.file_data = "New file data"
|
188
|
+
record.save!
|
189
|
+
|
190
|
+
record.reload
|
191
|
+
record.save!
|
192
|
+
|
193
|
+
assert_equal "New file data", record.file_data
|
194
|
+
end
|
195
|
+
|
196
|
+
test "it does not think the column has been loaded if a fresh instance that has not loaded the attribute is saved" do
|
197
|
+
record = Implicit.first
|
198
|
+
record.file_data = "New file data"
|
199
|
+
record.save!
|
200
|
+
|
201
|
+
record = Implicit.find(record.id)
|
202
|
+
record.save!
|
203
|
+
|
204
|
+
assert_equal "New file data", record.file_data
|
205
|
+
end
|
206
|
+
|
161
207
|
test "it doesn't override custom select() finds" do
|
162
208
|
record = Implicit.select("id, file_data").first
|
163
209
|
klass = ActiveRecord.const_defined?(:MissingAttributeError) ? ActiveRecord::MissingAttributeError : ActiveModel::MissingAttributeError
|
@@ -194,42 +240,7 @@ class ColumnsOnDemandTest < ActiveSupport::TestCase
|
|
194
240
|
assert_equal "This is the file data!", record.file_data # check it doesn't raise
|
195
241
|
end
|
196
242
|
|
197
|
-
test "it updates the select strings when columns are changed and the column information is reset" do
|
198
|
-
ActiveRecord::Schema.define(:version => 1) do
|
199
|
-
create_table :dummies, :force => true do |t|
|
200
|
-
t.string :some_field
|
201
|
-
t.binary :big_field
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
class Dummy < ActiveRecord::Base
|
206
|
-
columns_on_demand
|
207
|
-
end
|
208
|
-
|
209
|
-
assert_match /\W*id\W*, \W*some_field\W*/, Dummy.default_select(false)
|
210
|
-
|
211
|
-
ActiveRecord::Schema.define(:version => 2) do
|
212
|
-
create_table :dummies, :force => true do |t|
|
213
|
-
t.string :some_field
|
214
|
-
t.binary :big_field
|
215
|
-
t.string :another_field
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
assert_match /\W*id\W*, \W*some_field\W*/, Dummy.default_select(false)
|
220
|
-
Dummy.reset_column_information
|
221
|
-
assert_match /\W*id\W*, \W*some_field\W*, \W*another_field\W*/, Dummy.default_select(false)
|
222
|
-
end
|
223
|
-
|
224
243
|
test "it handles STI models" do
|
225
|
-
ActiveRecord::Schema.define(:version => 1) do
|
226
|
-
create_table :stis, :force => true do |t|
|
227
|
-
t.string :type
|
228
|
-
t.string :some_field
|
229
|
-
t.binary :big_field
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
244
|
class Sti < ActiveRecord::Base
|
234
245
|
columns_on_demand
|
235
246
|
end
|
@@ -238,8 +249,8 @@ class ColumnsOnDemandTest < ActiveSupport::TestCase
|
|
238
249
|
columns_on_demand :some_field
|
239
250
|
end
|
240
251
|
|
241
|
-
assert_match
|
242
|
-
assert_match
|
252
|
+
assert_match(/\W*id\W*, \W*type\W*, \W*some_field\W*/, Sti.default_select(false))
|
253
|
+
assert_match(/\W*id\W*, \W*type\W*, \W*big_field\W*/, StiChild.default_select(false))
|
243
254
|
end
|
244
255
|
|
245
256
|
test "it works on child records loaded from associations" do
|
@@ -279,9 +290,9 @@ class ColumnsOnDemandTest < ActiveSupport::TestCase
|
|
279
290
|
|
280
291
|
assert !ValidatedImplicit.new(:original_filename => "test.txt").valid?
|
281
292
|
instance = ValidatedImplicit.create!(:original_filename => "test.txt", :file_data => "test file data", :results => "test results")
|
282
|
-
instance.
|
293
|
+
assert instance.valid? # file_data and results are already loaded
|
283
294
|
new_instance = ValidatedImplicit.find(instance.id)
|
284
|
-
new_instance.
|
295
|
+
assert new_instance.valid? # file_data and results aren't loaded yet, but will be loaded to validate
|
285
296
|
end
|
286
297
|
|
287
298
|
test "it works with serialized columns" do
|
@@ -322,3 +333,38 @@ class ColumnsOnDemandTest < ActiveSupport::TestCase
|
|
322
333
|
assert_equal select_sql, reference_sql
|
323
334
|
end
|
324
335
|
end
|
336
|
+
|
337
|
+
class ColumnsOnDemandSchemaTest < ActiveSupport::TestCase
|
338
|
+
if respond_to?(:use_transactional_tests=)
|
339
|
+
self.use_transactional_tests = false
|
340
|
+
else
|
341
|
+
self.use_transactional_fixtures = false
|
342
|
+
end
|
343
|
+
|
344
|
+
test "it updates the select strings when columns are changed and the column information is reset" do
|
345
|
+
ActiveRecord::Schema.define(:version => 1) do
|
346
|
+
create_table :dummies, :force => true do |t|
|
347
|
+
t.string :some_field
|
348
|
+
t.binary :big_field
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
class Dummy < ActiveRecord::Base
|
353
|
+
columns_on_demand
|
354
|
+
end
|
355
|
+
|
356
|
+
assert_match(/\W*id\W*, \W*some_field\W*/, Dummy.default_select(false))
|
357
|
+
|
358
|
+
ActiveRecord::Schema.define(:version => 2) do
|
359
|
+
create_table :dummies, :force => true do |t|
|
360
|
+
t.string :some_field
|
361
|
+
t.binary :big_field
|
362
|
+
t.string :another_field
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
assert_match(/\W*id\W*, \W*some_field\W*/, Dummy.default_select(false))
|
367
|
+
Dummy.reset_column_information
|
368
|
+
assert_match(/\W*id\W*, \W*some_field\W*, \W*another_field\W*/, Dummy.default_select(false))
|
369
|
+
end
|
370
|
+
end
|
data/test/schema.rb
CHANGED
data/test_all.sh
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
for version in 5.0.7.2 5.1.7 5.2.4.4
|
6
|
+
do
|
7
|
+
RAILS_VERSION=$version SQLITE3_VERSION=1.3.9 bundle update rails sqlite3
|
8
|
+
RAILS_ENV=sqlite3 bundle exec rake
|
9
|
+
RAILS_ENV=postgresql bundle exec rake
|
10
|
+
RAILS_ENV=mysql2 bundle exec rake
|
11
|
+
done
|
12
|
+
|
13
|
+
for version in 6.0.3.4 6.1.0.rc1
|
14
|
+
do
|
15
|
+
RAILS_VERSION=$version SQLITE3_VERSION=1.4.1 bundle update rails sqlite3
|
16
|
+
RAILS_ENV=sqlite3 bundle exec rake
|
17
|
+
RAILS_ENV=postgresql bundle exec rake
|
18
|
+
RAILS_ENV=mysql2 bundle exec rake
|
19
|
+
done
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: columns_on_demand
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Will Bryant
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-11-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: mysql2
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: pg
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: sqlite3
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: byebug
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -108,20 +108,13 @@ description: |
|
|
108
108
|
|
109
109
|
Although this plugin is mainly used for BLOB and TEXT columns, it will actually
|
110
110
|
work on all types - and is just as useful for large string fields etc.
|
111
|
-
|
112
|
-
|
113
|
-
Compatibility
|
114
|
-
=============
|
115
|
-
|
116
|
-
Supports mysql, mysql2, postgresql, and sqlite3.
|
117
|
-
|
118
|
-
Currently tested against Rails 3.2.18, 4.0.8, and 4.1.4, on Ruby 2.0.0.
|
119
111
|
email: will.bryant@gmail.com
|
120
112
|
executables: []
|
121
113
|
extensions: []
|
122
114
|
extra_rdoc_files: []
|
123
115
|
files:
|
124
116
|
- ".gitignore"
|
117
|
+
- ".travis.yml"
|
125
118
|
- Gemfile
|
126
119
|
- MIT-LICENSE
|
127
120
|
- README.md
|
@@ -138,11 +131,12 @@ files:
|
|
138
131
|
- test/fixtures/parents.yml
|
139
132
|
- test/schema.rb
|
140
133
|
- test/test_helper.rb
|
134
|
+
- test_all.sh
|
141
135
|
homepage: http://github.com/willbryant/columns_on_demand
|
142
136
|
licenses:
|
143
137
|
- MIT
|
144
138
|
metadata: {}
|
145
|
-
post_install_message:
|
139
|
+
post_install_message:
|
146
140
|
rdoc_options: []
|
147
141
|
require_paths:
|
148
142
|
- lib
|
@@ -157,9 +151,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
151
|
- !ruby/object:Gem::Version
|
158
152
|
version: '0'
|
159
153
|
requirements: []
|
160
|
-
|
161
|
-
|
162
|
-
signing_key:
|
154
|
+
rubygems_version: 3.0.3
|
155
|
+
signing_key:
|
163
156
|
specification_version: 4
|
164
157
|
summary: Lazily loads large columns on demand.
|
165
158
|
test_files:
|