cosine-active_record_encoding 0.9.3 → 0.9.4
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/lib/active_record_encoding.rb +85 -59
- metadata +1 -1
@@ -7,64 +7,49 @@
|
|
7
7
|
#
|
8
8
|
# ActiveRecordEncoding — Module to make ActiveRecord aware of Unicode
|
9
9
|
# encoding issues on Ruby 1.9. This software is not supported on Ruby
|
10
|
-
# 1.8 at all, and never will be. It should be used only if the
|
11
|
-
# underlying database does not or cannot properly handle
|
12
|
-
# data
|
13
|
-
# can properly encode data, so your first assumption
|
14
|
-
# do not need this software unless you really know
|
10
|
+
# 1.8 at all, and probably never will be. It should be used only if the
|
11
|
+
# underlying database and its driver does not or cannot properly handle
|
12
|
+
# the encoding of the data it returns (usually as "ASCII-8BIT"). Most
|
13
|
+
# databases can properly encode data, however, so your first assumption
|
14
|
+
# should be that you do not need this software unless you really know
|
15
|
+
# you need it.
|
15
16
|
#
|
16
|
-
# ActiveRecordEncoding keeps two variables
|
17
|
-
#
|
17
|
+
# ActiveRecordEncoding keeps two variables for each column and table
|
18
|
+
# where encoding is requested: a required external_encoding value and
|
19
|
+
# an optional internal_encoding value.
|
18
20
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
+
# External encodings must be defined for each column or table where
|
22
|
+
# a translation is to occur, and this is done in the model definition:
|
21
23
|
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
24
|
+
# class User < ActiveRecord::Base
|
25
|
+
# external_encoding 'ISO-8859-1', :for => :comment
|
26
|
+
# external_encoding 'ISO-8859-1', :for => [:first_name, :last_name]
|
27
|
+
# end
|
25
28
|
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
+
# A similar internal_encoding method exists and specifies what encoding
|
30
|
+
# to use internally for each column or table, but this may also be set
|
31
|
+
# systemwide in the Rails environment files:
|
29
32
|
#
|
30
|
-
#
|
31
|
-
# returned by ActiveRecord from String-based columns. The
|
32
|
-
# external_encoding value tells ActiveRecord how the database is
|
33
|
-
# actually encoding the data that is being returned as "ASCII-8BIT".
|
34
|
-
# A conversion is done if necessary.
|
33
|
+
# ActiveRecordEncoding.internal_encoding = 'UTF-8'
|
35
34
|
#
|
36
35
|
# When data is being saved back to the database, the internal_encoding
|
37
36
|
# value is ignored and the encoding of the input is used to determine
|
38
|
-
# how to
|
39
|
-
#
|
40
|
-
# Encodings may also be defined on a table-by-table basis or
|
41
|
-
# a column-by-column basis in the model definition.
|
37
|
+
# how to convert data to the external_encoding.
|
42
38
|
#
|
43
39
|
module ActiveRecordEncoding
|
44
|
-
|
45
40
|
class << self
|
46
|
-
attr_accessor :
|
47
|
-
|
48
|
-
|
49
|
-
#
|
50
|
-
# Set both ActiveRecordEncoding.external_encoding and
|
51
|
-
# ActiveRecordEncoding.internal_encoding in a single method.
|
52
|
-
#
|
53
|
-
# ActiveRecordEncoding.encoding = 'UTF-8'
|
54
|
-
#
|
55
|
-
def encoding= (new_encoding)
|
56
|
-
@internal_encoding = @external_encoding = new_encoding
|
41
|
+
attr_accessor :internal_encoding
|
42
|
+
alias :encoding= :internal_encoding=
|
57
43
|
end
|
58
|
-
module_function :encoding=
|
59
44
|
end
|
60
45
|
|
61
46
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
47
|
+
#
|
48
|
+
# StandardClassMethods defines class methods for inclusion in
|
49
|
+
# ActiveRecord::Base in order to provide the user interface for
|
50
|
+
# ActiveRecordEncoding.
|
51
|
+
#
|
52
|
+
module ActiveRecordEncoding::StandardClassMethods
|
68
53
|
|
69
54
|
#
|
70
55
|
# Set the external_encoding value for this model class.
|
@@ -85,6 +70,9 @@ module ActiveRecordEncoding::ActiveRecordExtensionClassMethods
|
|
85
70
|
# end
|
86
71
|
#
|
87
72
|
def external_encoding (new_encoding, options = {})
|
73
|
+
extend ActiveRecordEncoding::ExtendedClassMethods
|
74
|
+
include ActiveRecordEncoding::IncludedInstanceMethods
|
75
|
+
|
88
76
|
if attr_names = options[:for]
|
89
77
|
[*attr_names].each do |attr_name|
|
90
78
|
active_record_encodings[attr_name.to_s][:ext] = new_encoding
|
@@ -113,6 +101,9 @@ module ActiveRecordEncoding::ActiveRecordExtensionClassMethods
|
|
113
101
|
# end
|
114
102
|
#
|
115
103
|
def internal_encoding (new_encoding, options = {})
|
104
|
+
extend ActiveRecordEncoding::ExtendedClassMethods
|
105
|
+
include ActiveRecordEncoding::IncludedInstanceMethods
|
106
|
+
|
116
107
|
if attr_names = options[:for]
|
117
108
|
[*attr_names].each do |attr_name|
|
118
109
|
active_record_encodings[attr_name.to_s][:int] = new_encoding
|
@@ -142,6 +133,9 @@ module ActiveRecordEncoding::ActiveRecordExtensionClassMethods
|
|
142
133
|
# end
|
143
134
|
#
|
144
135
|
def encoding (new_encoding, options = {})
|
136
|
+
extend ActiveRecordEncoding::ExtendedClassMethods
|
137
|
+
include ActiveRecordEncoding::IncludedInstanceMethods
|
138
|
+
|
145
139
|
if attr_names = options[:for]
|
146
140
|
[*attr_names].each do |attr_name|
|
147
141
|
active_record_encodings[attr_name.to_s] =
|
@@ -153,10 +147,23 @@ module ActiveRecordEncoding::ActiveRecordExtensionClassMethods
|
|
153
147
|
end
|
154
148
|
end
|
155
149
|
|
150
|
+
end # ActiveRecordEncoding::StandardClassMethods
|
151
|
+
|
152
|
+
|
153
|
+
#
|
154
|
+
# ExtendedClassMethods defines class methods for inclusion in
|
155
|
+
# models sub-classed from ActiveRecord::Base to do the dirty work. It
|
156
|
+
# is only included in models that use ActiveRecordEncoding.
|
157
|
+
#
|
158
|
+
module ActiveRecordEncoding::ExtendedClassMethods
|
159
|
+
|
160
|
+
def active_record_encodings #:nodoc:
|
161
|
+
@active_record_encodings ||= Hash.new { |h, k| h[k] = Hash.new }
|
162
|
+
end
|
163
|
+
|
156
164
|
def active_record_external_encoding (attr_name = nil) #:nodoc:
|
157
165
|
active_record_encodings[attr_name][:ext] ||
|
158
|
-
@active_record_external_encoding
|
159
|
-
ActiveRecordEncoding.external_encoding
|
166
|
+
@active_record_external_encoding
|
160
167
|
end
|
161
168
|
|
162
169
|
def active_record_internal_encoding (attr_name = nil) #:nodoc:
|
@@ -172,6 +179,7 @@ module ActiveRecordEncoding::ActiveRecordExtensionClassMethods
|
|
172
179
|
# Redefine the attribute read method to do the conversion.
|
173
180
|
def encoding_aware_define_read_method (symbol, attr_name, column) #:nodoc:
|
174
181
|
pre_encoding_aware_define_read_method(symbol, attr_name, column)
|
182
|
+
return if active_record_external_encoding(attr_name).nil?
|
175
183
|
method_name = "encoding_aware_attr_#{symbol}".to_sym
|
176
184
|
old_method_name = "pre_#{method_name}".to_sym
|
177
185
|
code = <<-__EOM__
|
@@ -181,25 +189,42 @@ module ActiveRecordEncoding::ActiveRecordExtensionClassMethods
|
|
181
189
|
alias_method "pre_#{method_name}".to_sym, symbol
|
182
190
|
alias_method symbol, method_name
|
183
191
|
end
|
184
|
-
end
|
185
192
|
|
193
|
+
end # ActiveRecordEncoding::ExtendedClassMethods
|
186
194
|
|
187
|
-
class ActiveRecord::Base #:nodoc:
|
188
|
-
extend ActiveRecordEncoding::ActiveRecordExtensionClassMethods
|
189
195
|
|
190
|
-
|
191
|
-
|
192
|
-
|
196
|
+
#
|
197
|
+
# IncludedInstanceMethods defines instance methods for inclusion in
|
198
|
+
# models sub-classed from ActiveRecord::Base to do the dirty work. It
|
199
|
+
# is only included in models that use ActiveRecordEncoding.
|
200
|
+
#
|
201
|
+
module ActiveRecordEncoding::IncludedInstanceMethods
|
202
|
+
|
203
|
+
def self.included (model_class) #:nodoc:
|
204
|
+
class << model_class
|
205
|
+
alias_method :pre_encoding_aware_define_read_method, :define_read_method
|
206
|
+
alias_method :define_read_method, :encoding_aware_define_read_method
|
207
|
+
end
|
208
|
+
|
209
|
+
model_class.class_eval do
|
210
|
+
alias_method :pre_encoding_aware_read_attribute, :read_attribute
|
211
|
+
alias_method :read_attribute, :encoding_aware_read_attribute
|
212
|
+
end
|
193
213
|
end
|
194
214
|
|
195
215
|
# Method that casts the Binary data into Unicode, if necessary.
|
196
216
|
def encoding_aware_attribute_cast! (attr_name, value) #:nodoc:
|
197
|
-
if value.
|
198
|
-
value.
|
199
|
-
ext_encoding = self.class.active_record_external_encoding(attr_name) \
|
217
|
+
if not value.frozen? and
|
218
|
+
not value.instance_variable_get(:@active_record_encoded) \
|
200
219
|
then
|
201
|
-
|
202
|
-
|
220
|
+
if value.respond_to? :encoding and
|
221
|
+
ext_encoding = self.class.active_record_external_encoding(attr_name) \
|
222
|
+
then
|
223
|
+
int_encoding = self.class.active_record_internal_encoding(attr_name)
|
224
|
+
value.force_encoding(ext_encoding).encode!(int_encoding)
|
225
|
+
end
|
226
|
+
|
227
|
+
value.instance_variable_set(:@active_record_encoded, true)
|
203
228
|
end
|
204
229
|
|
205
230
|
value
|
@@ -239,6 +264,7 @@ class ActiveRecord::Base #:nodoc:
|
|
239
264
|
end
|
240
265
|
end
|
241
266
|
|
242
|
-
|
243
|
-
|
244
|
-
|
267
|
+
end # ActiveRecordEncoding::IncludedInstanceMethods
|
268
|
+
|
269
|
+
|
270
|
+
ActiveRecord::Base.extend ActiveRecordEncoding::StandardClassMethods
|