document_record 0.0.14 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,28 +1,67 @@
1
1
  require 'document_hash'
2
+ require 'bson'
2
3
 
3
4
  module DocumentRecord
4
5
  module Serializer
5
- def self.dump object
6
- Base64.encode64 Marshal.dump object
6
+ MARSHALL_VERSION = 0
7
+ MESSAGEPACK_VERSION = 1
8
+ DEFAULT_VERSION = 1
9
+
10
+ def self.dump object, options = {}
11
+ version = DEFAULT_VERSION
12
+ version = options[:force_version] if options.has_key? :force_version
13
+
14
+ binary_dump =
15
+ case version
16
+ when 0 then
17
+ Marshal.dump object
18
+ when 1 then
19
+ object.to_hash.to_bson
20
+ else
21
+ raise "No serialization version found: #{ version }"
22
+ end
23
+
24
+ unless options.has_key? :no_version and options[:no_version]
25
+ stamp = [68, 82, version].pack 'c2S' # DR<version> In 4 bits
26
+ binary_dump.insert( 0, stamp )
27
+ end
28
+
29
+ Base64.encode64 binary_dump
7
30
  end
8
31
  def self.load data
9
- Marshal.load Base64.decode64 data rescue nil
32
+ decoded = Base64.decode64 data rescue nil
33
+ version = 0
34
+
35
+ if decoded.start_with? "DR" # Has version Stamp
36
+ version = decoded[2,2].unpack('S').pop # Gets the Version
37
+ decoded[0...4] = '' # Removes version stamp
38
+ end
39
+
40
+ case version
41
+ when 0 then
42
+ Marshal.load decoded rescue nil
43
+ when 1 then
44
+ Hash.from_bson( StringIO.new( decoded ) )
45
+ else
46
+ raise "Unrecognized version #{version}"
47
+ end
10
48
  end
11
49
  end
12
50
 
13
51
  module Base
14
52
  extend ActiveSupport::Concern
15
53
 
16
- def document_field name
54
+ def document_field name, options = {}
17
55
  raise "Field must exist in record in order to become a document field" unless column_names.include? name.to_s
18
- @@_document_field_name = name
19
- @@_index_fields ||= []
20
-
21
56
  class_eval do
22
57
  alias_method :regular_assign_attributes, :assign_attributes
23
58
  alias_method :regular_method_missing, :method_missing
24
59
  alias_method :regular_save, :save
25
60
 
61
+ @@_document_field_name = name
62
+ @@_schema_fields = options[:schema_fields] || []
63
+ @@_index_fields ||= []
64
+
26
65
  def read_serialized_hash_attribute field_name
27
66
  raw = read_attribute field_name
28
67
  raw && Serializer.load( raw ) || {}
@@ -61,7 +100,7 @@ module DocumentRecord
61
100
  end
62
101
 
63
102
  def touch!
64
- document.touch!
103
+ self.document.touch!
65
104
  save
66
105
  end
67
106
 
@@ -71,15 +110,37 @@ module DocumentRecord
71
110
 
72
111
  def assign_attributes new_attributes, options
73
112
  new_attributes.each do | key, value |
74
- self.send "#{key}=".to_sym, value
113
+ assign_key = :"#{key}="
114
+ method_missing assign_key, value
115
+ self.send assign_key, value if self.respond_to? assign_key
75
116
  end
76
117
  end
77
118
 
78
119
  def method_missing method, *args
79
120
  if method =~ /(.*)=$/
80
- document[$1] = args.shift
121
+ write_document $1, args.shift
122
+ else
123
+ read_document method.to_s
124
+ end
125
+ end
126
+
127
+ def is_schema_field? attribute
128
+ @@_schema_fields.include? attribute.to_sym
129
+ end
130
+
131
+ def read_document attribute
132
+ if is_schema_field? attribute
133
+ read_attribute attribute
134
+ else
135
+ document[attribute] || read_attribute(attribute)
136
+ end
137
+ end
138
+
139
+ def write_document attribute, value
140
+ if is_schema_field? attribute
141
+ write_attribute attribute, value
81
142
  else
82
- document[method.to_s]
143
+ document[attribute] = value
83
144
  end
84
145
  end
85
146
 
@@ -88,17 +149,61 @@ module DocumentRecord
88
149
  end
89
150
 
90
151
  def as_json options = {}
91
- ( read_serialized_hash_attribute(@@_document_field_name) || {} ).merge(super.reject{ |k, v| k === @@_document_field_name.to_s })
152
+ included_fields = super.select{ |k, v|
153
+ @@_schema_fields.include?( k.to_sym )
154
+ }.stringify_keys!
155
+
156
+ document.to_hash( stringify_keys: true ).
157
+ merge( included_fields ).
158
+ merge( method_values(options) )
159
+ end
160
+
161
+ def method_values options
162
+ {}.tap do | result |
163
+ return result unless options[:methods].is_a? Array
164
+ options[:methods].each do | method |
165
+ result[method] = self.__send__(method)
166
+ end
167
+ end
168
+ end
169
+
170
+
171
+ def _deep_key_values hash = nil, path = []
172
+ hash = document.to_hash unless hash
173
+ result = []
174
+
175
+ hash.each do | k, v |
176
+ current = path.dup
177
+
178
+ current << k
179
+ if v.is_a? Hash
180
+ result += _deep_key_values hash[ k ], current
181
+ else
182
+ result += [ current.join("_"), v ]
183
+ end
184
+ end
185
+ result
186
+ end
187
+
188
+ def deep_key_values
189
+ Hash[*_deep_key_values]
92
190
  end
93
- end
191
+
192
+ def deep_keys
193
+ deep_key_values.keys
194
+ end
195
+ end
94
196
 
95
197
  column_names.each do |column|
96
198
  class_eval <<-METHOD
97
199
  def #{column}
98
- document["#{column}"] || read_attribute("#{column}")
200
+ # document["#{column}"] || read_attribute("#{column}")
201
+ read_document "#{ column }"
99
202
  end
203
+
100
204
  def #{column}= value
101
- document["#{column}"] = value
205
+ # document["#{column}"] = value
206
+ write_document "#{ column }", value
102
207
  end
103
208
  METHOD
104
209
  end
@@ -1,3 +1,3 @@
1
1
  module DocumentRecord
2
- VERSION = "0.0.14"
2
+ VERSION = "0.0.17"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: document_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.14
4
+ version: 0.0.17
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-08 00:00:00.000000000 Z
12
+ date: 2015-05-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: document_hash
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 0.0.13
21
+ version: 0.0.15
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: 0.0.13
29
+ version: 0.0.15
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rails
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
45
  version: 3.2.11
46
+ - !ruby/object:Gem::Dependency
47
+ name: bson
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 3.0.1
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 3.0.1
46
62
  - !ruby/object:Gem::Dependency
47
63
  name: sqlite3
48
64
  requirement: !ruby/object:Gem::Requirement