plain_record 0.1.0 → 0.2

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.
@@ -0,0 +1,5 @@
1
+ - author_name: super1997
2
+ text: Cool!
3
+ answers:
4
+ - author_name: john
5
+ text: Thanks
File without changes
@@ -1,3 +1,3 @@
1
1
  unknow_property: 1
2
- ---
2
+ ---
3
3
  only one
@@ -0,0 +1,4 @@
1
+ title: Third
2
+ rate:
3
+ text: 2
4
+ subject: 5
@@ -1,3 +1,3 @@
1
1
  - name: Anonymous
2
- - login: super1997
3
- name: SuperHacker
2
+ - name: SuperHacker
3
+ login: super1997
@@ -1,4 +1,4 @@
1
- - login: john
2
- name: John Smith
3
- - login: ivan
4
- name: Ivan Ivanov
1
+ - name: John Smith
2
+ login: john
3
+ - name: Ivan Ivanov
4
+ login: ivan
@@ -0,0 +1 @@
1
+ title: Best
@@ -0,0 +1,53 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe PlainRecord::Filepath do
4
+
5
+ it "shouldn't create non-virtual filepath property" do
6
+ lambda {
7
+ Class.new do
8
+ include PlainRecord::Resource
9
+ entry_in 'data/*/post.md'
10
+ property :category, in_filepath(1)
11
+ end
12
+ }.should raise_error(ArgumentError, /virtual creator/)
13
+ end
14
+
15
+ it "should load filepath property" do
16
+ best = FilepathPost.first(:title => 'Best')
17
+ best.category.should == 'best/'
18
+ best.name.should == '4'
19
+ end
20
+
21
+ it "should load filepath property as nil when ** pattern is empty" do
22
+ FilepathPost.first(:title => 'First').category.should be_empty
23
+ end
24
+
25
+ it "should return more accurate path by filepath properties" do
26
+ FilepathPost.path(:name => 2).should == 'data/**/2/post.md'
27
+ end
28
+
29
+ it "should use filepath properties in search" do
30
+ FilepathPost.loaded = { }
31
+ FilepathPost.all(:category => 'best/')
32
+ FilepathPost.loaded.should have(1).keys
33
+ end
34
+
35
+ it "should load properties from model constructor" do
36
+ post = FilepathPost.new(:name => 5)
37
+ post.name.should == 5
38
+ post.category.should be_nil
39
+ end
40
+
41
+ it "should get entry path by filepath properties" do
42
+ path = File.join(File.dirname(__FILE__), 'data/5/post.md')
43
+ post = FilepathPost.new(:name => 5, :category => '')
44
+ FilepathPost.should_receive(:move_entry).with(post, nil, path)
45
+ post.save
46
+ end
47
+
48
+ it "should raise error, when can't get entry path by filepath properties" do
49
+ post = FilepathPost.new
50
+ lambda { post.save }.should raise_error(ArgumentError, /isn't file to save/)
51
+ end
52
+
53
+ end
data/spec/model_spec.rb CHANGED
@@ -1,33 +1,56 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
3
  describe PlainRecord::Model do
4
-
4
+
5
+ after :each do
6
+ Post.loaded = { }
7
+ Author.loaded = { }
8
+ end
9
+
10
+ it "should define virtual property" do
11
+ klass = Class.new do
12
+ include PlainRecord::Resource
13
+ virtual :one, Definers.none
14
+ end
15
+
16
+ klass.virtuals.should == [:one]
17
+ end
18
+
19
+ it "shouldn't define virtual property without accessor from definers" do
20
+ lambda {
21
+ Class.new do
22
+ include PlainRecord::Resource
23
+ virtual :one, Definers.reader
24
+ end
25
+ }.should raise_error(ArgumentError, /own accessors/)
26
+ end
27
+
5
28
  it "should define property" do
6
29
  klass = Class.new do
7
30
  include PlainRecord::Resource
8
31
  property :one
9
32
  end
10
-
33
+
11
34
  klass.properties.should == [:one]
12
- object = klass.new(nil, {'one' => 1})
35
+ object = klass.new(nil, { 'one' => 1 })
13
36
  object.one.should == 1
14
37
  object.one = 2
15
38
  object.one.should == 2
16
39
  end
17
-
40
+
18
41
  it "should define text" do
19
42
  klass = Class.new do
20
43
  include PlainRecord::Resource
21
44
  text :content
22
45
  end
23
-
46
+
24
47
  klass.texts.should == [:content]
25
- object = klass.new(nil, {}, ['text'])
48
+ object = klass.new(nil, { }, ['text'])
26
49
  object.content.should == 'text'
27
50
  object.content = 'another'
28
51
  object.content.should == 'another'
29
52
  end
30
-
53
+
31
54
  it "should call definer" do
32
55
  klass = Class.new do
33
56
  include PlainRecord::Resource
@@ -38,7 +61,7 @@ describe PlainRecord::Model do
38
61
  end
39
62
  klass.should has_methods(:one, :'one=', :'three=', :two)
40
63
  end
41
-
64
+
42
65
  it "should use accessors from definers" do
43
66
  klass = Class.new do
44
67
  include PlainRecord::Resource
@@ -47,25 +70,29 @@ describe PlainRecord::Model do
47
70
  end
48
71
  klass.should has_methods(:two)
49
72
  end
50
-
51
- it "should send property name to definer" do
73
+
74
+ it "should send property name and caller type to definer" do
52
75
  definer = mock
53
- definer.stub!(:accessor).with(:one)
76
+ definer.stub!(:virtual).with(:one, :virtual)
77
+ definer.stub!(:property).with(:two, :property)
78
+ definer.stub!(:text).with(:three, :text)
54
79
  klass = Class.new do
55
80
  include PlainRecord::Resource
56
- property :one, definer.method(:accessor)
81
+ virtual :one, definer.method(:virtual)
82
+ property :two, definer.method(:property)
83
+ text :three, definer.method(:text)
57
84
  end
58
85
  end
59
-
86
+
60
87
  it "should find all enrty files by glob pattern" do
61
88
  klass = Class.new do
62
89
  include PlainRecord::Resource
63
- entry_in 'data/*/post.m'
90
+ entry_in 'data/*/post.md'
64
91
  end
65
92
  klass.storage.should == :entry
66
93
  klass.files.sort.should == [FIRST, SECOND, THIRD]
67
94
  end
68
-
95
+
69
96
  it "should find all list files by glob pattern" do
70
97
  klass = Class.new do
71
98
  include PlainRecord::Resource
@@ -74,40 +101,40 @@ describe PlainRecord::Model do
74
101
  klass.storage.should == :list
75
102
  klass.files.sort.should == [EXTERN, INTERN]
76
103
  end
77
-
104
+
78
105
  it "should load YAML data from entry file" do
79
106
  obj = Post.load_file(FIRST)
80
107
  obj.should be_a(Post)
81
108
  obj.title.should == 'First'
82
-
109
+
83
110
  obj = Post.load_file(SECOND)
84
111
  obj.should be_a(Post)
85
112
  obj.title.should be_nil
86
113
  end
87
-
114
+
88
115
  it "should load text data from entry file" do
89
116
  post = Post.load_file(FIRST)
90
117
  post.summary.should == 'first --- content'
91
118
  post.content.rstrip.should == "big\n---\ncontent"
92
-
119
+
93
120
  post = Post.load_file(SECOND)
94
121
  post.summary.rstrip.should == " only one"
95
122
  post.content.should be_nil
96
123
  end
97
-
124
+
98
125
  it "should load data from list file" do
99
126
  authors = Author.load_file(EXTERN)
100
127
  authors.length.should == 2
101
-
128
+
102
129
  authors[0].should be_a(Author)
103
130
  authors[0].login.should be_nil
104
131
  authors[0].name.should == 'Anonymous'
105
-
132
+
106
133
  authors[1].should be_a(Author)
107
134
  authors[1].login.should == 'super1997'
108
135
  authors[1].name.should == 'SuperHacker'
109
136
  end
110
-
137
+
111
138
  it "shouldn't define text data in model with list storage" do
112
139
  lambda {
113
140
  klass = Class.new do
@@ -117,45 +144,79 @@ describe PlainRecord::Model do
117
144
  end
118
145
  }.should raise_error /entry_in/
119
146
  end
120
-
147
+
121
148
  it "should load all entries" do
122
- Post.all.should == [SECOND_POST, THIRD_POST, FIRST_POST]
149
+ Post.all.should =~ [SECOND_POST, THIRD_POST, FIRST_POST]
123
150
  end
124
-
151
+
125
152
  it "should return entries by string matcher" do
126
153
  Post.all(:title => 'First').should == [FIRST_POST]
127
154
  end
128
-
155
+
129
156
  it "should return entries by regexp matcher" do
130
157
  Post.all(:title => /First/, :title => /Second/).should be_empty
131
158
  end
132
-
159
+
133
160
  it "should return entries by search proc" do
134
- Post.all { |i| not i.title.nil? }.should == [THIRD_POST, FIRST_POST]
161
+ Post.all { |i| not i.title.nil? }.should =~ [THIRD_POST, FIRST_POST]
135
162
  end
136
-
163
+
137
164
  it "should return all list entries" do
138
- Author.all.map { |i| i.login }.should == [nil, 'super1997', 'john', 'ivan']
165
+ Author.all.map { |i| i.login }.should =~ [nil, 'super1997', 'john', 'ivan']
139
166
  end
140
-
167
+
141
168
  it "should return first entry" do
142
169
  Post.first.should be_a(Post)
143
170
  end
144
-
171
+
145
172
  it "should return entry by string matcher" do
146
173
  Post.first(:title => 'Third').should == THIRD_POST
147
174
  end
148
-
175
+
149
176
  it "should return entry by regexp matcher" do
150
- Post.first(:title => /First|Third/).should == THIRD_POST
177
+ Post.first(:title => /First/).should == FIRST_POST
151
178
  end
152
-
179
+
153
180
  it "should return entry by search proc" do
154
181
  Post.first { |i| false }.should be_nil
155
182
  end
156
-
183
+
157
184
  it "should return first list entry" do
158
- Author.first { |i| not i.login.nil? }.name.should == 'SuperHacker'
185
+ Author.first { |i| not i.login.nil? and i.type == 'extern' }.
186
+ name.should == 'SuperHacker'
187
+ end
188
+
189
+ it "should delete file, cache and empty dirs" do
190
+ File.should_receive(:delete).with(FIRST)
191
+
192
+ first_dir = File.dirname(FIRST)
193
+ Dir.should_receive(:entries).with(first_dir).and_return(['.', '..'])
194
+ Dir.should_receive(:rmdir).with(first_dir)
195
+ Dir.should_receive(:entries).with(File.dirname(first_dir)).and_return(
196
+ ['.', '..', '2', '3'])
197
+
198
+ Post.instance_eval { delete_file(FIRST) }
199
+ Post.loaded.should_not have_key(FIRST)
200
+ end
201
+
202
+ it "should move entry from one file to another" do
203
+ first = Post.first(:title => 'First')
204
+ Post.should_receive(:delete_file).with(FIRST)
205
+ Post.should_receive(:save_file).with(PlainRecord.root('file'))
206
+ first.file = 'file'
207
+ first.save
208
+ end
209
+
210
+ it "should move list entry from one file to another" do
211
+ Author.should_receive(:save_file).with(INTERN).once
212
+ Author.should_receive(:save_file).with(PlainRecord.root('file')).twice
213
+ Author.should_receive(:delete_file).with(INTERN).once
214
+
215
+ authors = Author.all(:login => /john|ivan/)
216
+ authors.each do |author|
217
+ author.file = 'file'
218
+ author.save
219
+ end
159
220
  end
160
-
221
+
161
222
  end
@@ -1,30 +1,35 @@
1
1
  require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
3
  describe PlainRecord::Resource do
4
-
4
+
5
+ after :each do
6
+ Post.loaded = { }
7
+ Author.loaded = { }
8
+ end
9
+
5
10
  it "should compare two object" do
6
- first = Post.load_file(FIRST)
7
- another_first = Post.load_file(FIRST)
8
- second = Post.load_file(SECOND)
9
-
10
- first.should == another_first
11
+ first = Post.load_file(FIRST)
12
+ another = Post.load_file(FIRST)
13
+ second = Post.load_file(SECOND)
14
+
15
+ first.should == another
11
16
  first.should_not == second
12
17
  end
13
-
18
+
14
19
  it "should remeber it file" do
15
20
  Post.load_file(FIRST).file.should == FIRST
21
+ Post.load_file(FIRST).path.should == 'data/1/post.md'
16
22
  end
17
-
23
+
18
24
  it "should save entry" do
19
25
  file = StringIO.new
20
26
  File.should_receive(:open).with(FIRST, 'w').and_yield(file)
21
-
27
+
22
28
  first = Post.first(:title => 'First')
23
- first.title = 'First 1'
24
29
  first.save
25
-
30
+
26
31
  file.rewind
27
- file.read.should == "title: First 1\n" +
32
+ file.read.should == "title: First\n" +
28
33
  "---\n" +
29
34
  "first --- content\n" +
30
35
  "---\n" +
@@ -32,20 +37,76 @@ describe PlainRecord::Resource do
32
37
  "---\n" +
33
38
  "content\n"
34
39
  end
35
-
36
- it "should save in_list entry" do
40
+
41
+ it "should save list entry" do
37
42
  file = StringIO.new
43
+ Author.all
38
44
  File.should_receive(:open).with(INTERN, 'w').and_yield(file)
39
-
45
+
40
46
  john = Author.first(:login => 'john')
41
- john.name = 'New name'
42
47
  john.save
43
-
44
- file.rewind
45
- file.read.should == "- login: john\n" +
46
- " name: New name\n" +
47
- "- login: ivan\n" +
48
- " name: Ivan Ivanov\n"
48
+
49
+ file.should has_yaml([
50
+ { 'name' => 'John Smith', 'login' => 'john' },
51
+ { 'name' => 'Ivan Ivanov', 'login' => 'ivan' }
52
+ ])
49
53
  end
50
-
54
+
55
+ it "should delete entry" do
56
+ Post.should_receive(:delete_file).with(FIRST)
57
+ Post.first(:title => 'First').destroy
58
+ end
59
+
60
+ it "should save entry without file if model use only one file" do
61
+ class Model
62
+ include PlainRecord::Resource
63
+ list_in 'file.yml'
64
+ end
65
+
66
+ path = PlainRecord.root('file.yml')
67
+ File.should_receive(:open).with(path, 'w').and_yield(StringIO.new)
68
+ Model.new.save
69
+ end
70
+
71
+ it "should delete list entry" do
72
+ file = StringIO.new
73
+ Author.all
74
+ File.should_receive(:open).with(INTERN, 'w').and_yield(file)
75
+
76
+ Author.first(:login => 'john').destroy
77
+
78
+ Author.first(:login => 'john').should be_nil
79
+
80
+ file.should has_yaml([{ 'name' => 'Ivan Ivanov', 'login' => 'ivan' }])
81
+
82
+ Author.should_receive(:delete_file).with(INTERN)
83
+ Author.first(:login => 'ivan').destroy
84
+ end
85
+
86
+ it "should call callbacks" do
87
+ class Callbacked
88
+ include PlainRecord::Resource
89
+ entry_in 'data/*/post.md'
90
+ property :title
91
+ text :summary
92
+ text :content
93
+ end
94
+
95
+ callbacks = mock()
96
+ callbacks.should_receive(:path).
97
+ with(Callbacked.path, { :title => 'First' }).and_return('data/1/post.md')
98
+ callbacks.should_receive(:load).with(an_instance_of Callbacked)
99
+ callbacks.should_receive(:save).with(an_instance_of Callbacked).and_raise
100
+ callbacks.should_receive(:destroy).with(an_instance_of Callbacked).and_raise
101
+
102
+ Callbacked.after :path, &callbacks.method(:path)
103
+ Callbacked.before :load, &callbacks.method(:load)
104
+ Callbacked.before :save, &callbacks.method(:save)
105
+ Callbacked.before :destroy, &callbacks.method(:destroy)
106
+
107
+ first = Callbacked.first({ :title => 'First' })
108
+ lambda { first.save }.should raise_error
109
+ lambda { first.destroy }.should raise_error
110
+ end
111
+
51
112
  end