yaml_record 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|