zeng 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/README.md +67 -0
  2. data/Rakefile +21 -19
  3. data/book.rb +23 -0
  4. data/{init.rb → lib/zeng.rb} +5 -1
  5. data/lib/{cute_kv → zeng}/adapters/tokyo_cabinet.rb +7 -6
  6. data/lib/zeng/adapters/tokyo_tyrant.rb +30 -0
  7. data/lib/zeng/connector.rb +28 -0
  8. data/lib/{cute_kv → zeng}/document.rb +7 -12
  9. data/lib/{cute_kv → zeng}/indexer.rb +2 -2
  10. data/spec/case/document_test.rb +174 -174
  11. data/spec/case/indexer_test.rb +31 -31
  12. data/spec/helper.rb +12 -14
  13. data/spec/model/Account.rb +3 -3
  14. data/spec/model/Book.rb +2 -2
  15. data/spec/model/Friend.rb +3 -3
  16. data/spec/model/Icon.rb +3 -3
  17. data/spec/model/Project.rb +2 -2
  18. data/spec/model/User.rb +3 -4
  19. metadata +26 -49
  20. data/README.rdoc +0 -89
  21. data/lib/cute_kv/adapters/light_cloud.rb +0 -22
  22. data/lib/cute_kv/adapters/tokyo_tyrant.rb +0 -22
  23. data/lib/cute_kv/associations.rb +0 -285
  24. data/lib/cute_kv/connector.rb +0 -27
  25. data/lib/cute_kv/ext/string.rb +0 -34
  26. data/lib/cute_kv/ext/symbol.rb +0 -9
  27. data/lib/cute_kv/serialization.rb +0 -95
  28. data/lib/cute_kv/serializers/json_serializer.rb +0 -75
  29. data/lib/cute_kv/serializers/xml_serializer.rb +0 -325
  30. data/lib/cute_kv/timestamp.rb +0 -56
  31. data/lib/cute_kv/validations.rb +0 -68
  32. data/lib/cutekv.rb +0 -17
  33. data/spec/asso.yml +0 -23
  34. data/spec/asso_sin_plural.yml +0 -36
  35. data/spec/case/associations_test.rb +0 -313
  36. data/spec/case/document_docking_test.rb +0 -103
  37. data/spec/case/serialization_test.rb +0 -78
  38. data/spec/case/sin_plu_dic_test.rb +0 -29
  39. data/spec/case/symmetry_test.rb +0 -80
  40. data/spec/case/timestamp_test.rb +0 -65
  41. data/spec/case/validations_test.rb +0 -74
  42. data/spec/light_cloud.yml +0 -9
  43. data/spec/model/Topic.rb +0 -26
  44. data/tags +0 -322
@@ -1,27 +0,0 @@
1
- module CuteKV
2
- class Connector
3
- def self.config(adapter)
4
- case adapter.to_sym
5
- when :TC
6
- require 'cute_kv/adapters/tokyo_cabinet'
7
- include CuteKV::Adapters::TokyoCabinet
8
- when :TT
9
- require 'cute_kv/adapters/tokyo_tyrant'
10
- include CuteKV::Adapters::TokyoTyrant
11
- when :LC
12
- require 'cute_kv/adapters/light_cloud'
13
- include CuteKV::Adapters::TokyoCloud
14
- else
15
- raise ConfigError,'没有指定数据库类型!'
16
- end
17
- end
18
-
19
- def initialize(adapter, conf)
20
- @adapter = adapter
21
- self.class.config(adapter)
22
- establish(conf)
23
- end
24
-
25
- end
26
-
27
- end
@@ -1,34 +0,0 @@
1
- class String
2
-
3
- def plural?
4
- (Dic::PLU_WORDS.include?(self) || self.pluralize == self) && !Dic::SIN_WORDS.include?(self)
5
- end
6
-
7
- def singular?
8
- (Dic::SIN_WORDS.include?(self) || self.singularize == self) && !Dic::PLU_WORDS.include?(self)
9
- end
10
-
11
- end
12
-
13
- module WordAct
14
- def add(words)
15
- if words.is_a? Array
16
- words.each {|w| self.add(w.to_s)}
17
- else
18
- self << words.to_s
19
- Dic::Mirror[self].delete(words.to_s)
20
- self.uniq!
21
- end
22
- end
23
-
24
- def hash
25
- self.object_id
26
- end
27
- end
28
-
29
- module Dic
30
- (SIN_WORDS = []).extend(WordAct)
31
- (PLU_WORDS = []).extend(WordAct)
32
- Mirror = {SIN_WORDS=>PLU_WORDS, PLU_WORDS=>SIN_WORDS}
33
- end
34
-
@@ -1,9 +0,0 @@
1
- class Symbol
2
- def plural?
3
- self.to_s.plural?
4
- end
5
-
6
- def singular?
7
- self.to_s.singular?
8
- end
9
- end
@@ -1,95 +0,0 @@
1
- module CuteKV#:nodoc:
2
- module Serialization
3
- class Serializer #:nodoc:
4
- attr_reader :options
5
-
6
- def initialize(object, options = {})
7
- @object, @options = object, options.dup
8
- end
9
-
10
- # To replicate the behavior in ActiveObject#attributes,
11
- # <tt>:except</tt> takes precedence over <tt>:only</tt>. If <tt>:only</tt> is not set
12
- # for a N level model but is set for the N+1 level models,
13
- # then because <tt>:except</tt> is set to a default value, the second
14
- # level model can have both <tt>:except</tt> and <tt>:only</tt> set. So if
15
- # <tt>:only</tt> is set, always delete <tt>:except</tt>.
16
- def serializable_attribute_names
17
- attribute_names = @object.assigned_attributes.collect {|n| n.to_s} << "id"
18
-
19
- if options[:only]
20
- options.delete(:except)
21
- attribute_names = attribute_names & Array(options[:only]).collect { |n| n.to_s }
22
- else
23
- options[:except] = Array(options[:except])
24
- attribute_names = attribute_names - options[:except].collect { |n| n.to_s }
25
- end
26
-
27
- attribute_names
28
- end
29
-
30
- def serializable_method_names
31
- Array(options[:methods]).inject([]) do |method_attributes, name|
32
- method_attributes << name if @object.respond_to?(name.to_s)
33
- method_attributes
34
- end
35
- end
36
-
37
- def serializable_names
38
- serializable_attribute_names + serializable_method_names
39
- end
40
-
41
- # Add associations specified via the <tt>:includes</tt> option.
42
- # Expects a block that takes as arguments:
43
- # +association+ - name of the association
44
- # +objects+ - the association object(s) to be serialized
45
- # +opts+ - options for the association objects
46
- def add_includes(&block)
47
- if include_associations = options.delete(:include)
48
- base_only_or_except = { :except => options[:except],
49
- :only => options[:only] }
50
-
51
- include_has_options = include_associations.is_a?(Hash)
52
- associations = include_has_options ? include_associations.keys : Array(include_associations)
53
-
54
- for association in associations
55
- objects = @object.send association
56
-
57
- unless objects.nil?
58
- association_options = include_has_options ? include_associations[association] : base_only_or_except
59
- opts = options.merge(association_options)
60
- yield(association, objects, opts)
61
- end
62
- end
63
-
64
- options[:include] = include_associations
65
- end
66
- end
67
-
68
- def serializable_object
69
- returning(serializable_object = {}) do
70
- serializable_names.each { |name| serializable_object[name] = @object.send(name) }
71
-
72
- add_includes do |association, objects, opts|
73
- if objects.is_a?(Enumerable)
74
- serializable_object[association] = objects.collect { |r| self.class.new(r, opts).serializable_object }
75
- else
76
- serializable_object[association] = self.class.new(objects, opts).serializable_object
77
- end
78
-
79
- end
80
- end
81
- end
82
-
83
- def serialize
84
- # overwrite to implement
85
- end
86
-
87
- def to_s(&block)
88
- serialize(&block)
89
- end
90
- end
91
- end
92
- end
93
-
94
- require 'cute_kv/serializers/xml_serializer'
95
- require 'cute_kv/serializers/json_serializer'
@@ -1,75 +0,0 @@
1
- module CuteKV#:nodoc:
2
- module Serialization
3
- def self.included(base)
4
- base.cattr_accessor :include_root_in_json, :instance_writer => false
5
- base.extend ClassMethods
6
- end
7
-
8
- # Returns a JSON string representing the model. Some configuration is
9
- # available through +options+.
10
- #
11
- # Without any +options+, the returned JSON string will include all
12
- # the model's attributes. For example:
13
- #
14
- # konata = User.find(1)
15
- # konata.to_json
16
- # # => {"id": 1, "name": "Konata Izumi", "age": 16,
17
- # "created_at": "2006/08/01", "awesome": true}
18
- #
19
- # The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the attributes
20
- # included, and work similar to the +attributes+ method. For example:
21
- #
22
- # konata.to_json(:only => [ :id, :name ])
23
- # # => {"id": 1, "name": "Konata Izumi"}
24
- #
25
- # konata.to_json(:except => [ :id, :created_at, :age ])
26
- # # => {"name": "Konata Izumi", "awesome": true}
27
- #
28
- # To include any methods on the model, use <tt>:methods</tt>.
29
- #
30
- # konata.to_json(:methods => :permalink)
31
- # # => {"id": 1, "name": "Konata Izumi", "age": 16,
32
- # "created_at": "2006/08/01", "awesome": true,
33
- # "permalink": "1-konata-izumi"}
34
- #
35
- # To include associations, use <tt>:include</tt>.
36
- #
37
- # konata.to_json(:include => :posts)
38
- # # => {"id": 1, "name": "Konata Izumi", "age": 16,
39
- # "created_at": "2006/08/01", "awesome": true,
40
- # "posts": [{"id": 1, "author_id": 1, "title": "Welcome to the weblog"},
41
- # {"id": 2, author_id: 1, "title": "So I was thinking"}]}
42
- #
43
- # 2nd level and higher order associations work as well:
44
- #
45
- # konata.to_json(:include => { :posts => {
46
- # :include => { :comments => {
47
- # :only => :body } },
48
- # :only => :title } })
49
- # # => {"id": 1, "name": "Konata Izumi", "age": 16,
50
- # "created_at": "2006/08/01", "awesome": true,
51
- # "posts": [{"comments": [{"body": "1st post!"}, {"body": "Second!"}],
52
- # "title": "Welcome to the weblog"},
53
- # {"comments": [{"body": "Don't think too hard"}],
54
- # "title": "So I was thinking"}]}
55
- def to_json(options = {})
56
- if include_root_in_json
57
- "{#{self.class.json_class_name}: #{JsonSerializer.new(self, options).to_s}}"
58
- else
59
- JsonSerializer.new(self, options).to_s
60
- end
61
- end
62
-
63
- class JsonSerializer < CuteKV::Serialization::Serializer #:nodoc:
64
- def serialize
65
- serializable_object.to_json
66
- end
67
- end
68
-
69
- module ClassMethods
70
- def json_class_name
71
- @json_class_name ||= name.demodulize.underscore.inspect
72
- end
73
- end
74
- end
75
- end
@@ -1,325 +0,0 @@
1
- module CuteKV#:nodoc:
2
- module Serialization
3
- # Builds an XML document to represent the model. Some configuration is
4
- # available through +options+. However more complicated cases should
5
- # override ActiveObject::Base#to_xml.
6
- #
7
- # By default the generated XML document will include the processing
8
- # instruction and all the object's attributes. For example:
9
- #
10
- # <?xml version="1.0" encoding="UTF-8"?>
11
- # <topic>
12
- # <title>The First Topic</title>
13
- # <author-name>David</author-name>
14
- # <id type="integer">1</id>
15
- # <approved type="boolean">false</approved>
16
- # <replies-count type="integer">0</replies-count>
17
- # <bonus-time type="datetime">2000-01-01T08:28:00+12:00</bonus-time>
18
- # <written-on type="datetime">2003-07-16T09:28:00+1200</written-on>
19
- # <content>Have a nice day</content>
20
- # <author-email-address>david@loudthinking.com</author-email-address>
21
- # <parent-id></parent-id>
22
- # <last-read type="date">2004-04-15</last-read>
23
- # </topic>
24
- #
25
- # This behavior can be controlled with <tt>:only</tt>, <tt>:except</tt>,
26
- # <tt>:skip_instruct</tt>, <tt>:skip_types</tt> and <tt>:dasherize</tt>.
27
- # The <tt>:only</tt> and <tt>:except</tt> options are the same as for the
28
- # +attributes+ method. The default is to dasherize all column names, but you
29
- # can disable this setting <tt>:dasherize</tt> to +false+. To not have the
30
- # column type included in the XML output set <tt>:skip_types</tt> to +true+.
31
- #
32
- # For instance:
33
- #
34
- # topic.to_xml(:skip_instruct => true, :except => [ :id, :bonus_time, :written_on, :replies_count ])
35
- #
36
- # <topic>
37
- # <title>The First Topic</title>
38
- # <author-name>David</author-name>
39
- # <approved type="boolean">false</approved>
40
- # <content>Have a nice day</content>
41
- # <author-email-address>david@loudthinking.com</author-email-address>
42
- # <parent-id></parent-id>
43
- # <last-read type="date">2004-04-15</last-read>
44
- # </topic>
45
- #
46
- # To include first level associations use <tt>:include</tt>:
47
- #
48
- # firm.to_xml :include => [ :account, :clients ]
49
- #
50
- # <?xml version="1.0" encoding="UTF-8"?>
51
- # <firm>
52
- # <id type="integer">1</id>
53
- # <rating type="integer">1</rating>
54
- # <name>37signals</name>
55
- # <clients type="array">
56
- # <client>
57
- # <rating type="integer">1</rating>
58
- # <name>Summit</name>
59
- # </client>
60
- # <client>
61
- # <rating type="integer">1</rating>
62
- # <name>Microsoft</name>
63
- # </client>
64
- # </clients>
65
- # <account>
66
- # <id type="integer">1</id>
67
- # <credit-limit type="integer">50</credit-limit>
68
- # </account>
69
- # </firm>
70
- #
71
- # To include deeper levels of associations pass a hash like this:
72
- #
73
- # firm.to_xml :include => {:account => {}, :clients => {:include => :address}}
74
- # <?xml version="1.0" encoding="UTF-8"?>
75
- # <firm>
76
- # <id type="integer">1</id>
77
- # <rating type="integer">1</rating>
78
- # <name>37signals</name>
79
- # <clients type="array">
80
- # <client>
81
- # <rating type="integer">1</rating>
82
- # <name>Summit</name>
83
- # <address>
84
- # ...
85
- # </address>
86
- # </client>
87
- # <client>
88
- # <rating type="integer">1</rating>
89
- # <name>Microsoft</name>
90
- # <address>
91
- # ...
92
- # </address>
93
- # </client>
94
- # </clients>
95
- # <account>
96
- # <id type="integer">1</id>
97
- # <credit-limit type="integer">50</credit-limit>
98
- # </account>
99
- # </firm>
100
- #
101
- # To include any methods on the model being called use <tt>:methods</tt>:
102
- #
103
- # firm.to_xml :methods => [ :calculated_earnings, :real_earnings ]
104
- #
105
- # <firm>
106
- # # ... normal attributes as shown above ...
107
- # <calculated-earnings>100000000000000000</calculated-earnings>
108
- # <real-earnings>5</real-earnings>
109
- # </firm>
110
- #
111
- # To call any additional Procs use <tt>:procs</tt>. The Procs are passed a
112
- # modified version of the options hash that was given to +to_xml+:
113
- #
114
- # proc = Proc.new { |options| options[:builder].tag!('abc', 'def') }
115
- # firm.to_xml :procs => [ proc ]
116
- #
117
- # <firm>
118
- # # ... normal attributes as shown above ...
119
- # <abc>def</abc>
120
- # </firm>
121
- #
122
- # Alternatively, you can yield the builder object as part of the +to_xml+ call:
123
- #
124
- # firm.to_xml do |xml|
125
- # xml.creator do
126
- # xml.first_name "David"
127
- # xml.last_name "Heinemeier Hansson"
128
- # end
129
- # end
130
- #
131
- # <firm>
132
- # # ... normal attributes as shown above ...
133
- # <creator>
134
- # <first_name>David</first_name>
135
- # <last_name>Heinemeier Hansson</last_name>
136
- # </creator>
137
- # </firm>
138
- #
139
- # As noted above, you may override +to_xml+ in your ActiveObject::Base
140
- # subclasses to have complete control about what's generated. The general
141
- # form of doing this is:
142
- #
143
- # class IHaveMyOwnXML < ActiveObject::Base
144
- # def to_xml(options = {})
145
- # options[:indent] ||= 2
146
- # xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
147
- # xml.instruct! unless options[:skip_instruct]
148
- # xml.level_one do
149
- # xml.tag!(:second_level, 'content')
150
- # end
151
- # end
152
- # end
153
- def to_xml(options = {}, &block)
154
- serializer = XmlSerializer.new(self, options)
155
- block_given? ? serializer.to_s(&block) : serializer.to_s
156
- end
157
-
158
- end
159
-
160
- class XmlSerializer < CuteKV::Serialization::Serializer #:nodoc:
161
- def builder
162
- @builder ||= begin
163
- options[:indent] ||= 2
164
- builder = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
165
-
166
- unless options[:skip_instruct]
167
- builder.instruct!
168
- options[:skip_instruct] = true
169
- end
170
-
171
- builder
172
- end
173
- end
174
-
175
- def root
176
- root = (options[:root] || @object.class.to_s.underscore).to_s
177
- dasherize? ? root.dasherize : root
178
- end
179
-
180
- def dasherize?
181
- !options.has_key?(:dasherize) || options[:dasherize]
182
- end
183
-
184
- def serializable_attributes
185
- serializable_attribute_names.collect { |name| Attribute.new(name.to_s, @object) }
186
- end
187
-
188
- def serializable_method_attributes
189
- Array(options[:methods]).inject([]) do |method_attributes, name|
190
- method_attributes << MethodAttribute.new(name.to_s, @object) if @object.respond_to?(name.to_s)
191
- method_attributes
192
- end
193
- end
194
-
195
- def add_attributes
196
- (serializable_attributes + serializable_method_attributes).each do |attribute|
197
- add_tag(attribute)
198
- end
199
- end
200
-
201
- def add_procs
202
- if procs = options.delete(:procs)
203
- [ *procs ].each do |proc|
204
- proc.call(options)
205
- end
206
- end
207
- end
208
-
209
- def add_tag(attribute)
210
- builder.tag!(
211
- dasherize? ? attribute.name.dasherize : attribute.name,
212
- attribute.value.to_s,
213
- attribute.decorations(!options[:skip_types])
214
- )
215
- end
216
-
217
- def add_associations(association, objects, opts)
218
- if objects.is_a?(Enumerable)
219
- tag = association.to_s
220
- tag = tag.dasherize if dasherize?
221
- if objects.empty?
222
- builder.tag!(tag, :type => :array)
223
- else
224
- builder.tag!(tag, :type => :array) do
225
- association_name = association.to_s.singularize
226
- objects.each do |object|
227
- object.to_xml opts.merge(
228
- :root => association_name,
229
- :type => (object.class.to_s.underscore == association_name ? nil : object.class.name)
230
- )
231
- end
232
- end
233
- end
234
- else
235
- if object = @object.send(association)
236
- object.to_xml(opts.merge(:root => association))
237
- end
238
- end
239
- end
240
-
241
- def serialize
242
- args = [root]
243
- if options[:namespace]
244
- args << {:xmlns=>options[:namespace]}
245
- end
246
-
247
- if options[:type]
248
- args << {:type=>options[:type]}
249
- end
250
-
251
- builder.tag!(*args) do
252
- add_attributes
253
- procs = options.delete(:procs)
254
- add_includes { |association, objects, opts| add_associations(association, objects, opts) }
255
- options[:procs] = procs
256
- add_procs
257
- yield builder if block_given?
258
- end
259
- end
260
-
261
- class Attribute #:nodoc:
262
- attr_reader :name, :value, :type
263
-
264
- def initialize(name, object)
265
- @name, @object = name, object
266
-
267
- @type = compute_type
268
- @value = compute_value
269
- end
270
-
271
- # There is a significant speed improvement if the value
272
- # does not need to be escaped, as <tt>tag!</tt> escapes all values
273
- # to ensure that valid XML is generated. For known binary
274
- # values, it is at least an order of magnitude faster to
275
- # Base64 encode binary values and directly put them in the
276
- # output XML than to pass the original value or the Base64
277
- # encoded value to the <tt>tag!</tt> method. It definitely makes
278
- # no sense to Base64 encode the value and then give it to
279
- # <tt>tag!</tt>, since that just adds additional overhead.
280
- def needs_encoding?
281
- ![ :binary, :date, :datetime, :boolean, :float, :integer ].include?(type)
282
- end
283
-
284
- def decorations(include_types = true)
285
- decorations = {}
286
-
287
- if type == :binary
288
- decorations[:encoding] = 'base64'
289
- end
290
-
291
- if include_types && type != :string
292
- decorations[:type] = type
293
- end
294
-
295
- if value.nil?
296
- decorations[:nil] = true
297
- end
298
-
299
- decorations
300
- end
301
-
302
- protected
303
- def compute_type
304
- type = @object.send(name).class
305
- end
306
-
307
- def compute_value
308
- value = @object.send(name)
309
-
310
- if formatter = Hash::XML_FORMATTING[type.to_s]
311
- value ? formatter.call(value) : nil
312
- else
313
- value
314
- end
315
- end
316
- end
317
-
318
- class MethodAttribute < Attribute #:nodoc:
319
- protected
320
- def compute_type
321
- Hash::XML_TYPE_NAMES[@object.send(name).class.name] || :string
322
- end
323
- end
324
- end
325
- end