georgepalmer-couch_foo 0.7.3 → 0.7.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/README.rdoc +1 -1
- data/VERSION.yml +1 -1
- data/lib/couch_foo/attribute_methods.rb +37 -14
- data/lib/couch_foo/base.rb +19 -36
- data/lib/couch_foo/view_methods.rb +1 -0
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -35,7 +35,7 @@ Basic operations are the same as ActiveRecord:
|
|
35
35
|
class Address < CouchFoo::Base
|
36
36
|
property :number, Integer
|
37
37
|
property :street, String
|
38
|
-
property :postcode # Any generic type is fine as long as .to_json can be called on it
|
38
|
+
property :postcode # Any generic type is fine as long as .to_json and class.from_json(json) can be called on it
|
39
39
|
end
|
40
40
|
|
41
41
|
address1 = Address.create(:number => 3, :street => "My Street", :postcode => "secret") # Create address
|
data/VERSION.yml
CHANGED
@@ -191,15 +191,7 @@ module CouchFoo
|
|
191
191
|
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
|
192
192
|
# "2004-12-12" in a data type is cast to a date object, like Date.new(2004, 12, 12)).
|
193
193
|
def read_attribute(attr_name)
|
194
|
-
|
195
|
-
if type = type_for_property(attr_name.to_sym)
|
196
|
-
convert_to_type(value, type)
|
197
|
-
else
|
198
|
-
value
|
199
|
-
end
|
200
|
-
else
|
201
|
-
nil
|
202
|
-
end
|
194
|
+
convert_to_type(@attributes[attr_name.to_s], type_for_property(attr_name.to_sym))
|
203
195
|
end
|
204
196
|
|
205
197
|
def read_attribute_before_type_cast(attr_name)
|
@@ -211,7 +203,7 @@ module CouchFoo
|
|
211
203
|
def write_attribute(attr_name, value)
|
212
204
|
attr_name = attr_name.to_s
|
213
205
|
@attributes_cache.delete(attr_name)
|
214
|
-
@attributes[attr_name] = value
|
206
|
+
@attributes[attr_name] = convert_to_json(value, type_for_property(attr_name.to_sym))
|
215
207
|
end
|
216
208
|
|
217
209
|
def query_attribute(attr_name)
|
@@ -259,15 +251,46 @@ module CouchFoo
|
|
259
251
|
end
|
260
252
|
|
261
253
|
protected
|
262
|
-
|
254
|
+
def convert_to_json(value, type)
|
255
|
+
return nil if value.nil?
|
256
|
+
|
257
|
+
#Not keen on type hack for case statement
|
258
|
+
case type.to_s
|
259
|
+
when "String"
|
260
|
+
value.to_s
|
261
|
+
when "Integer"
|
262
|
+
value.to_i
|
263
|
+
when "Float"
|
264
|
+
value.to_f
|
265
|
+
when "DateTime"
|
266
|
+
DateTime.parse(value.to_s).strftime("%Y/%m/%d %H:%M:%S +0000")
|
267
|
+
when "Time"
|
268
|
+
Time.at(value.to_f).strftime("%Y/%m/%d %H:%M:%S +0000")
|
269
|
+
when "Date"
|
270
|
+
Date.new(value.year, value.month, value.day).strftime("%Y/%m/%d %H:%M:%S +0000")
|
271
|
+
when "TrueClass"
|
272
|
+
convert_boolean(value)
|
273
|
+
when "Boolean"
|
274
|
+
convert_boolean(value)
|
275
|
+
else
|
276
|
+
# Calling to_json on Array or Hash makes them strings = bad
|
277
|
+
if value.is_a?(Array) || value.is_a?(Hash)
|
278
|
+
value
|
279
|
+
else
|
280
|
+
value.to_json rescue value
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
# Converts a value to its type, or if not specified tries calling from_json on the value before
|
263
286
|
# falling back on just using the value
|
264
287
|
def convert_to_type(value, type)
|
265
288
|
return nil if value.nil?
|
266
|
-
|
289
|
+
|
267
290
|
#Not keen on type hack for case statement
|
268
291
|
case type.to_s
|
269
292
|
when "String"
|
270
|
-
value
|
293
|
+
value.to_s
|
271
294
|
when "Integer"
|
272
295
|
value.to_i
|
273
296
|
when "Float"
|
@@ -283,7 +306,7 @@ module CouchFoo
|
|
283
306
|
when "Boolean"
|
284
307
|
convert_boolean(value)
|
285
308
|
else
|
286
|
-
value
|
309
|
+
type.from_json(value) rescue value
|
287
310
|
end
|
288
311
|
end
|
289
312
|
|
data/lib/couch_foo/base.rb
CHANGED
@@ -109,7 +109,7 @@ module CouchFoo
|
|
109
109
|
# class Address < CouchFoo::Base
|
110
110
|
# property :number, Integer
|
111
111
|
# property :street, String
|
112
|
-
# property :postcode # Any generic type is fine as long as .to_json can be called on it
|
112
|
+
# property :postcode # Any generic type is fine as long as .to_json and class.from_json(json) can be called on it
|
113
113
|
# end
|
114
114
|
#
|
115
115
|
# Documents have three more properties that get added automatically. _id and _rev are CouchDB
|
@@ -1030,9 +1030,11 @@ module CouchFoo
|
|
1030
1030
|
|
1031
1031
|
# Set a property for the document. These can be passed a type and options hash. If no type
|
1032
1032
|
# is passed a #to_json method is called on the ruby object and the result stored in the
|
1033
|
-
# database.
|
1034
|
-
#
|
1035
|
-
#
|
1033
|
+
# database. When it is retrieved from the database a class.from_json(json) method is called
|
1034
|
+
# on it or if that doesn't exist it just uses the value. If a type is passed then the object
|
1035
|
+
# is cast before storing in the database. This does not guarantee that the object is the
|
1036
|
+
# correct type (use the validaters for that), it merely tries to convert the current type to
|
1037
|
+
# the desired one - for example:
|
1036
1038
|
# '123' => 123 # useful
|
1037
1039
|
# 'a' => 0 # probably not desired behaviour
|
1038
1040
|
# The later would fail with a validator
|
@@ -1046,10 +1048,11 @@ module CouchFoo
|
|
1046
1048
|
# property :number, Integer
|
1047
1049
|
# property :paid, TrueClass, :default => false
|
1048
1050
|
# property :notes, String
|
1049
|
-
# property :acl
|
1051
|
+
# property :acl # or acl, Object is equivalent
|
1052
|
+
# property :price, Price
|
1050
1053
|
# end
|
1051
|
-
def property(name, type =
|
1052
|
-
logger.warn("Using type as a
|
1054
|
+
def property(name, type = Object, options = {})
|
1055
|
+
logger.warn("Using type as a property name may issue unexpected behaviour") if name == :type
|
1053
1056
|
properties.delete_if{|e| e.name == name} # Subset properties override
|
1054
1057
|
properties << Property.new(name, type, options[:default])
|
1055
1058
|
end
|
@@ -1295,25 +1298,17 @@ module CouchFoo
|
|
1295
1298
|
allocate
|
1296
1299
|
end
|
1297
1300
|
|
1298
|
-
object.instance_variable_set("@attributes",
|
1301
|
+
object.instance_variable_set("@attributes", check_document_attributes(document))
|
1299
1302
|
object.instance_variable_set("@attributes_cache", Hash.new)
|
1300
1303
|
object
|
1301
1304
|
end
|
1302
1305
|
|
1303
|
-
# Checks that the document only contains types that are listed as properties
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
if (type == Date || type == DateTime || type == Time)
|
1310
|
-
record[property.to_s] = type.send(:parse, value) rescue nil
|
1311
|
-
else
|
1312
|
-
# Seems pointless but ensures we get attributes for properties that have been added to
|
1313
|
-
# model since document last saved
|
1314
|
-
record[property.to_s] = value
|
1315
|
-
end
|
1316
|
-
end
|
1306
|
+
# Checks that the document only contains types that are listed as properties
|
1307
|
+
def check_document_attributes(record)
|
1308
|
+
# Add new properties
|
1309
|
+
(property_names.map{|p| p.to_s} - record.keys).each {|k| record[k] = nil}
|
1310
|
+
|
1311
|
+
# Remove old properties
|
1317
1312
|
record.reject!{|key, value| !(unchangeable_property_names + property_names).include?(key.to_sym)}
|
1318
1313
|
record
|
1319
1314
|
end
|
@@ -1941,7 +1936,7 @@ module CouchFoo
|
|
1941
1936
|
|
1942
1937
|
def update
|
1943
1938
|
begin
|
1944
|
-
response = self.class.database.save(
|
1939
|
+
response = self.class.database.save(attributes_before_type_cast)
|
1945
1940
|
@attributes["_rev"] = response['rev']
|
1946
1941
|
1
|
1947
1942
|
rescue Exception => e
|
@@ -1953,7 +1948,7 @@ module CouchFoo
|
|
1953
1948
|
def create
|
1954
1949
|
@attributes["_id"] = self.class.get_uuid
|
1955
1950
|
begin
|
1956
|
-
response = self.class.database.save(
|
1951
|
+
response = self.class.database.save(attributes_before_type_cast.reject{|key,value| key == "_rev"})
|
1957
1952
|
@attributes["_rev"] = response['rev']
|
1958
1953
|
@new_record = false
|
1959
1954
|
@attributes["_id"]
|
@@ -1964,18 +1959,6 @@ module CouchFoo
|
|
1964
1959
|
end
|
1965
1960
|
end
|
1966
1961
|
|
1967
|
-
# Attributes but with date/time types convert to JSON sortable format. This creates a copy of
|
1968
|
-
# the original attributes for saving so doesn't alter the attributes accessible to the user
|
1969
|
-
def attributes_for_save
|
1970
|
-
attrs = attributes
|
1971
|
-
self.class.property_types.each do |name, type|
|
1972
|
-
if (type == Date || type == DateTime || type == Time)
|
1973
|
-
attrs[name.to_s] = attrs[name.to_s].strftime("%Y/%m/%d %H:%M:%S +0000") if attrs[name.to_s]
|
1974
|
-
end
|
1975
|
-
end
|
1976
|
-
attrs
|
1977
|
-
end
|
1978
|
-
|
1979
1962
|
# Sets the attribute used for inheritance to this class name if this is not the CouchFoo::Base
|
1980
1963
|
# descendent. Considering the hierarchy Reply < Message < ActiveRecord::Base, this makes it
|
1981
1964
|
# possible to do Reply.new without having to set <tt>Reply[Reply.inheritance_column] = "Reply"</tt>
|
@@ -122,6 +122,7 @@ module CouchFoo
|
|
122
122
|
search_fields = options.delete(:use_key)
|
123
123
|
if search_fields
|
124
124
|
search_fields = [search_fields] unless search_fields.is_a?(Array)
|
125
|
+
search_fields = search_fields.sort_by{|f| f.to_s}
|
125
126
|
else
|
126
127
|
search_fields = options[:conditions].to_a.sort_by{|f| f.first.to_s}.map(&:first)
|
127
128
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: georgepalmer-couch_foo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- George Palmer
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-02-
|
12
|
+
date: 2009-02-06 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|