yaml_record 0.0.1
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/.gitignore +5 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +22 -0
- data/README.md +76 -0
- data/Rakefile +10 -0
- data/lib/yaml_record/base.rb +371 -0
- data/lib/yaml_record/version.rb +3 -0
- data/lib/yaml_record.rb +10 -0
- data/test/base_test.rb +187 -0
- data/test/test_helper.rb +16 -0
- data/yaml_record.gemspec +25 -0
- metadata +125 -0
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2011, Nico Taing, Miso, Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# YAML RECORD #
|
2
|
+
|
3
|
+
## Introduction ##
|
4
|
+
|
5
|
+
YAML Record allows you to persist data to a yaml file and manage it with activemodel API
|
6
|
+
|
7
|
+
## Installation ##
|
8
|
+
|
9
|
+
gem install yaml_record
|
10
|
+
|
11
|
+
## Usage ##
|
12
|
+
|
13
|
+
To use YAML Record add gem to your Gemfile
|
14
|
+
|
15
|
+
# Gemfile
|
16
|
+
gem 'yaml_record'
|
17
|
+
|
18
|
+
Next define your YAML Record class
|
19
|
+
|
20
|
+
class Post < YamlRecord::Base
|
21
|
+
# Declare your properties
|
22
|
+
properties :title, :body, :user_id
|
23
|
+
|
24
|
+
# Declare source file path
|
25
|
+
source Rails.root.join("config/posts")
|
26
|
+
end
|
27
|
+
|
28
|
+
Use as any activerecord object.
|
29
|
+
|
30
|
+
Retrieve all items:
|
31
|
+
|
32
|
+
Post.all => [@p1, @p2]
|
33
|
+
|
34
|
+
Retrieve item by ID:
|
35
|
+
|
36
|
+
Post.find("a1b2") => @p1
|
37
|
+
|
38
|
+
Retrieve by attribute
|
39
|
+
|
40
|
+
Post.find_by_attribute(:title, "some title") => @p
|
41
|
+
|
42
|
+
Initialize post:
|
43
|
+
|
44
|
+
@p = Post.new(:title => "...", :body => "...", :user_id => 5)
|
45
|
+
|
46
|
+
Save post:
|
47
|
+
|
48
|
+
@p.save
|
49
|
+
# or Post.create(:title => "...", :body => "...", :user_id => 5)
|
50
|
+
|
51
|
+
Access attributes
|
52
|
+
|
53
|
+
@p = Post.find("a1b2")
|
54
|
+
@p.title => "..."
|
55
|
+
|
56
|
+
Assign attributes
|
57
|
+
|
58
|
+
@p.title = "new title"
|
59
|
+
|
60
|
+
Update attributes
|
61
|
+
|
62
|
+
@p.update_attributes(:title => "new title")
|
63
|
+
|
64
|
+
Destroy record
|
65
|
+
|
66
|
+
@p.destroy
|
67
|
+
|
68
|
+
## Contributors ##
|
69
|
+
|
70
|
+
Created at Miso by Nico Taing and Nathan Esquenazi
|
71
|
+
|
72
|
+
Contributors are welcome!
|
73
|
+
|
74
|
+
## License ##
|
75
|
+
|
76
|
+
YAML Record is Copyright © 2011 Nico Taing, Miso. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
|
data/Rakefile
ADDED
@@ -0,0 +1,371 @@
|
|
1
|
+
module YamlRecord
|
2
|
+
class Base
|
3
|
+
attr_accessor :attributes, :is_created, :is_destroyed
|
4
|
+
|
5
|
+
include ActiveSupport::Callbacks
|
6
|
+
define_callbacks :before_save, :after_save, :before_destroy, :after_destroy, :before_validation, :before_create, :after_create
|
7
|
+
|
8
|
+
before_create :set_id!
|
9
|
+
|
10
|
+
# Constructs a new YamlRecord instance based on specified attribute hash
|
11
|
+
#
|
12
|
+
# === Example:
|
13
|
+
#
|
14
|
+
# class Post < YamlRecord::Base; properties :foo; end
|
15
|
+
#
|
16
|
+
# Post.new(:foo => "bar")
|
17
|
+
#
|
18
|
+
def initialize(attr_hash={})
|
19
|
+
attr_hash.symbolize_keys!
|
20
|
+
attr_hash.reverse_merge!(self.class.properties.inject({}) { |result, key| result[key] = nil; result })
|
21
|
+
|
22
|
+
self.attributes ||= {}
|
23
|
+
self.is_created = attr_hash.delete(:persisted) || false
|
24
|
+
self.setup_properties!
|
25
|
+
attr_hash.each do |k,v|
|
26
|
+
self.send("#{k}=", v) # self.attributes[:media] = "foo"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Accesses given attribute from YamlRecord instance
|
31
|
+
#
|
32
|
+
# === Example:
|
33
|
+
#
|
34
|
+
# @post[:foo] => "bar"
|
35
|
+
#
|
36
|
+
def [](attribute)
|
37
|
+
self.attributes[attribute]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Assign given attribute from YamlRecord instance with specified value
|
41
|
+
#
|
42
|
+
# === Example:
|
43
|
+
#
|
44
|
+
# @post[:foo] = "baz"
|
45
|
+
#
|
46
|
+
def []=(attribute, value)
|
47
|
+
self.attributes[attribute] = value
|
48
|
+
end
|
49
|
+
|
50
|
+
# Saved YamlRecord instance to file
|
51
|
+
# Executes save and create callbacks
|
52
|
+
# Returns true if record saved; false otherwise
|
53
|
+
#
|
54
|
+
# === Example:
|
55
|
+
#
|
56
|
+
# @post.save => true
|
57
|
+
#
|
58
|
+
def save
|
59
|
+
run_callbacks(:before_save)
|
60
|
+
run_callbacks(:before_create) unless self.is_created
|
61
|
+
|
62
|
+
existing_items = self.class.all
|
63
|
+
if self.new_record?
|
64
|
+
existing_items << self
|
65
|
+
else # update existing record
|
66
|
+
updated_item = existing_items.find { |item| item.id == self.id }
|
67
|
+
return false unless updated_item
|
68
|
+
updated_item.attributes = self.attributes
|
69
|
+
end
|
70
|
+
|
71
|
+
raw_data = existing_items ? existing_items.map { |item| item.persisted_attributes } : []
|
72
|
+
self.class.write_contents(raw_data) if self.valid?
|
73
|
+
|
74
|
+
run_callbacks(:after_create) unless self.is_created
|
75
|
+
run_callbacks(:after_save)
|
76
|
+
true
|
77
|
+
rescue IOError
|
78
|
+
false
|
79
|
+
end
|
80
|
+
|
81
|
+
# Update YamlRecord instance with specified attributes
|
82
|
+
# Returns true if record updated; false otherwise
|
83
|
+
#
|
84
|
+
# === Example:
|
85
|
+
#
|
86
|
+
# @post.update_attributes(:foo => "baz", :miso => "awesome") => true
|
87
|
+
#
|
88
|
+
def update_attributes(updated_attrs={})
|
89
|
+
updated_attrs.each { |k,v| self.send("#{k}=", v) }
|
90
|
+
self.save
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns array of instance attributes names; An attribute is a value stored for this record (persisted or not)
|
94
|
+
#
|
95
|
+
# === Example:
|
96
|
+
#
|
97
|
+
# @post.column_names => ["foo", "miso"]
|
98
|
+
#
|
99
|
+
def column_names
|
100
|
+
array = []
|
101
|
+
self.attributes.each_key { |k| array << k.to_s }
|
102
|
+
array
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns hash of attributes to be persisted to file.
|
106
|
+
# A persisted attribute is a value stored in the file (specified with the properties declaration)
|
107
|
+
#
|
108
|
+
# === Example:
|
109
|
+
#
|
110
|
+
# class Post < YamlRecord::Base; properties :foo, :miso; end
|
111
|
+
# @post = Post.create(:foo => "bar", :miso => "great")
|
112
|
+
# @post.persisted_attributes => { :id => "a1b2c3", :foo => "bar", :miso => "great" }
|
113
|
+
#
|
114
|
+
def persisted_attributes
|
115
|
+
self.attributes.slice(*self.class.properties).reject { |k, v| v.nil? }
|
116
|
+
end
|
117
|
+
|
118
|
+
# Returns true if YamlRecord instance hasn't persisted; false otherwise
|
119
|
+
#
|
120
|
+
# === Example:
|
121
|
+
#
|
122
|
+
# @post = Post.new(:foo => "bar", :miso => "great")
|
123
|
+
# @post.new_record? => true
|
124
|
+
# @post.save => true
|
125
|
+
# @post.new_record? => false
|
126
|
+
#
|
127
|
+
def new_record?
|
128
|
+
!self.is_created
|
129
|
+
end
|
130
|
+
|
131
|
+
# Returns true if YamlRecord instance has been destroyed; false otherwise
|
132
|
+
#
|
133
|
+
# === Example:
|
134
|
+
#
|
135
|
+
# @post = Post.new(:foo => "bar", :miso => "great")
|
136
|
+
# @post.destroyed? => false
|
137
|
+
# @post.save
|
138
|
+
# @post.destroy => true
|
139
|
+
# @post.destroyed? => true
|
140
|
+
#
|
141
|
+
def destroyed?
|
142
|
+
self.is_destroyed
|
143
|
+
end
|
144
|
+
|
145
|
+
# Remove a persisted YamlRecord object
|
146
|
+
# Returns true if destroyed; false otherwise
|
147
|
+
#
|
148
|
+
# === Example:
|
149
|
+
#
|
150
|
+
# @post = Post.create(:foo => "bar", :miso => "great")
|
151
|
+
# Post.all.size => 1
|
152
|
+
# @post.destroy => true
|
153
|
+
# Post.all.size => 0
|
154
|
+
#
|
155
|
+
def destroy
|
156
|
+
run_callbacks(:before_destroy)
|
157
|
+
new_data = self.class.all.reject { |item| item.persisted_attributes == self.persisted_attributes }.map { |item| item.persisted_attributes }
|
158
|
+
self.class.write_contents(new_data)
|
159
|
+
self.is_destroyed = true
|
160
|
+
run_callbacks(:after_destroy)
|
161
|
+
true
|
162
|
+
rescue IOError
|
163
|
+
false
|
164
|
+
end
|
165
|
+
|
166
|
+
# Execute validations for instance
|
167
|
+
# Returns true if record is valid; false otherwise
|
168
|
+
# TODO Implement validation
|
169
|
+
#
|
170
|
+
# === Example:
|
171
|
+
#
|
172
|
+
# @post.valid? => true
|
173
|
+
#
|
174
|
+
def valid?
|
175
|
+
true
|
176
|
+
end
|
177
|
+
|
178
|
+
# Returns errors messages if record isn't valid; empty array otherwise
|
179
|
+
# TODO Implement validation
|
180
|
+
#
|
181
|
+
# === Example:
|
182
|
+
#
|
183
|
+
# @post.errors => ["Foo can't be blank"]
|
184
|
+
#
|
185
|
+
def errors
|
186
|
+
[]
|
187
|
+
end
|
188
|
+
|
189
|
+
# Returns YamlRecord Instance
|
190
|
+
# Complies with ActiveModel api
|
191
|
+
#
|
192
|
+
# === Example:
|
193
|
+
#
|
194
|
+
# @post.to_model => @post
|
195
|
+
#
|
196
|
+
def to_model
|
197
|
+
self
|
198
|
+
end
|
199
|
+
|
200
|
+
# Reload YamlRecord instance attributes from file
|
201
|
+
#
|
202
|
+
# === Example:
|
203
|
+
#
|
204
|
+
# @post = Post.create(:foo => "bar", :miso => "great")
|
205
|
+
# @post.foo = "bazz"
|
206
|
+
# @post.reload
|
207
|
+
# @post.foo => "bar"
|
208
|
+
#
|
209
|
+
def reload
|
210
|
+
record = self.class.find(self.id)
|
211
|
+
self.attributes = record.attributes
|
212
|
+
record
|
213
|
+
end
|
214
|
+
|
215
|
+
# Find YamlRecord instance given attribute name and expected value
|
216
|
+
# Returns instance if found; false otherwise
|
217
|
+
#
|
218
|
+
# === Example:
|
219
|
+
#
|
220
|
+
# Post.find_by_attribute(:foo, "bar") => @post
|
221
|
+
#
|
222
|
+
def self.find_by_attribute(attribute, expected_value)
|
223
|
+
self.all.find do |record|
|
224
|
+
value = record.send(attribute) if record.respond_to?(attribute)
|
225
|
+
value.is_a?(Array) ?
|
226
|
+
value.include?(expected_value) :
|
227
|
+
value == expected_value
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
class << self;
|
232
|
+
|
233
|
+
# Find YamlRecord instance given id
|
234
|
+
# Returns instance if found; false otherwise
|
235
|
+
#
|
236
|
+
# === Example:
|
237
|
+
#
|
238
|
+
# Post.find_by_id("a1b2c3") => @post
|
239
|
+
#
|
240
|
+
def find_by_id(value)
|
241
|
+
self.find_by_attribute(:id, value)
|
242
|
+
end
|
243
|
+
alias :find :find_by_id
|
244
|
+
end
|
245
|
+
|
246
|
+
# Returns collection of all YamlRecord instances
|
247
|
+
# Caches results during request
|
248
|
+
#
|
249
|
+
# === Example:
|
250
|
+
#
|
251
|
+
# Post.all => [@post1, @post2, ...]
|
252
|
+
#
|
253
|
+
def self.all
|
254
|
+
@records ||= begin
|
255
|
+
raw_items = YAML.load_file(source)
|
256
|
+
raw_items ? raw_items.map { |item| self.new(item.merge(:persisted => true)) } : []
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
# Find last YamlRecord instance given a limit
|
261
|
+
# Returns an array of instances if found; empty otherwise
|
262
|
+
#
|
263
|
+
# === Example:
|
264
|
+
#
|
265
|
+
# Post.last => @post6
|
266
|
+
# Post.last(3) => [@p4, @p5, @p6]
|
267
|
+
#
|
268
|
+
def self.last(limit=1)
|
269
|
+
limit == 1 ? self.all.last : self.all.last(limit)
|
270
|
+
end
|
271
|
+
|
272
|
+
# Find first YamlRecord instance given a limit
|
273
|
+
# Returns an array of instances if found; empty otherwise
|
274
|
+
#
|
275
|
+
# === Example:
|
276
|
+
#
|
277
|
+
# Post.first => @post
|
278
|
+
# Post.first(3) => [@p1, @p2, @p3]
|
279
|
+
#
|
280
|
+
def self.first(limit=1)
|
281
|
+
limit == 1 ? self.all.first : self.all.first(limit)
|
282
|
+
end
|
283
|
+
|
284
|
+
# Initializes YamlRecord instance given an attribute hash and saves afterwards
|
285
|
+
# Returns instance if successfully saved; false otherwise
|
286
|
+
#
|
287
|
+
# === Example:
|
288
|
+
#
|
289
|
+
# Post.create(:foo => "bar", :miso => "great") => @post
|
290
|
+
#
|
291
|
+
def self.create(attributes={})
|
292
|
+
@fs = self.new(attributes)
|
293
|
+
if @fs.save == true
|
294
|
+
@fs.is_created = true;
|
295
|
+
@fs
|
296
|
+
else
|
297
|
+
false
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# Declares persisted attributes for YamlRecord class
|
302
|
+
#
|
303
|
+
# === Example:
|
304
|
+
#
|
305
|
+
# class Post < YamlRecord::Base; properties :foo, :miso; end
|
306
|
+
# Post.create(:foo => "bar", :miso => "great") => @post
|
307
|
+
#
|
308
|
+
def self.properties(*names)
|
309
|
+
names = names | [:id] if names.size > 0
|
310
|
+
names.size == 0 ? @_properties : @_properties = names
|
311
|
+
end
|
312
|
+
|
313
|
+
# Declares source file for YamlRecord class
|
314
|
+
#
|
315
|
+
# === Example:
|
316
|
+
#
|
317
|
+
# class Post < YamlRecord::Base
|
318
|
+
# source "path/to/yaml/file"
|
319
|
+
# end
|
320
|
+
#
|
321
|
+
def self.source(file=nil)
|
322
|
+
file ? @file = (file.to_s + ".yml") : @file
|
323
|
+
end
|
324
|
+
|
325
|
+
protected
|
326
|
+
|
327
|
+
# Validates each persisted attributes
|
328
|
+
# TODO Implement validation
|
329
|
+
#
|
330
|
+
def self.validates_each(*args, &block)
|
331
|
+
true
|
332
|
+
end
|
333
|
+
|
334
|
+
# Write raw yaml data to file
|
335
|
+
# Protected method, not called during usage
|
336
|
+
#
|
337
|
+
# === Example:
|
338
|
+
#
|
339
|
+
# Post.write_content([{ :foo => "bar"}, { :foo => "baz"}, ...]) # writes to source file
|
340
|
+
#
|
341
|
+
def self.write_contents(raw_data)
|
342
|
+
File.open(self.source, 'w') {|f| f.write(raw_data.to_yaml) }
|
343
|
+
@records = nil
|
344
|
+
end
|
345
|
+
|
346
|
+
# Creates reader and writer methods for each persisted attribute
|
347
|
+
# Protected method, not called during usage
|
348
|
+
#
|
349
|
+
# === Example:
|
350
|
+
#
|
351
|
+
# Post.setup_properties!
|
352
|
+
# @post.foo = "baz"
|
353
|
+
# @post.foo => "baz"
|
354
|
+
#
|
355
|
+
def setup_properties!
|
356
|
+
self.class.properties.each do |name|
|
357
|
+
self.class_eval do
|
358
|
+
define_method(name) { self[name.to_sym] } # def media; self.attributes[:media]; end
|
359
|
+
define_method("#{name}=") { |val| self[name.to_sym] = val } # def media; self.attributes[:media]; end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
# Assign YamlRecord a unique id if not set
|
365
|
+
# Invoke before create of an instance
|
366
|
+
#
|
367
|
+
def set_id!
|
368
|
+
self.id = ActiveSupport::SecureRandom.hex(15)
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
data/lib/yaml_record.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'active_support/core_ext/kernel'
|
2
|
+
require 'active_support/core_ext/class'
|
3
|
+
require 'active_support/core_ext/hash'
|
4
|
+
require 'active_support/secure_random'
|
5
|
+
require 'active_support/callbacks'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
module YamlRecord
|
9
|
+
require File.dirname(__FILE__) + "/yaml_record/base"
|
10
|
+
end
|
data/test/base_test.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class YamlObject < YamlRecord::Base
|
4
|
+
properties :title, :body, :child_ids
|
5
|
+
source File.dirname(__FILE__) + "/../tmp/yaml_object"
|
6
|
+
end
|
7
|
+
|
8
|
+
class BaseTest < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@obj_title = "Simple Title"
|
12
|
+
@obj_id = "1234"
|
13
|
+
@obj2_id = "5678"
|
14
|
+
@obj2_title = "Simple Title 2"
|
15
|
+
|
16
|
+
@attr = {
|
17
|
+
:child_ids => [@obj_id],
|
18
|
+
:title => @obj_title,
|
19
|
+
:body => "Body!!"
|
20
|
+
}
|
21
|
+
|
22
|
+
@attr2 = {
|
23
|
+
:child_ids => [@obj2_id],
|
24
|
+
:title => @obj2_title,
|
25
|
+
:body => "Body!!"
|
26
|
+
}
|
27
|
+
|
28
|
+
clean_yaml_record(YamlObject)
|
29
|
+
@fs = YamlObject.create(@attr)
|
30
|
+
end
|
31
|
+
|
32
|
+
context "for instance methods" do
|
33
|
+
|
34
|
+
context "for [] method" do
|
35
|
+
should("get attribute with [attribute]"){ assert_equal @fs.title, @fs[:title] }
|
36
|
+
end
|
37
|
+
|
38
|
+
context "for []= method" do
|
39
|
+
setup do
|
40
|
+
@fs[:title] = "Toto"
|
41
|
+
end
|
42
|
+
should("set attribute with [attribute]="){ assert_equal @fs[:title], "Toto" }
|
43
|
+
end
|
44
|
+
|
45
|
+
context "for save method" do
|
46
|
+
setup do
|
47
|
+
@fs2 = YamlObject.new(@attr)
|
48
|
+
@fs2.save
|
49
|
+
end
|
50
|
+
|
51
|
+
should("save on yaml file"){ assert_equal YamlObject.last.attributes.diff(@attr), {:id => @fs2.reload.id } }
|
52
|
+
end
|
53
|
+
|
54
|
+
context "for update_attributes method" do
|
55
|
+
setup do
|
56
|
+
@fs.update_attributes(:title => "Toto", :body => "http://somewhereelse.com")
|
57
|
+
@fs.reload
|
58
|
+
end
|
59
|
+
should("update title") { assert_equal @fs.title, "Toto" }
|
60
|
+
should("update body") { assert_equal @fs.body, "http://somewhereelse.com" }
|
61
|
+
end
|
62
|
+
|
63
|
+
context "for column_names method" do
|
64
|
+
should("return an array with attributes names") { assert_equal @fs.column_names.sort!, YamlObject.properties.map { |p| p.to_s }.sort! }
|
65
|
+
end
|
66
|
+
|
67
|
+
context "for persisted_attributes method" do
|
68
|
+
should("return persisted attributes") { assert_equal [:title, :body, :child_ids, :id ].sort_by {|sym| sym.to_s}, @fs.persisted_attributes.keys.sort_by {|sym| sym.to_s} }
|
69
|
+
end
|
70
|
+
|
71
|
+
context "for new_record? method" do
|
72
|
+
setup do
|
73
|
+
@fs3 = YamlObject.new
|
74
|
+
end
|
75
|
+
should("be a new record") { assert @fs3.new_record? }
|
76
|
+
should("not be a new record") { assert_false @fs.new_record? }
|
77
|
+
end
|
78
|
+
|
79
|
+
context "for destroyed? method" do
|
80
|
+
setup do
|
81
|
+
@fs4 = YamlObject.create(@attr)
|
82
|
+
@fs4.destroy
|
83
|
+
end
|
84
|
+
should("be a destoyed") { assert @fs4.destroyed? }
|
85
|
+
should("not be destroyed") { assert_false @fs.destroyed? }
|
86
|
+
end
|
87
|
+
|
88
|
+
context "for destroy method" do
|
89
|
+
setup do
|
90
|
+
@fs5 = YamlObject.create(@attr)
|
91
|
+
@fs5.destroy
|
92
|
+
end
|
93
|
+
should("not find @fs5"){ assert_nil YamlObject.find(@fs5.id) }
|
94
|
+
end
|
95
|
+
|
96
|
+
context "for reload method" do
|
97
|
+
setup do
|
98
|
+
@fs.title = "Foo"
|
99
|
+
end
|
100
|
+
should("equal to Foo"){ assert_equal @fs.title, "Foo" }
|
101
|
+
should("equal to correct title"){ assert_equal @fs.reload.title, @obj_title }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context "for class methods" do
|
106
|
+
context "for self.find_by_attribute method" do
|
107
|
+
setup do
|
108
|
+
@fs_found = YamlObject.find_by_attribute(:title, @obj_title)
|
109
|
+
end
|
110
|
+
should("be same object as @fs"){ assert_equal @fs_found, YamlObject.find(@fs.id) }
|
111
|
+
end
|
112
|
+
|
113
|
+
context "for self.find_by_id method" do
|
114
|
+
setup do
|
115
|
+
@fs_found = YamlObject.find_by_id(@fs.id)
|
116
|
+
@fs_found2 = YamlObject.find(@fs.id)
|
117
|
+
end
|
118
|
+
should("be same object as @fs"){ assert_equal @fs.attributes, @fs_found.attributes }
|
119
|
+
should("be same object as @fs bis"){ assert_equal @fs.attributes, @fs_found2.attributes }
|
120
|
+
end
|
121
|
+
|
122
|
+
context "for self.all method" do
|
123
|
+
setup do
|
124
|
+
clean_yaml_record(YamlObject)
|
125
|
+
@fs, @fs2 = YamlObject.create(@attr), YamlObject.create(@attr2)
|
126
|
+
end
|
127
|
+
should("retrieve 2 YamlObject obj"){ assert_equal YamlObject.all.size, 2 }
|
128
|
+
should("return as first item @fs"){ assert_equal YamlObject.all.first.attributes, @fs.attributes }
|
129
|
+
should("return as last item @fs2"){ assert_equal YamlObject.all.last.attributes, @fs2.attributes }
|
130
|
+
end
|
131
|
+
|
132
|
+
context "for self.first method" do
|
133
|
+
setup do
|
134
|
+
clean_yaml_record(YamlObject)
|
135
|
+
@fs, @fs2 = YamlObject.create(@attr), YamlObject.create(@attr2)
|
136
|
+
end
|
137
|
+
|
138
|
+
should("return @fs as the first item"){ assert_equal YamlObject.first.attributes, @fs.attributes }
|
139
|
+
should("return @fs"){ assert_equal YamlObject.first(2).first.attributes, @fs.attributes }
|
140
|
+
should("return @fs2"){ assert_equal YamlObject.first(2).last.attributes, @fs2.attributes }
|
141
|
+
end
|
142
|
+
|
143
|
+
context "for self.last method" do
|
144
|
+
setup do
|
145
|
+
clean_yaml_record(YamlObject)
|
146
|
+
@fs, @fs2 = YamlObject.create(@attr), YamlObject.create(@attr2)
|
147
|
+
end
|
148
|
+
|
149
|
+
should("return @fs as the first item"){ assert_equal YamlObject.last.attributes, @fs2.attributes }
|
150
|
+
should("return @fs"){ assert_equal YamlObject.last(2).first.attributes, @fs.attributes }
|
151
|
+
should("return @fs2"){ assert_equal YamlObject.last(2).last.attributes, @fs2.attributes }
|
152
|
+
end
|
153
|
+
|
154
|
+
context "for self.write_contents method" do
|
155
|
+
setup do
|
156
|
+
clean_yaml_record(YamlObject)
|
157
|
+
@attributes = [ @attr, @attr2 ]
|
158
|
+
YamlObject.write_contents(@attributes)
|
159
|
+
end
|
160
|
+
should("write in yaml file"){ assert_equal YAML.load_file(YamlObject.source), [ @attr, @attr2 ] }
|
161
|
+
end
|
162
|
+
|
163
|
+
context "for self.create method" do
|
164
|
+
setup do
|
165
|
+
clean_yaml_record(YamlObject)
|
166
|
+
@fs = YamlObject.create(@attr)
|
167
|
+
@fs_not_created = YamlObject.new(@attr)
|
168
|
+
end
|
169
|
+
should("create @fs"){ assert_equal YamlObject.last.attributes, @fs.attributes }
|
170
|
+
should("set its is_created to true"){ assert @fs.is_created }
|
171
|
+
should("set @fs_not_created is_created field to false"){ assert_false @fs_not_created.is_created }
|
172
|
+
end
|
173
|
+
|
174
|
+
context "for set_id!" do
|
175
|
+
setup do
|
176
|
+
@fs_no_id = YamlObject.new(@attr)
|
177
|
+
@fs_with_id = YamlObject.create(@attr)
|
178
|
+
@id = @fs_with_id.id
|
179
|
+
@fs_with_id.update_attributes(:title => "Gomiso")
|
180
|
+
end
|
181
|
+
should("not have any id"){ assert_nil @fs_no_id.id }
|
182
|
+
should("have a id"){ assert @fs_with_id.id }
|
183
|
+
should("keep the same id"){ assert_equal @fs_with_id.id, @id }
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require File.dirname(__FILE__) + "/../lib/yaml_record"
|
5
|
+
|
6
|
+
class Test::Unit::TestCase
|
7
|
+
def clean_yaml_record(class_record)
|
8
|
+
File.open(class_record.source, 'w') {|f| f.write(nil) }
|
9
|
+
end
|
10
|
+
|
11
|
+
# Asserts that the condition is not true
|
12
|
+
# assert_false @title == "hey"
|
13
|
+
def assert_false(condition, message=nil)
|
14
|
+
assert !condition, message
|
15
|
+
end
|
16
|
+
end
|
data/yaml_record.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "yaml_record/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "yaml_record"
|
7
|
+
s.version = YamlRecord::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Nico Taing", "Nathan Esquenazi"]
|
10
|
+
s.email = ["nico@gomiso.com"]
|
11
|
+
s.homepage = "https://github.com/nico-taing/yaml_record"
|
12
|
+
s.summary = %q{YAML file persistence engine}
|
13
|
+
s.description = %q{Use YAML for persisted data with ActiveModel interface}
|
14
|
+
|
15
|
+
s.rubyforge_project = "yaml_record"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_dependency 'activesupport', '~> 2.3.11'
|
23
|
+
s.add_development_dependency 'rake', '~> 0.9.2'
|
24
|
+
s.add_development_dependency 'shoulda'
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: yaml_record
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Nico Taing
|
14
|
+
- Nathan Esquenazi
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2011-07-11 00:00:00 -07:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: activesupport
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 21
|
31
|
+
segments:
|
32
|
+
- 2
|
33
|
+
- 3
|
34
|
+
- 11
|
35
|
+
version: 2.3.11
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id001
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: rake
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
hash: 63
|
47
|
+
segments:
|
48
|
+
- 0
|
49
|
+
- 9
|
50
|
+
- 2
|
51
|
+
version: 0.9.2
|
52
|
+
type: :development
|
53
|
+
version_requirements: *id002
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: shoulda
|
56
|
+
prerelease: false
|
57
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
hash: 3
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
type: :development
|
67
|
+
version_requirements: *id003
|
68
|
+
description: Use YAML for persisted data with ActiveModel interface
|
69
|
+
email:
|
70
|
+
- nico@gomiso.com
|
71
|
+
executables: []
|
72
|
+
|
73
|
+
extensions: []
|
74
|
+
|
75
|
+
extra_rdoc_files: []
|
76
|
+
|
77
|
+
files:
|
78
|
+
- .gitignore
|
79
|
+
- Gemfile
|
80
|
+
- MIT-LICENSE
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- lib/yaml_record.rb
|
84
|
+
- lib/yaml_record/base.rb
|
85
|
+
- lib/yaml_record/version.rb
|
86
|
+
- test/base_test.rb
|
87
|
+
- test/test_helper.rb
|
88
|
+
- yaml_record.gemspec
|
89
|
+
has_rdoc: true
|
90
|
+
homepage: https://github.com/nico-taing/yaml_record
|
91
|
+
licenses: []
|
92
|
+
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
hash: 3
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
version: "0"
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
hash: 3
|
113
|
+
segments:
|
114
|
+
- 0
|
115
|
+
version: "0"
|
116
|
+
requirements: []
|
117
|
+
|
118
|
+
rubyforge_project: yaml_record
|
119
|
+
rubygems_version: 1.6.2
|
120
|
+
signing_key:
|
121
|
+
specification_version: 3
|
122
|
+
summary: YAML file persistence engine
|
123
|
+
test_files:
|
124
|
+
- test/base_test.rb
|
125
|
+
- test/test_helper.rb
|