riakrest 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,8 @@
1
+ === 0.1.7 2009-12-17
2
+ - Added write data conversion.
3
+
1
4
  === 0.1.6 2009-12-17
2
- - Add method for specifying data conversion in JiakData and JiakResouce.
5
+ - Add method for specifying read data conversion in JiakData and JiakResouce.
3
6
  - Add testing and examples for data conversion.
4
7
 
5
8
  === 0.1.5 2009-12-11
@@ -44,7 +44,7 @@ sudo gem install riakrest
44
44
  class People
45
45
  include JiakResource
46
46
  server 'http://localhost:8002/jiak'
47
- jattr_accessor :name, :age
47
+ attr_accessor :name, :age
48
48
  end
49
49
 
50
50
  # Created and store a resource.
data/Rakefile CHANGED
@@ -20,8 +20,8 @@ Jeweler::Tasks.new do |gem|
20
20
  that gives a true RESTful feel.
21
21
  EOS
22
22
  gem.authors = ["Paul Rogers"]
23
- gem.email = "riak@dingosky.com"
24
- gem.homepage = "http://github.com/wcpr/riakrest"
23
+ gem.email = "paul@riakrest.com"
24
+ gem.homepage = "http://riakrest.com"
25
25
  gem.add_dependency('rest-client', '>= 1.0.0')
26
26
  gem.add_dependency('json', '>= 1.1.9')
27
27
  gem.add_development_dependency "rest-client", ">= 1.0.0"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.6
1
+ 0.1.7
@@ -1,11 +1,12 @@
1
1
  require File.dirname(__FILE__) + '/example_helper.rb'
2
2
  require 'date'
3
3
 
4
- # JiakData class with a couple of attributes, one of which requires conversion
4
+ # JiakData class with a couple of attributes, one with conversion
5
5
  class DateData
6
6
  include JiakData
7
7
  attr_accessor :name, :date
8
- convert :date => lambda{|value| Date.parse(value)}
8
+
9
+ attr_converter :date => { :read => lambda{|value| Date.parse(value)} }
9
10
  end
10
11
 
11
12
  client = JiakClient.new(SERVER_URI)
@@ -23,10 +24,28 @@ puts leap_obj.data.date.inspect # => #<Date: 2008-02-29 (etc.)>
23
24
  client.delete(bucket,leap_obj.key)
24
25
 
25
26
 
26
- # It is also possible to use Ruby JSON processing to achieve a similar result;
27
- # however, this is not optimal as the stored Riak data value contains
28
- # Ruby-secific information which may be undesirable to non-Ruby consumers of
29
- # that data.
27
+ # Alter DateData to store ordinal Date
28
+ class DateData
29
+ attr_converter(:date => {
30
+ :write => lambda {|v| { :year => v.year, :yday => v.yday} },
31
+ :read => lambda {|v| Date::ordinal(v['year'],v['yday'])} } )
32
+ end
33
+ leap_obj = client.store(JiakObject.new(:bucket => bucket,
34
+ :data => leap_2008),
35
+ :return => :object)
36
+ puts leap_obj.data.date.inspect # => #<Date: 2008-02-29 (etc.)>
37
+
38
+ # JSON payload
39
+ # {"name":"Leap 2008","date":{"year":2008,"yday":60}}
40
+
41
+ # Clean-up stored object
42
+ client.delete(bucket,leap_obj.key)
43
+
44
+
45
+ # It is also possible to change the JSON processing of the Ruby Date class to
46
+ # achieve the same results as above. Given the following changes to the Date
47
+ # class, the DateData class could be defined as before, but without any
48
+ # attribute converters.
30
49
 
31
50
  # Instrument the Ruby Date class for round-trip JSON processing.
32
51
  class Date
@@ -47,16 +66,18 @@ end
47
66
 
48
67
  bucket = JiakBucket.new('date data',DateData2)
49
68
 
50
- leap_2012 = DateData2.new(:name => "Leap 2012",
51
- :date => Date.new(2012,02,29))
69
+ leap_2008 = DateData2.new(:name => "Leap 2008",
70
+ :date => Date.new(2008,02,29))
52
71
  leap_obj = client.store(JiakObject.new(:bucket => bucket,
53
- :data => leap_2012),
72
+ :data => leap_2008),
54
73
  :return => :object)
55
- puts leap_obj.data.date.inspect # => #<Date: 2012-02-29 (etc.)>
74
+ puts leap_obj.data.date.inspect # => #<Date: 2008-02-29 (etc.)>
56
75
 
57
- # JSON payload:
58
- # leap_2008 : {"name":"leap","date":"2008-02-29"}
59
- # leap_2012 : {"name":"leap","date":{"json_class":"Date","date":"2012-02-29"}}
76
+ # However, this is not optimal as the data stored in Riak now contains
77
+ # Ruby-secific information which may be undesirable to non-Ruby consumers of
78
+ # the data. For the code above, the JSON payload contains:
79
+ #
80
+ # {"name":"Leap 2008","date":{"json_class":"Date","date":"2008-02-29"}}
60
81
 
61
82
  # Clean-up stored object
62
83
  client.delete(bucket,leap_obj.key)
@@ -1,23 +1,27 @@
1
1
  require File.dirname(__FILE__) + '/example_helper.rb'
2
2
  require 'date'
3
3
 
4
- # JiakResource with a couple of attributes, one of which requires conversion
4
+ # JiakResource with a couple of attributes. Store birthdate as ordinal Date.
5
5
  class Person
6
6
  include JiakResource
7
7
  server SERVER_URI
8
8
  attr_accessor :name, :birthdate
9
- convert :birthdate => lambda{|value| Date.parse(value)}
9
+ attr_converter :birthdate => { :read => lambda{|value| Date.parse(value)} }
10
10
  keygen {name.downcase}
11
11
 
12
+ # Calculate "human" age from birthdate
12
13
  def age
13
14
  now = DateTime.now
14
15
  age = now.year - birthdate.year
15
- age -= 1 if(now.yday < birthdate.yday)
16
+ if((now.month < birthdate.month) or
17
+ (now.month == birthdate.month and now.day < birthdate.day))
18
+ age -= 1
19
+ end
16
20
  age
17
21
  end
18
22
  end
19
23
 
20
- # Create and post resource, showing birthdate is a Date before and after post.
24
+ # The birthdate attribute is a Date before and after post.
21
25
  remy = Person.new(:name => 'Remy',:birthdate => Date.new(1999,06,26))
22
26
  puts remy.birthdate.inspect # => #<Date: 1999-06-26 (etc.)>
23
27
  puts remy.age # => current age
@@ -27,3 +31,59 @@ puts remy.age # => current age
27
31
 
28
32
  remy.delete
29
33
 
34
+ # JSON payload from the HTTP request and response
35
+ # {"name":"Remy","birthdate":"1999-06-26"}
36
+
37
+ class Person
38
+ attr_converter(:birthdate => {
39
+ :write => lambda{|v| {:year => v.year, :yday => v.yday} },
40
+ :read => lambda{|v| Date::ordinal(v['year'],v['yday'])}})
41
+ end
42
+
43
+ # The same code as previous yields the exact same results.
44
+ remy = Person.new(:name => 'Remy',:birthdate => Date.new(1999,06,26))
45
+ puts remy.birthdate.inspect # => #<Date: 1999-06-26 (etc.)>
46
+ puts remy.age # => current age
47
+ remy.post
48
+ puts remy.birthdate.inspect # => #<Date: 1999-06-26 (etc.)>
49
+ puts remy.age # => current age
50
+
51
+ remy.delete
52
+
53
+ # JSON payload from the HTTP request and response with ordinal Date structure
54
+ # {"name":"Remy","birthdate":{"year":1999,"yday":177}}
55
+
56
+
57
+ # It is also possible to change the JSON processing of the Ruby Date class to
58
+ # achieve the same results as above. Given the following changes to the Date
59
+ # class, the Person class could be defined as before, but without any attribute
60
+ # converters.
61
+
62
+ # Instrument the Ruby Date class for round-trip JSON processing.
63
+ class Date
64
+ def to_json(*args)
65
+ { 'json_class' => self.class.name,
66
+ 'date' => to_s
67
+ }.to_json(*args)
68
+ end
69
+ def self.json_create(hash)
70
+ parse(hash['date'])
71
+ end
72
+ end
73
+
74
+ class Person2
75
+ include JiakResource
76
+ server SERVER_URI
77
+ attr_accessor :name, :birthdate
78
+ end
79
+
80
+ remy = Person2.new(:name => 'Remy',:birthdate => Date.new(1999,06,26))
81
+ remy.post
82
+ puts remy.birthdate.inspect # => #<Date: 1999-06-26 (etc.)>
83
+
84
+ # However, this is not optimal as the data stored in Riak now contains
85
+ # Ruby-secific information which may be undesirable to non-Ruby consumers of
86
+ # the data. For the code above, the JSON payload contains:
87
+ #
88
+ # {"name":"Remy","birthdate":{"json_class":"Date","date":"1999-06-26"}}
89
+
@@ -81,6 +81,34 @@ module RiakRest
81
81
  writable *fields
82
82
  end
83
83
 
84
+ # :call-seq:
85
+ # att_converter(hash) -> nil
86
+ #
87
+ # Specify a hash of optional Procs for converting data attribute values
88
+ # during reading and writing data to a Jiak server. Each hash key should
89
+ # be a data class attribute, with an associated value of a hash
90
+ # containing a write and/or a read Proc for use in converting data. Each
91
+ # Procs should accept one argument, the data value actually stored in
92
+ # Riak.
93
+ #
94
+ # ====Example
95
+ #
96
+ # A Person data class that stores a Date in ordinal format:
97
+ #
98
+ # def PersonData
99
+ # include JiakData
100
+ # attr_accessor :name, :birthdate
101
+ # attr_converter(:birthdate => {
102
+ # :write => lambda {|v| { :year => v.year, :yday => v.yday} },
103
+ # :read => lambda {|v| Date::ordinal(v['year'],v['yday'])} } )
104
+ # end
105
+ def attr_converter(hash)
106
+ hash.each do |attr,blks|
107
+ @read_converter[attr] = blks[:read] if(blks[:read])
108
+ @write_converter[attr] = blks[:write] if(blks[:write])
109
+ end
110
+ end
111
+
84
112
  # :call-seq:
85
113
  # allow :f1, ..., :fn -> array
86
114
  # allow [:f1, ..., :fn] -> array
@@ -180,33 +208,12 @@ module RiakRest
180
208
  define_method(:keygen,&block)
181
209
  end
182
210
 
183
- # :call-seq:
184
- # JiakData.convert(hash) -> nil
185
- #
186
- # Specify a hash of optional Procs for converting the data values stored
187
- # in Riak during the process of inflating returned Riak data into Ruby
188
- # objects. The hash values should be Procs used to convert the data
189
- # attribute specified by the hash key. The Procs must accept one
190
- # argument, the data value actually stored in Riak. The converted result
191
- # will be the actual value of the data field inside the inflated Ruby
192
- # object.
193
- #
194
- # ====Example
195
- # def PersonData
196
- # include JiakData
197
- # attr_accessor :name, :birthdate
198
- # convert :birthdate => lambda {|val| Date.parse(val)}
199
- # end
200
- def convert(hash)
201
- @converter ||= {}
202
- hash.each {|k,blk| @converter[k.to_s] = blk}
203
- end
204
-
205
- # Use optional converters to convert returned data values before passing
206
- # to the JiakData constructor.
211
+ # Use optional read converters to convert returned data values before
212
+ # passing to the JiakData constructor.
207
213
  def jiak_create(jiak) # :nodoc:
208
- unless(@converter.nil?)
209
- @converter.each {|k,blk| jiak[k] = blk.call(jiak[k])}
214
+ read_converter.each do |attr,blk|
215
+ key = attr.to_s
216
+ jiak[key] = blk.call(jiak[key])
210
217
  end
211
218
  new(jiak)
212
219
  end
@@ -214,11 +221,27 @@ module RiakRest
214
221
  end
215
222
 
216
223
  def self.included(including_class) # :nodoc:
217
- including_class.extend(ClassMethods)
224
+ including_class.instance_eval do
225
+ extend ClassMethods
226
+
227
+ def read_converter
228
+ @read_converter
229
+ end
230
+ @read_converter = {}
231
+
232
+ def write_converter
233
+ @write_converter
234
+ end
235
+ @write_converter = {}
236
+ end
218
237
 
219
238
  define_method(:to_jiak) do
220
- self.class.schema.write_mask.inject({}) do |build,field|
221
- build[field] = send("#{field}")
239
+ self.class.schema.write_mask.inject({}) do |build,attr|
240
+ val = send("#{attr}")
241
+ if(self.class.write_converter[attr])
242
+ val = self.class.write_converter[attr].call(val)
243
+ end
244
+ build[attr] = val
222
245
  build
223
246
  end
224
247
  end
@@ -135,17 +135,16 @@ module RiakRest
135
135
  end
136
136
 
137
137
  # :call-seq:
138
- # JiakResource.convert(hash)
139
- #
140
- # Specify a hash of optional Procs for converting the data values stored
141
- # in Riak during the process of inflating returned Riak data into
142
- # JiakResource objects. The hash values should be Procs used to convert
143
- # the data attribute specified by the hash key. The Procs must accept one
144
- # argument, the data value actually stored in Riak. The converted result
145
- # will be the actual value of the data field inside the inflated
146
- # JiakResource.
147
- def convert(hash)
148
- jiak.data.convert(hash)
138
+ # attr_converter(hash)
139
+ #
140
+ # Specify a hash of optional Procs for converting data attribute values
141
+ # during reading and writing data to a Jiak server. Each hash key should
142
+ # be a data class attribute, with an associated value of a hash
143
+ # containing a write and/or a read Proc for use in converting data. Each
144
+ # Procs should accept one argument, the data value actually stored in
145
+ # Riak.
146
+ def attr_converter(hash)
147
+ jiak.data.attr_converter(hash)
149
148
  end
150
149
 
151
150
  # :call-seq:
@@ -11,7 +11,9 @@ require 'date'
11
11
  class DateData
12
12
  include JiakData
13
13
  attr_accessor :name, :date
14
- convert :date => lambda { |v| Date.parse(v) }
14
+ attr_converter(:date => {
15
+ :write => lambda {|v| { :year => v.year, :yday => v.yday} },
16
+ :read => lambda {|v| Date::ordinal(v['year'],v['yday'])} } )
15
17
  end
16
18
 
17
19
  class PersonData
@@ -325,7 +325,9 @@ describe "JiakResource data conversion" do
325
325
  server SERVER_URI
326
326
  group 'dogs'
327
327
  attr_accessor :name, :birthdate
328
- convert :birthdate => lambda{|value| Date.parse(value)}
328
+ attr_converter(:birthdate => {
329
+ :write => lambda{|v| {:year => v.year, :yday => v.yday} },
330
+ :read => lambda{|v| Date::ordinal(v['year'],v['yday'])}})
329
331
  keygen { name }
330
332
  auto_manage
331
333
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riakrest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Rogers
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-16 00:00:00 -08:00
12
+ date: 2009-12-17 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -73,7 +73,7 @@ dependencies:
73
73
  version: 1.2.9
74
74
  version:
75
75
  description: " RiakRest provides structured, RESTful interaction with\n the HTTP/JSON interface of a Riak[http://riak.basho.com] document data\n store. RiakRest provides two levels of interaction: Core Client and\n Resource. Core Client works at the Jiak level and exposes Jiak\n internals. JiakResource is an abstraction built on top of the Core Client\n that gives a true RESTful feel.\n"
76
- email: riak@dingosky.com
76
+ email: paul@riakrest.com
77
77
  executables: []
78
78
 
79
79
  extensions: []
@@ -123,7 +123,7 @@ files:
123
123
  - spec/spec.opts
124
124
  - spec/spec_helper.rb
125
125
  has_rdoc: true
126
- homepage: http://github.com/wcpr/riakrest
126
+ homepage: http://riakrest.com
127
127
  licenses: []
128
128
 
129
129
  post_install_message: