yaml_record4 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fbf3ac61a8c2cad6bc2bd097c5e08c0fd02c2f82
4
+ data.tar.gz: 4e4cea5900e52aa4885093b69bee89215322331a
5
+ SHA512:
6
+ metadata.gz: 138dfcfb209574bef2735f56731eafdf24c9374135d067e50a3d5a928caeee25b20996ee538c89ba2f41f1ebaa5342693768544c581cdf0c85423349ed32ba27
7
+ data.tar.gz: 5ae126e0f749cb9825b077cf0545db92109f217e3d24db6f3321ad0e0b2f0ce26c0b2f4d50655cdd9f1305e8fd84fb512304026f180caf32dc7eb3713f9ea0a3
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ tmp/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create use ruby-1.9.2-p180@sandbox #> /dev/null
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in yaml_record.gemspec
4
+ gemspec
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,180 @@
1
+ # YAML RECORD #
2
+
3
+ ## Introduction ##
4
+
5
+ YAML Record is a data persistence library that complies with the ActiveModel API. Using YAMLRecord should be familiar to anyone that has used ActiveRecord before to manage your database. Using this library, the data is persisted in a YAML backed file.
6
+
7
+ ## Rationale ##
8
+
9
+ *Why a YAML-based persistence store?* In certain situations, there are collections of simple data in which there are very few records which are by nature infrequently accessed and that are ideally able to be scanned easily within a text file. These can include a simple contact form, landing page interest, feedback forms, surveys, team pages, etc where there is simply no need for the overhead of a fully persisted database solution.
10
+
11
+ There are many cases where YAMLRecord is **not the correct** persistence strategy. Any collection that is going to have substantial number of records, will be frequently updated, or is accessible by a large volume of users should not be stored in a YAML text file for obvious reasons. However, for specific cases, the convenience of storing things in a simple text file becomes apparent. Being able to access the text file data as if the records were in a familiar database ORM has many conveniences and advantages such as keeping the controllers standard and leveraging existing ORM knowledge.
12
+
13
+ ## Installation ##
14
+
15
+ Install using rubygems:
16
+
17
+ gem install yaml_record
18
+
19
+ Or add gem to your Gemfile:
20
+
21
+ # Gemfile
22
+ gem 'yaml_record'
23
+
24
+ ## Usage ##
25
+
26
+ ### Declaration ###
27
+
28
+ Create any ruby object and inherit from `YamlRecord:Base` to define a type:
29
+
30
+ ```ruby
31
+ class Post < YamlRecord::Base
32
+ # Declare your properties
33
+ properties :title, :body, :user_id
34
+
35
+ # Declare source file path
36
+ source Rails.root.join("config/posts")
37
+ end
38
+ ```
39
+
40
+ Use this new object the same way as any ActiveRecord object.
41
+
42
+ ### Retrieval ###
43
+
44
+ Retrieve the collection:
45
+
46
+ Post.all => [@p1, @p2]
47
+
48
+ Retrieve item by id:
49
+
50
+ Post.find("a1b2") => @p1
51
+
52
+ Retrieve by attribute:
53
+
54
+ Post.find_by_attribute(:title, "some title") => @p
55
+
56
+ ### Create ###
57
+
58
+ Initialize post:
59
+
60
+ @p = Post.new(:title => "...", :body => "...", :user_id => 5)
61
+ @p.save
62
+
63
+ Create post:
64
+
65
+ @p = Post.create(:title => "...", :body => "...", :user_id => 6)
66
+
67
+ ### Update ###
68
+
69
+ Update attributes using the expected method:
70
+
71
+ @p.update_attributes(:title => "new title")
72
+
73
+ ### Destroy ###
74
+
75
+ Destroy a given record:
76
+
77
+ @p.destroy
78
+
79
+ ### Access ###
80
+
81
+ Access attributes:
82
+
83
+ @p = Post.find("a1b2")
84
+ @p.title => "..."
85
+
86
+ Assign attributes:
87
+
88
+ @p.title = "new title"
89
+ @p.save
90
+
91
+ ### Callbacks ###
92
+
93
+ Create callbacks:
94
+
95
+ ```ruby
96
+ class Submission < YamlRecord::Base
97
+ # ...
98
+ before_create :do_something # or before_save, before_destroy, ...
99
+
100
+ def do_something
101
+ # something here
102
+ end
103
+ end
104
+ ```
105
+
106
+ ## Example ##
107
+
108
+ Imagine a simple contact form that accepts a name and email from a user along with a body:
109
+
110
+ ```ruby
111
+ class Submission < YamlRecord::Base
112
+ # Declare your properties
113
+ properties :name, :email, :body
114
+
115
+ # Declare source file path (config/contact.yml)
116
+ source Rails.root.join("config/contact")
117
+ end
118
+ ```
119
+
120
+ Once we define the Contact model, we can setup a controller and form just the same as in ActiveRecord:
121
+
122
+ ```ruby
123
+ class SubmissionsController < AC::Base
124
+ def create
125
+ @submission = Submission.create(params[:submission])
126
+ end
127
+
128
+ def index
129
+ @submissions = Submission.all
130
+ end
131
+
132
+ def show
133
+ @submission = Submission.find(params[:id])
134
+ end
135
+
136
+ def update
137
+ @submission = Submission.find(params[:id])
138
+ @submission.update_attributes(params[:submission])
139
+ end
140
+
141
+ def destroy
142
+ @submission = Submission.find(params[:id])
143
+ @submission.destroy
144
+ end
145
+ end
146
+ ```
147
+
148
+ As you can see the controller appears the same as any ActiveRecord controller would and this makes managing the YAML data easy and convenient. You can even define callbacks in your object as you would in ActiveRecord:
149
+
150
+ ```ruby
151
+ class Submission < YamlRecord::Base
152
+ # ...
153
+ before_create :do_something # or before_save, before_destroy, ...
154
+
155
+ def do_something
156
+ # something here
157
+ end
158
+ end
159
+ ```
160
+
161
+ And that's all! Each record will be persisted to the source file for easy access.
162
+
163
+ ## Issues ##
164
+
165
+ * Validations should be supported `validates_presence_of :name`
166
+ * Property type declarations should be available `property :age, Integer`
167
+
168
+ ## Contributors ##
169
+
170
+ Created at Miso by Nico Taing and Nathan Esquenazi
171
+
172
+ Contributors and patches are welcome! Please send a pull request!
173
+
174
+ ## Notes ##
175
+
176
+ There is already an excellent project for YAML persistence if you are using [Datamapper](https://github.com/datamapper/dm-yaml-adapter). In the situation in which we were using DM and [Padrino](http://padrinorb.com), this would surely be a better choice. But if you are using ActiveRecord and Rails, this library is a lightweight and standalone solution.
177
+
178
+ ## License ##
179
+
180
+ 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,10 @@
1
+ require 'bundler'
2
+ include Rake::DSL
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rake/testtask'
7
+ Rake::TestTask.new('test') do |test|
8
+ test.pattern = 'test/**/*_test.rb'
9
+ test.verbose = true
10
+ end
@@ -0,0 +1,388 @@
1
+ # coding: utf-8
2
+
3
+ require 'yaml'
4
+ require 'securerandom'
5
+
6
+ #require 'active_support'
7
+ require 'active_support/core_ext/kernel'
8
+ require 'active_support/core_ext/class'
9
+ require 'active_support/core_ext/hash'
10
+
11
+ require 'active_model'
12
+
13
+ module YamlRecord
14
+ class Base
15
+ include ActiveModel::Validations
16
+ extend ActiveModel::Naming # Required dependency for ActiveModel::Errors
17
+ extend ActiveModel::Callbacks
18
+
19
+ define_model_callbacks :save, :create, :destroy, :only => [:after, :before]
20
+
21
+ before_create :set_id!
22
+
23
+ attr_accessor :attributes, :is_created, :is_destroyed
24
+ attr_reader :errors
25
+
26
+ # Constructs a new YamlRecord instance based on specified attribute hash
27
+ #
28
+ # === Example:
29
+ #
30
+ # class Post < YamlRecord::Base; properties :foo; end
31
+ #
32
+ # Post.new(:foo => "bar")
33
+ #
34
+ def initialize(attr_hash={})
35
+ attr_hash.symbolize_keys!
36
+ attr_hash.reverse_merge!(self.class.properties.inject({}) { |result, key| result[key] = nil; result })
37
+
38
+ self.attributes ||= {}
39
+ self.is_created = attr_hash.delete(:persisted) || false
40
+ attr_hash.each do |k,v|
41
+ self.send("#{k}=", v) # self.attributes[:media] = "foo"
42
+ end
43
+
44
+ @errors = ActiveModel::Errors.new(self)
45
+ end
46
+
47
+ # Accesses given attribute from YamlRecord instance
48
+ #
49
+ # === Example:
50
+ #
51
+ # @post[:foo] => "bar"
52
+ #
53
+ def [](attribute)
54
+ self.attributes[attribute]
55
+ end
56
+
57
+ # Assign given attribute from YamlRecord instance with specified value
58
+ #
59
+ # === Example:
60
+ #
61
+ # @post[:foo] = "baz"
62
+ #
63
+ def []=(attribute, value)
64
+ self.attributes[attribute] = value
65
+ end
66
+
67
+ # Saved YamlRecord instance to file
68
+ # Executes save and create callbacks
69
+ # Returns true if record saved; false otherwise
70
+ #
71
+ # === Example:
72
+ #
73
+ # @post.save => true
74
+ #
75
+ def save
76
+ block = lambda do
77
+ run_callbacks(:save) do
78
+ existing_items = self.class.all
79
+ if self.new_record?
80
+ existing_items << self
81
+ else # update existing record
82
+ updated_item = existing_items.find { |item| item.id == self.id }
83
+ return false unless updated_item
84
+ updated_item.attributes = self.attributes
85
+ end
86
+
87
+ raw_data = existing_items ? existing_items.map { |item| item.persisted_attributes } : []
88
+ self.class.write_contents(raw_data) if self.valid?
89
+ end
90
+ end
91
+
92
+ self.is_created ? block.call : run_callbacks(:create) { block.call }
93
+ true
94
+ rescue IOError
95
+ false
96
+ end
97
+
98
+ # Update YamlRecord instance with specified attributes
99
+ # Returns true if record updated; false otherwise
100
+ #
101
+ # === Example:
102
+ #
103
+ # @post.update_attributes(:foo => "baz", :miso => "awesome") => true
104
+ #
105
+ def update_attributes(updated_attrs={})
106
+ updated_attrs.each { |k,v| self.send("#{k}=", v) }
107
+ self.save
108
+ end
109
+
110
+ # Returns array of instance attributes names; An attribute is a value stored for this record (persisted or not)
111
+ #
112
+ # === Example:
113
+ #
114
+ # @post.column_names => ["foo", "miso"]
115
+ #
116
+ def column_names
117
+ array = []
118
+ self.attributes.each_key { |k| array << k.to_s }
119
+ array
120
+ end
121
+
122
+ # Returns hash of attributes to be persisted to file.
123
+ # A persisted attribute is a value stored in the file (specified with the properties declaration)
124
+ #
125
+ # === Example:
126
+ #
127
+ # class Post < YamlRecord::Base; properties :foo, :miso; end
128
+ # @post = Post.create(:foo => "bar", :miso => "great")
129
+ # @post.persisted_attributes => { :id => "a1b2c3", :foo => "bar", :miso => "great" }
130
+ #
131
+ def persisted_attributes
132
+ self.attributes.slice(*self.class.properties).reject { |k, v| v.nil? }
133
+ end
134
+
135
+ # Returns true if YamlRecord instance hasn't persisted; false otherwise
136
+ #
137
+ # === Example:
138
+ #
139
+ # @post = Post.new(:foo => "bar", :miso => "great")
140
+ # @post.new_record? => true
141
+ # @post.save => true
142
+ # @post.new_record? => false
143
+ #
144
+ def new_record?
145
+ !self.is_created
146
+ end
147
+
148
+ # Returns true if YamlRecord instance has been destroyed; false otherwise
149
+ #
150
+ # === Example:
151
+ #
152
+ # @post = Post.new(:foo => "bar", :miso => "great")
153
+ # @post.destroyed? => false
154
+ # @post.save
155
+ # @post.destroy => true
156
+ # @post.destroyed? => true
157
+ #
158
+ def destroyed?
159
+ self.is_destroyed
160
+ end
161
+
162
+ # Remove a persisted YamlRecord object
163
+ # Returns true if destroyed; false otherwise
164
+ #
165
+ # === Example:
166
+ #
167
+ # @post = Post.create(:foo => "bar", :miso => "great")
168
+ # Post.all.size => 1
169
+ # @post.destroy => true
170
+ # Post.all.size => 0
171
+ #
172
+ def destroy
173
+ run_callbacks(:destroy) do
174
+ new_data = self.class.all
175
+ .reject { |item| item.persisted_attributes == self.persisted_attributes }
176
+ .map { |item| item.persisted_attributes }
177
+ self.class.write_contents(new_data)
178
+ self.is_destroyed = true
179
+ end
180
+ true
181
+ rescue IOError
182
+ false
183
+ end
184
+
185
+ # Returns YamlRecord Instance
186
+ # Complies with ActiveModel api
187
+ #
188
+ # === Example:
189
+ #
190
+ # @post.to_model => @post
191
+ #
192
+ def to_model
193
+ self
194
+ end
195
+
196
+ # Returns the instance of a record as a parameter
197
+ # By default return an id
198
+ #
199
+ # === Example:
200
+ #
201
+ # @post.to_param => <id>
202
+ #
203
+ def to_param
204
+ self.id
205
+ end
206
+
207
+ # Reload YamlRecord instance attributes from file
208
+ #
209
+ # === Example:
210
+ #
211
+ # @post = Post.create(:foo => "bar", :miso => "great")
212
+ # @post.foo = "bazz"
213
+ # @post.reload
214
+ # @post.foo => "bar"
215
+ #
216
+ def reload
217
+ record = self.class.find(self.id)
218
+ self.attributes = record.attributes
219
+ record
220
+ end
221
+
222
+ # Find YamlRecord instance given attribute name and expected value
223
+ # Supports checking inclusion for array based values
224
+ # Returns instance if found; false otherwise
225
+ #
226
+ # === Example:
227
+ #
228
+ # Post.find_by_attribute(:foo, "bar") => @post
229
+ # Post.find_by_attribute(:some_list, "item") => @post
230
+ #
231
+ def self.find_by_attribute(attribute, expected_value)
232
+ self.all.find do |record|
233
+ value = record.send(attribute) if record.respond_to?(attribute)
234
+ value.is_a?(Array) ?
235
+ value.include?(expected_value) :
236
+ value == expected_value
237
+ end
238
+ end
239
+
240
+ class << self
241
+
242
+ # Find YamlRecord instance given id
243
+ # Returns instance if found; false otherwise
244
+ #
245
+ # === Example:
246
+ #
247
+ # Post.find_by_id("a1b2c3") => @post
248
+ #
249
+ def find_by_id(value)
250
+ self.find_by_attribute(:id, value)
251
+ end
252
+ alias :find :find_by_id
253
+ end
254
+
255
+ # Returns collection of all YamlRecord instances
256
+ # Caches results during request
257
+ #
258
+ # === Example:
259
+ #
260
+ # Post.all => [@post1, @post2, ...]
261
+ # Post.all(true) => (...force reload...)
262
+ #
263
+ def self.all
264
+ begin
265
+ raw_items = YAML.load_file(source)
266
+ rescue Errno::ENOENT
267
+ ensure
268
+ raw_items ||= []
269
+ end
270
+ raw_items.map { |item| self.new(item.merge(:persisted => true)) }
271
+ end
272
+
273
+ # Find last YamlRecord instance given a limit
274
+ # Returns an array of instances if found; empty otherwise
275
+ #
276
+ # === Example:
277
+ #
278
+ # Post.last => @post6
279
+ # Post.last(3) => [@p4, @p5, @p6]
280
+ #
281
+ def self.last(limit=1)
282
+ limit == 1 ? self.all.last : self.all.last(limit)
283
+ end
284
+
285
+ # Find first YamlRecord instance given a limit
286
+ # Returns an array of instances if found; empty otherwise
287
+ #
288
+ # === Example:
289
+ #
290
+ # Post.first => @post
291
+ # Post.first(3) => [@p1, @p2, @p3]
292
+ #
293
+ def self.first(limit=1)
294
+ limit == 1 ? self.all.first : self.all.first(limit)
295
+ end
296
+
297
+ # Initializes YamlRecord instance given an attribute hash and saves afterwards
298
+ # Returns instance if successfully saved; false otherwise
299
+ #
300
+ # === Example:
301
+ #
302
+ # Post.create(:foo => "bar", :miso => "great") => @post
303
+ #
304
+ def self.create(attributes={})
305
+ @fs = self.new(attributes)
306
+ if @fs.save == true
307
+ @fs.is_created = true;
308
+ @fs
309
+ else
310
+ false
311
+ end
312
+ end
313
+
314
+ # Declares persisted attributes for YamlRecord class
315
+ #
316
+ # === Example:
317
+ #
318
+ # class Post < YamlRecord::Base; properties :foo, :miso; end
319
+ # Post.create(:foo => "bar", :miso => "great") => @post
320
+ #
321
+ def self.properties(*names)
322
+ @_properties ||= []
323
+ if names.size == 0 # getter
324
+ @_properties
325
+ elsif names.size > 0 # setter
326
+ names = names | [:id]
327
+ setup_properties!(*names)
328
+ @_properties += names
329
+ end
330
+ end
331
+
332
+ # Declares source file for YamlRecord class
333
+ #
334
+ # === Example:
335
+ #
336
+ # class Post < YamlRecord::Base
337
+ # source "path/to/yaml/file"
338
+ # end
339
+ #
340
+ def self.source(file = nil)
341
+ @@file ||= file ? file.to_s : File.join(YamlRecord.root_path, "#{model_name.name}.yml")
342
+ end
343
+
344
+ # Overrides equality to match if matching ids
345
+ #
346
+ def ==(comparison_record)
347
+ self.id == comparison_record.id
348
+ end
349
+
350
+ protected
351
+
352
+ # Write raw yaml data to file
353
+ # Protected method, not called during usage
354
+ #
355
+ # === Example:
356
+ #
357
+ # Post.write_content([{ :foo => "bar"}, { :foo => "baz"}, ...]) # writes to source file
358
+ #
359
+ def self.write_contents(raw_data)
360
+ File.open(self.source, 'w') {|f| f.write(raw_data.to_yaml) }
361
+ @records = nil
362
+ end
363
+
364
+ # Creates reader and writer methods for each persisted attribute
365
+ # Protected method, not called during usage
366
+ #
367
+ # === Example:
368
+ #
369
+ # Post.setup_properties!(:foo)
370
+ # @post.foo = "baz"
371
+ # @post.foo => "baz"
372
+ #
373
+ def self.setup_properties!(*names)
374
+ names.each do |name|
375
+ define_method(name) { self[name.to_sym] }
376
+ define_method("#{name}=") { |val| self[name.to_sym] = val }
377
+ end
378
+ end
379
+
380
+ # Assign YamlRecord a unique id if not set
381
+ # Invoke before create of an instance
382
+ # Protected method, not called during usage
383
+ #
384
+ def set_id!
385
+ self.id ||= SecureRandom.hex(15)
386
+ end
387
+ end
388
+ end
@@ -0,0 +1,3 @@
1
+ module YamlRecord
2
+ VERSION = '0.0.5'
3
+ end
@@ -0,0 +1,9 @@
1
+ require 'yaml_record/base'
2
+
3
+ require 'active_support/core_ext/module/attribute_accessors'
4
+
5
+ module YamlRecord
6
+ mattr_accessor :root_path do
7
+ Dir.tmpdir
8
+ end
9
+ end
data/test/base_test.rb ADDED
@@ -0,0 +1,193 @@
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
+
104
+ context "for to_param method" do
105
+ setup { @fs.id = "a1b2c3" }
106
+
107
+ should("return id of record") { assert_equal(@fs.to_param, @fs.id) }
108
+ end
109
+ end
110
+
111
+ context "for class methods" do
112
+ context "for self.find_by_attribute method" do
113
+ setup do
114
+ @fs_found = YamlObject.find_by_attribute(:title, @obj_title)
115
+ end
116
+ should("be same object as @fs"){ assert_equal @fs_found, YamlObject.find(@fs.id) }
117
+ end
118
+
119
+ context "for self.find_by_id method" do
120
+ setup do
121
+ @fs_found = YamlObject.find_by_id(@fs.id)
122
+ @fs_found2 = YamlObject.find(@fs.id)
123
+ end
124
+ should("be same object as @fs"){ assert_equal @fs.attributes, @fs_found.attributes }
125
+ should("be same object as @fs bis"){ assert_equal @fs.attributes, @fs_found2.attributes }
126
+ end
127
+
128
+ context "for self.all method" do
129
+ setup do
130
+ clean_yaml_record(YamlObject)
131
+ @fs, @fs2 = YamlObject.create(@attr), YamlObject.create(@attr2)
132
+ end
133
+ should("retrieve 2 YamlObject obj"){ assert_equal YamlObject.all.size, 2 }
134
+ should("return as first item @fs"){ assert_equal YamlObject.all.first.attributes, @fs.attributes }
135
+ should("return as last item @fs2"){ assert_equal YamlObject.all.last.attributes, @fs2.attributes }
136
+ end
137
+
138
+ context "for self.first method" do
139
+ setup do
140
+ clean_yaml_record(YamlObject)
141
+ @fs, @fs2 = YamlObject.create(@attr), YamlObject.create(@attr2)
142
+ end
143
+
144
+ should("return @fs as the first item"){ assert_equal YamlObject.first.attributes, @fs.attributes }
145
+ should("return @fs"){ assert_equal YamlObject.first(2).first.attributes, @fs.attributes }
146
+ should("return @fs2"){ assert_equal YamlObject.first(2).last.attributes, @fs2.attributes }
147
+ end
148
+
149
+ context "for self.last method" do
150
+ setup do
151
+ clean_yaml_record(YamlObject)
152
+ @fs, @fs2 = YamlObject.create(@attr), YamlObject.create(@attr2)
153
+ end
154
+
155
+ should("return @fs as the first item"){ assert_equal YamlObject.last.attributes, @fs2.attributes }
156
+ should("return @fs"){ assert_equal YamlObject.last(2).first.attributes, @fs.attributes }
157
+ should("return @fs2"){ assert_equal YamlObject.last(2).last.attributes, @fs2.attributes }
158
+ end
159
+
160
+ context "for self.write_contents method" do
161
+ setup do
162
+ clean_yaml_record(YamlObject)
163
+ @attributes = [ @attr, @attr2 ]
164
+ YamlObject.write_contents(@attributes)
165
+ end
166
+ should("write in yaml file"){ assert_equal YAML.load_file(YamlObject.source), [ @attr, @attr2 ] }
167
+ end
168
+
169
+ context "for self.create method" do
170
+ setup do
171
+ clean_yaml_record(YamlObject)
172
+ @fs = YamlObject.create(@attr)
173
+ @fs_not_created = YamlObject.new(@attr)
174
+ end
175
+ should("create @fs"){ assert_equal YamlObject.last.attributes, @fs.attributes }
176
+ should("set its is_created to true"){ assert @fs.is_created }
177
+ should("set @fs_not_created is_created field to false"){ assert_false @fs_not_created.is_created }
178
+ end
179
+
180
+ context "for set_id!" do
181
+ setup do
182
+ @fs_no_id = YamlObject.new(@attr)
183
+ @fs_with_id = YamlObject.create(@attr)
184
+ @id = @fs_with_id.id
185
+ @fs_with_id.update_attributes(:title => "Gomiso")
186
+ end
187
+ should("not have any id"){ assert_nil @fs_no_id.id }
188
+ should("have a id"){ assert @fs_with_id.id }
189
+ should("keep the same id"){ assert_equal @fs_with_id.id, @id }
190
+ end
191
+ end
192
+
193
+ end
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'minitest/autorun'
3
+ #require 'test/unit'
4
+ require 'shoulda'
5
+ require File.dirname(__FILE__) + "/../lib/yaml_record"
6
+
7
+ class Test::Unit::TestCase
8
+ def clean_yaml_record(class_record)
9
+ File.open(class_record.source, 'w') {|f| f.write(nil) }
10
+ end
11
+
12
+ # Asserts that the condition is not true
13
+ # assert_false @title == "hey"
14
+ def assert_false(condition, message='')
15
+ assert !condition, message
16
+ end
17
+ end
@@ -0,0 +1,26 @@
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_record4"
7
+ s.version = YamlRecord::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Nico Taing", "Nathan Esquenazi", "Thierry Zires"]
10
+ s.email = ["zshuaibin@gmail.com"]
11
+ s.homepage = "https://github.com/zires/yaml_record/tree/rails41"
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', '~>4.1'
23
+ s.add_dependency 'activemodel', '~>4.1'
24
+ s.add_development_dependency 'rake', '~>0.9.2'
25
+ s.add_development_dependency 'shoulda'
26
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yaml_record4
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Nico Taing
8
+ - Nathan Esquenazi
9
+ - Thierry Zires
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-09-01 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '4.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ version: '4.1'
29
+ - !ruby/object:Gem::Dependency
30
+ name: activemodel
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: '4.1'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ version: '4.1'
43
+ - !ruby/object:Gem::Dependency
44
+ name: rake
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ version: 0.9.2
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: 0.9.2
57
+ - !ruby/object:Gem::Dependency
58
+ name: shoulda
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ description: Use YAML for persisted data with ActiveModel interface
72
+ email:
73
+ - zshuaibin@gmail.com
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - .gitignore
79
+ - .rvmrc
80
+ - Gemfile
81
+ - MIT-LICENSE
82
+ - README.md
83
+ - Rakefile
84
+ - lib/yaml_record.rb
85
+ - lib/yaml_record/base.rb
86
+ - lib/yaml_record/version.rb
87
+ - test/base_test.rb
88
+ - test/test_helper.rb
89
+ - yaml_record.gemspec
90
+ homepage: https://github.com/zires/yaml_record/tree/rails41
91
+ licenses: []
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 2.1.11
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: YAML file persistence engine
113
+ test_files:
114
+ - test/base_test.rb
115
+ - test/test_helper.rb
116
+ has_rdoc: