plain_record 0.2 → 0.3
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/.travis.yml +0 -1
- data/ChangeLog +11 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +10 -1
- data/README.md +18 -13
- data/lib/plain_record/association_proxy.rb +14 -13
- data/lib/plain_record/associations.rb +80 -80
- data/lib/plain_record/callbacks.rb +3 -2
- data/lib/plain_record/default.rb +56 -0
- data/lib/plain_record/extra/git.rb +97 -0
- data/lib/plain_record/extra/i18n.rb +157 -0
- data/lib/plain_record/filepath.rb +31 -39
- data/lib/plain_record/model/entry.rb +2 -1
- data/lib/plain_record/model/list.rb +2 -1
- data/lib/plain_record/model.rb +117 -88
- data/lib/plain_record/resource.rb +10 -9
- data/lib/plain_record/type.rb +86 -0
- data/lib/plain_record/version.rb +1 -1
- data/lib/plain_record.rb +17 -2
- data/plain_record.gemspec +3 -1
- data/spec/associations_spec.rb +12 -8
- data/spec/data/2/comments.yml +2 -0
- data/spec/data/2/post.md +1 -1
- data/spec/default_spec.rb +17 -0
- data/spec/filepath_spec.rb +10 -10
- data/spec/git_spec.rb +55 -0
- data/spec/i18n_spec.rb +167 -0
- data/spec/model_spec.rb +71 -30
- data/spec/plain_record_spec.rb +28 -0
- data/spec/resource_spec.rb +3 -3
- data/spec/spec_helper.rb +10 -24
- data/spec/type_spec.rb +129 -0
- metadata +47 -15
@@ -0,0 +1,86 @@
|
|
1
|
+
=begin
|
2
|
+
Extention to convert fields to special type.
|
3
|
+
|
4
|
+
Copyright (C) 2012 Andrey “A.I.” Sitnik <andrey@sitnik.ru>,
|
5
|
+
sponsored by Evil Martians.
|
6
|
+
|
7
|
+
This program is free software: you can redistribute it and/or modify
|
8
|
+
it under the terms of the GNU Lesser General Public License as published by
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
This program is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License
|
18
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
=end
|
20
|
+
|
21
|
+
require 'time'
|
22
|
+
require 'date'
|
23
|
+
|
24
|
+
module PlainRecord
|
25
|
+
# Extention to set field type and convert value to it.
|
26
|
+
#
|
27
|
+
# class Post
|
28
|
+
# include PlainRecord::Resource
|
29
|
+
#
|
30
|
+
# entry_in '*/*/post.md'
|
31
|
+
#
|
32
|
+
# field :title, type(String)
|
33
|
+
# field :visits, type(Integer)
|
34
|
+
# field :rating, type(Float)
|
35
|
+
# field :created, type(Date)
|
36
|
+
# field :updated, type(Time)
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# You can add support for your classes. Just set parse and stringify
|
40
|
+
# code to <tt>PlainRecord::Type</tt>:
|
41
|
+
#
|
42
|
+
# PlainRecord::Type.parsers[Car] = 'Car.parse(super)'
|
43
|
+
# PlainRecord::Type.stringifies[Car] = 'v.to_s'
|
44
|
+
module Type
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Filter to convert field values to some type.
|
49
|
+
def type(klass)
|
50
|
+
proc do |model, field, type|
|
51
|
+
model.add_accessors <<-EOS, __FILE__, __LINE__
|
52
|
+
def #{field}
|
53
|
+
v = super
|
54
|
+
#{Type.parsers[klass]}
|
55
|
+
end
|
56
|
+
def #{field}=(v)
|
57
|
+
super(#{Type.stringifies[klass]})
|
58
|
+
end
|
59
|
+
EOS
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class << self
|
64
|
+
# Hash of class to string of parse code.
|
65
|
+
attr_accessor :parsers
|
66
|
+
|
67
|
+
# Hash of class to string of stringify code.
|
68
|
+
attr_accessor :stringifies
|
69
|
+
end
|
70
|
+
|
71
|
+
Type.parsers = {
|
72
|
+
String => 'v ? v.to_s : v',
|
73
|
+
Integer => 'v ? v.to_i : v',
|
74
|
+
Float => 'v ? v.to_f : v',
|
75
|
+
Time => 'v.is_a?(String) ? Time.parse(v) : v',
|
76
|
+
Date => 'v.is_a?(String) ? Date.parse(v) : v'
|
77
|
+
}
|
78
|
+
Type.stringifies = {
|
79
|
+
String => 'v ? v.to_s : v',
|
80
|
+
Integer => 'v ? v.to_i : v',
|
81
|
+
Float => 'v ? v.to_f : v',
|
82
|
+
Time => 'v ? v.strftime("%Y-%m-%d %H:%M:%S %Z") : v',
|
83
|
+
Date => 'v'
|
84
|
+
}
|
85
|
+
end
|
86
|
+
end
|
data/lib/plain_record/version.rb
CHANGED
data/lib/plain_record.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
=begin
|
2
2
|
Main file to load all neccessary classes for Plain Record.
|
3
3
|
|
4
|
-
Copyright (C) 2009 Andrey “A.I.” Sitnik <andrey@sitnik.ru
|
4
|
+
Copyright (C) 2009 Andrey “A.I.” Sitnik <andrey@sitnik.ru>,
|
5
|
+
sponsored by Evil Martians.
|
5
6
|
|
6
7
|
This program is free software: you can redistribute it and/or modify
|
7
8
|
it under the terms of the GNU Lesser General Public License as published by
|
@@ -25,21 +26,29 @@ YAML::ENGINE.yamler = 'syck' if defined? YAML::ENGINE
|
|
25
26
|
dir = Pathname(__FILE__).dirname.expand_path + 'plain_record'
|
26
27
|
require dir + 'version'
|
27
28
|
require dir + 'callbacks'
|
29
|
+
require dir + 'default'
|
28
30
|
require dir + 'filepath'
|
29
31
|
require dir + 'association_proxy'
|
30
32
|
require dir + 'associations'
|
33
|
+
require dir + 'type'
|
31
34
|
require dir + 'model'
|
32
35
|
require dir + 'resource'
|
33
36
|
|
34
37
|
module PlainRecord
|
38
|
+
module Extra
|
39
|
+
autoload :Git, 'plain_record/extra/git'
|
40
|
+
autoload :I18n, 'plain_record/extra/i18n'
|
41
|
+
end
|
42
|
+
|
35
43
|
class << self
|
36
44
|
# Set new root for Model#entry_in or Model#list_in.
|
37
45
|
#
|
38
46
|
# Note, that it add last slash to root path (<tt>/content</tt> will be saved
|
39
47
|
# as <tt>/content/</tt>).
|
40
48
|
def root=(value)
|
49
|
+
value = value.to_s
|
41
50
|
value += File::SEPARATOR if File::SEPARATOR != value[-1..-1]
|
42
|
-
@root
|
51
|
+
@root = value
|
43
52
|
end
|
44
53
|
|
45
54
|
# Return root for Model#entry_in or Model#list_in.
|
@@ -50,3 +59,9 @@ module PlainRecord
|
|
50
59
|
end
|
51
60
|
end
|
52
61
|
end
|
62
|
+
|
63
|
+
if defined? Rails
|
64
|
+
ActiveSupport.on_load(:after_initialize) do
|
65
|
+
PlainRecord.root = Rails.root.join('data')
|
66
|
+
end
|
67
|
+
end
|
data/plain_record.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
'readable plain text files.'
|
10
10
|
s.description = <<-EOF
|
11
11
|
Plain Record is a data persistence, which use human editable and
|
12
|
-
readable plain text files. It
|
12
|
+
readable plain text files. It's ideal for static generated sites,
|
13
13
|
like blog or homepage.
|
14
14
|
EOF
|
15
15
|
|
@@ -27,4 +27,6 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_development_dependency "rake", [">= 0"]
|
28
28
|
s.add_development_dependency "rspec", [">= 0"]
|
29
29
|
s.add_development_dependency "redcarpet", [">= 0"]
|
30
|
+
s.add_development_dependency "r18n-core", [">= 0"]
|
31
|
+
s.add_development_dependency "i18n", [">= 0"]
|
30
32
|
end
|
data/spec/associations_spec.rb
CHANGED
@@ -10,7 +10,7 @@ describe PlainRecord::Associations do
|
|
10
10
|
class ::RatedPost
|
11
11
|
include PlainRecord::Resource
|
12
12
|
entry_in 'data/3/post.md'
|
13
|
-
|
13
|
+
field :rate, one(::Rate)
|
14
14
|
end
|
15
15
|
|
16
16
|
class ::Comment
|
@@ -21,9 +21,9 @@ describe PlainRecord::Associations do
|
|
21
21
|
virtual :commented_post_name, in_filepath(1)
|
22
22
|
virtual :commented_post, one(::FilepathPost)
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
field :author_name
|
25
|
+
field :text
|
26
|
+
field :answers, many(::Comment)
|
27
27
|
end
|
28
28
|
|
29
29
|
class ::CommentedPost
|
@@ -68,7 +68,7 @@ describe PlainRecord::Associations do
|
|
68
68
|
end
|
69
69
|
|
70
70
|
it "should load one-to-many real association" do
|
71
|
-
root = ::Comment.first()
|
71
|
+
root = ::Comment.first(:commented_post_name => '1')
|
72
72
|
root.should have(1).answers
|
73
73
|
root.answers[0].should be_instance_of(::Comment)
|
74
74
|
root.answers[0].path.should == 'data/1/comments.yml'
|
@@ -78,10 +78,11 @@ describe PlainRecord::Associations do
|
|
78
78
|
end
|
79
79
|
|
80
80
|
it "should save one-to-many real association" do
|
81
|
+
comment = ::Comment.first(:commented_post_name => '1')
|
82
|
+
|
81
83
|
file = StringIO.new
|
82
84
|
File.should_receive(:open).with(anything(), 'w').and_yield(file)
|
83
|
-
|
84
|
-
::Comment.first().save()
|
85
|
+
comment.save()
|
85
86
|
|
86
87
|
file.should has_yaml([
|
87
88
|
{
|
@@ -94,7 +95,7 @@ describe PlainRecord::Associations do
|
|
94
95
|
|
95
96
|
it "should find map for virtual association" do
|
96
97
|
PlainRecord::Associations.map(
|
97
|
-
::Comment, ::CommentedPost, 'commented_post_').should == {
|
98
|
+
::Comment, ::CommentedPost, 'commented_post_').should == {
|
98
99
|
:commented_post_name => :name }
|
99
100
|
end
|
100
101
|
|
@@ -102,6 +103,9 @@ describe PlainRecord::Associations do
|
|
102
103
|
post = ::FilepathPost.first(:name => '1')
|
103
104
|
comment = ::Comment.first(:author_name => 'super1997')
|
104
105
|
comment.commented_post.should == post
|
106
|
+
|
107
|
+
another = ::Comment.first(:commented_post_name => '2')
|
108
|
+
another.commented_post.should_not == post
|
105
109
|
end
|
106
110
|
|
107
111
|
it "should change one-to-one virtual association" do
|
data/spec/data/2/post.md
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe PlainRecord::Default do
|
4
|
+
|
5
|
+
it "should set default value for field" do
|
6
|
+
klass = Class.new do
|
7
|
+
include PlainRecord::Resource
|
8
|
+
field :category, default('uncategorized')
|
9
|
+
end
|
10
|
+
post = klass.new
|
11
|
+
|
12
|
+
post.category.should == 'uncategorized'
|
13
|
+
post.category = 'a'
|
14
|
+
post.category.should == 'a'
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/spec/filepath_spec.rb
CHANGED
@@ -2,50 +2,50 @@ require File.join(File.dirname(__FILE__), 'spec_helper')
|
|
2
2
|
|
3
3
|
describe PlainRecord::Filepath do
|
4
4
|
|
5
|
-
it "shouldn't create non-virtual filepath
|
5
|
+
it "shouldn't create non-virtual filepath field" do
|
6
6
|
lambda {
|
7
7
|
Class.new do
|
8
8
|
include PlainRecord::Resource
|
9
9
|
entry_in 'data/*/post.md'
|
10
|
-
|
10
|
+
field :category, in_filepath(1)
|
11
11
|
end
|
12
12
|
}.should raise_error(ArgumentError, /virtual creator/)
|
13
13
|
end
|
14
14
|
|
15
|
-
it "should load filepath
|
15
|
+
it "should load filepath field" do
|
16
16
|
best = FilepathPost.first(:title => 'Best')
|
17
17
|
best.category.should == 'best/'
|
18
|
-
best.name.should
|
18
|
+
best.name.should == '4'
|
19
19
|
end
|
20
20
|
|
21
|
-
it "should load filepath
|
21
|
+
it "should load filepath field as nil when ** pattern is empty" do
|
22
22
|
FilepathPost.first(:title => 'First').category.should be_empty
|
23
23
|
end
|
24
24
|
|
25
|
-
it "should return more accurate path by filepath
|
25
|
+
it "should return more accurate path by filepath fields" do
|
26
26
|
FilepathPost.path(:name => 2).should == 'data/**/2/post.md'
|
27
27
|
end
|
28
28
|
|
29
|
-
it "should use filepath
|
29
|
+
it "should use filepath fields in search" do
|
30
30
|
FilepathPost.loaded = { }
|
31
31
|
FilepathPost.all(:category => 'best/')
|
32
32
|
FilepathPost.loaded.should have(1).keys
|
33
33
|
end
|
34
34
|
|
35
|
-
it "should load
|
35
|
+
it "should load fields from model constructor" do
|
36
36
|
post = FilepathPost.new(:name => 5)
|
37
37
|
post.name.should == 5
|
38
38
|
post.category.should be_nil
|
39
39
|
end
|
40
40
|
|
41
|
-
it "should get entry path by filepath
|
41
|
+
it "should get entry path by filepath fields" do
|
42
42
|
path = File.join(File.dirname(__FILE__), 'data/5/post.md')
|
43
43
|
post = FilepathPost.new(:name => 5, :category => '')
|
44
44
|
FilepathPost.should_receive(:move_entry).with(post, nil, path)
|
45
45
|
post.save
|
46
46
|
end
|
47
47
|
|
48
|
-
it "should raise error, when can't get entry path by filepath
|
48
|
+
it "should raise error, when can't get entry path by filepath fields" do
|
49
49
|
post = FilepathPost.new
|
50
50
|
lambda { post.save }.should raise_error(ArgumentError, /isn't file to save/)
|
51
51
|
end
|
data/spec/git_spec.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe PlainRecord::Extra::Git do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
class TimedPost
|
7
|
+
include PlainRecord::Resource
|
8
|
+
include PlainRecord::Extra::Git
|
9
|
+
|
10
|
+
entry_in 'data/*/post.md'
|
11
|
+
|
12
|
+
virtual :name, in_filepath(1)
|
13
|
+
field :created, git_created_time
|
14
|
+
field :updated, git_modified_time
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
before do
|
19
|
+
@post = TimedPost.first(:name => '2')
|
20
|
+
|
21
|
+
@now = Time.at(256)
|
22
|
+
Time.stub!(:now).and_return(@now)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should take file create time from git" do
|
26
|
+
@post.created.utc.should == Time.parse('2012-05-17 22:23:47 UTC')
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should take file updated time from git" do
|
30
|
+
@post.updated.utc.should == Time.parse('2012-05-18 07:41:52 UTC')
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should overrided git time" do
|
34
|
+
post = TimedPost.new
|
35
|
+
|
36
|
+
post.created = Time.at(0)
|
37
|
+
post.created.should == Time.at(0)
|
38
|
+
|
39
|
+
post.updated = Time.at(1)
|
40
|
+
post.updated.should == Time.at(1)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should return now for new model" do
|
44
|
+
post = TimedPost.new
|
45
|
+
post.created.should == @now
|
46
|
+
post.updated.should == @now
|
47
|
+
end
|
48
|
+
|
49
|
+
it "shoult return now if file has uncommitted changes" do
|
50
|
+
@post.stub!(:git_uncommitted?).and_return(true)
|
51
|
+
@post.created.utc.should == Time.parse('2012-05-17 22:23:47 UTC')
|
52
|
+
@post.updated.should == @now
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/spec/i18n_spec.rb
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe PlainRecord::Extra::I18n do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
class I18nPost
|
7
|
+
include PlainRecord::Resource
|
8
|
+
include PlainRecord::Extra::I18n
|
9
|
+
field :one, i18n
|
10
|
+
end
|
11
|
+
|
12
|
+
class PlainI18nPost < I18nPost
|
13
|
+
attr_accessor :locale
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should raise error on i18n filter on text" do
|
18
|
+
lambda {
|
19
|
+
klass = Class.new do
|
20
|
+
include PlainRecord::Resource
|
21
|
+
include PlainRecord::Extra::I18n
|
22
|
+
text :one, i18n
|
23
|
+
end
|
24
|
+
}.should raise_error(ArgumentError, /text/)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should save translations with locale" do
|
28
|
+
post = PlainI18nPost.new
|
29
|
+
|
30
|
+
post.locale = 'en'
|
31
|
+
post.one = 1
|
32
|
+
post.data['one'].should == { 'en' => 1 }
|
33
|
+
|
34
|
+
post.locale = 'ru'
|
35
|
+
post.one = 2
|
36
|
+
post.data['one'].should == { 'en' => 1, 'ru' => 2 }
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return untraslated field" do
|
40
|
+
post = PlainI18nPost.new
|
41
|
+
|
42
|
+
post.locale = 'en'
|
43
|
+
post.one = 1
|
44
|
+
post.untraslated_one.should == { 'en' => 1 }
|
45
|
+
|
46
|
+
post.untraslated_one = { 'ru' => 2 }
|
47
|
+
post.data['one'] == { 'ru' => 2 }
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should return original field if it is not hash" do
|
51
|
+
post = PlainI18nPost.new
|
52
|
+
post.one.should be_nil
|
53
|
+
post.data['one'] = 1
|
54
|
+
post.one.should == 1
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'plain' do
|
58
|
+
|
59
|
+
it "should raise error when locale method is not redefined" do
|
60
|
+
klass = Class.new do
|
61
|
+
include PlainRecord::Resource
|
62
|
+
include PlainRecord::Extra::I18n
|
63
|
+
field :one, i18n
|
64
|
+
end
|
65
|
+
post = klass.new
|
66
|
+
lambda { post.locale }.should raise_error(/Redefine/)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should translate method" do
|
70
|
+
post = PlainI18nPost.new
|
71
|
+
post.data['one'] = { 'en' => 1, 'ru' => 2 }
|
72
|
+
|
73
|
+
post.locale = 'en'
|
74
|
+
post.one.should == 1
|
75
|
+
|
76
|
+
post.locale = 'ru'
|
77
|
+
post.one.should == 2
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'i18n' do
|
82
|
+
before :all do
|
83
|
+
require 'i18n'
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should git locale from I18n" do
|
87
|
+
post = I18nPost.new
|
88
|
+
post.data['one'] = { 'en' => 1, 'ru' => 2 }
|
89
|
+
|
90
|
+
I18n.locale = :en
|
91
|
+
post.one == 1
|
92
|
+
|
93
|
+
I18n.locale = :ru
|
94
|
+
post.one == 2
|
95
|
+
|
96
|
+
post.one = 3
|
97
|
+
post.data['one'].should == { 'en' => 1, 'ru' => 3 }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'r18n' do
|
102
|
+
before :all do
|
103
|
+
require 'r18n-core'
|
104
|
+
end
|
105
|
+
|
106
|
+
before do
|
107
|
+
@post = I18nPost.new
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should get I18n object from R18n" do
|
111
|
+
@post.data['one'] = { 'en' => 1, 'ru' => 2 }
|
112
|
+
|
113
|
+
R18n.set('en')
|
114
|
+
@post.one == 1
|
115
|
+
|
116
|
+
R18n.set('ru')
|
117
|
+
@post.one == 2
|
118
|
+
|
119
|
+
@post.one = 3
|
120
|
+
@post.data['one'].should == { 'en' => 1, 'ru' => 3 }
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should return translated string" do
|
124
|
+
@post.data['one'] = { 'en' => '1' }
|
125
|
+
R18n.set('en')
|
126
|
+
|
127
|
+
@post.one.should be_translated
|
128
|
+
@post.one.locale.code.should == 'en'
|
129
|
+
@post.one.path.should == 'I18nPost#one'
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should find translation in user locales" do
|
133
|
+
@post.data['one'] = { 'fr' => '1' }
|
134
|
+
|
135
|
+
R18n.set(['ru', 'fr'])
|
136
|
+
@post.one.should == '1'
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should return untraslated" do
|
140
|
+
@post.data['one'] = { 'fr' => '1' }
|
141
|
+
R18n.set('ru')
|
142
|
+
|
143
|
+
@post.one.should_not be_translated
|
144
|
+
@post.one.translated_path.should == 'I18nPost#'
|
145
|
+
@post.one.untranslated_path.should == 'one'
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should translate non-strings" do
|
149
|
+
@post.data['one'] = { 'ru' => { :a => 1 } }
|
150
|
+
R18n.set('ru')
|
151
|
+
|
152
|
+
@post.one.should == { :a => 1 }
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should use filters for custom type" do
|
156
|
+
klass = Class.new do
|
157
|
+
include PlainRecord::Resource
|
158
|
+
include PlainRecord::Extra::I18n
|
159
|
+
field :one, i18n('pl')
|
160
|
+
end
|
161
|
+
post = klass.new
|
162
|
+
post.data['one'] = { 'en' => { '1' => '%1 one', 'n' => '%1 ones' } }
|
163
|
+
post.one(5).should == '5 ones'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
data/spec/model_spec.rb
CHANGED
@@ -7,31 +7,33 @@ describe PlainRecord::Model do
|
|
7
7
|
Author.loaded = { }
|
8
8
|
end
|
9
9
|
|
10
|
-
it "should define virtual
|
10
|
+
it "should define virtual field" do
|
11
11
|
klass = Class.new do
|
12
12
|
include PlainRecord::Resource
|
13
|
-
virtual :one,
|
13
|
+
virtual :one, proc { }
|
14
14
|
end
|
15
15
|
|
16
16
|
klass.virtuals.should == [:one]
|
17
17
|
end
|
18
18
|
|
19
|
-
it "shouldn't define virtual
|
19
|
+
it "shouldn't define virtual field without accessor from filters" do
|
20
20
|
lambda {
|
21
21
|
Class.new do
|
22
22
|
include PlainRecord::Resource
|
23
|
-
virtual :one
|
23
|
+
virtual :one
|
24
24
|
end
|
25
25
|
}.should raise_error(ArgumentError, /own accessors/)
|
26
26
|
end
|
27
27
|
|
28
|
-
it "should define
|
28
|
+
it "should define field" do
|
29
29
|
klass = Class.new do
|
30
30
|
include PlainRecord::Resource
|
31
|
-
|
31
|
+
field :one
|
32
32
|
end
|
33
33
|
|
34
|
-
klass.
|
34
|
+
klass.fields.should == [:one]
|
35
|
+
klass.accessors_modules[:main].should has_methods(:one, :one=)
|
36
|
+
|
35
37
|
object = klass.new(nil, { 'one' => 1 })
|
36
38
|
object.one.should == 1
|
37
39
|
object.one = 2
|
@@ -45,43 +47,43 @@ describe PlainRecord::Model do
|
|
45
47
|
end
|
46
48
|
|
47
49
|
klass.texts.should == [:content]
|
50
|
+
klass.accessors_modules[:main].should has_methods(:content, :content=)
|
51
|
+
|
48
52
|
object = klass.new(nil, { }, ['text'])
|
49
53
|
object.content.should == 'text'
|
50
54
|
object.content = 'another'
|
51
55
|
object.content.should == 'another'
|
52
56
|
end
|
53
57
|
|
54
|
-
it "should
|
55
|
-
klass
|
58
|
+
it "should send field name and type type to filter" do
|
59
|
+
klass = Class.new
|
60
|
+
filter = mock
|
61
|
+
filter.stub!(:virtual).with(klass, :one, :virtual)
|
62
|
+
filter.stub!(:field).with(klass, :two, :field)
|
63
|
+
filter.stub!(:text).with(klass, :three, :text)
|
64
|
+
klass.class_eval do
|
56
65
|
include PlainRecord::Resource
|
57
|
-
|
58
|
-
|
59
|
-
text
|
60
|
-
text :four, Definers.none
|
66
|
+
virtual :one, filter.method(:virtual)
|
67
|
+
field :two, filter.method(:field)
|
68
|
+
text :three, filter.method(:text)
|
61
69
|
end
|
62
|
-
klass.should has_methods(:one, :'one=', :'three=', :two)
|
63
70
|
end
|
64
71
|
|
65
|
-
it "should
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
72
|
+
it "should override sustem accessors by filter" do
|
73
|
+
filter = proc do |model, name, type|
|
74
|
+
model.add_accessors <<-EOS, __FILE__, __LINE__
|
75
|
+
def #{name}
|
76
|
+
super + 1
|
77
|
+
end
|
78
|
+
EOS
|
70
79
|
end
|
71
|
-
klass.should has_methods(:two)
|
72
|
-
end
|
73
|
-
|
74
|
-
it "should send property name and caller type to definer" do
|
75
|
-
definer = mock
|
76
|
-
definer.stub!(:virtual).with(:one, :virtual)
|
77
|
-
definer.stub!(:property).with(:two, :property)
|
78
|
-
definer.stub!(:text).with(:three, :text)
|
79
80
|
klass = Class.new do
|
80
81
|
include PlainRecord::Resource
|
81
|
-
|
82
|
-
property :two, definer.method(:property)
|
83
|
-
text :three, definer.method(:text)
|
82
|
+
field :one, filter
|
84
83
|
end
|
84
|
+
a = klass.new
|
85
|
+
a.one = 1
|
86
|
+
a.one.should == 2
|
85
87
|
end
|
86
88
|
|
87
89
|
it "should find all enrty files by glob pattern" do
|
@@ -219,4 +221,43 @@ describe PlainRecord::Model do
|
|
219
221
|
end
|
220
222
|
end
|
221
223
|
|
224
|
+
it "should add modules for accessors" do
|
225
|
+
klass = Class.new do
|
226
|
+
include PlainRecord::Resource
|
227
|
+
end
|
228
|
+
|
229
|
+
klass.accessors_modules.should be_empty
|
230
|
+
|
231
|
+
main = klass.add_accessors(:main)
|
232
|
+
klass.add_accessors(:main).should == main
|
233
|
+
klass.accessors_modules.should have(1).keys
|
234
|
+
|
235
|
+
mod = klass.add_accessors
|
236
|
+
mod.should_not == main
|
237
|
+
klass.add_accessors.should_not == mod
|
238
|
+
klass.accessors_modules.should have(1).keys
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should define accessors" do
|
242
|
+
klass = Class.new do
|
243
|
+
include PlainRecord::Resource
|
244
|
+
end
|
245
|
+
klass.add_accessors :one, "def one; 1; end"
|
246
|
+
klass.add_accessors "def two; 2; end"
|
247
|
+
klass.add_accessors <<-EOS, __FILE__, __LINE__
|
248
|
+
def three; 3; end
|
249
|
+
EOS
|
250
|
+
|
251
|
+
klass.should has_methods(:one, :two, :three)
|
252
|
+
end
|
253
|
+
|
254
|
+
it "should allow to define filters as Hash" do
|
255
|
+
klass = Class.new do
|
256
|
+
include PlainRecord::Resource
|
257
|
+
field :one, :default => 1
|
258
|
+
end
|
259
|
+
a = klass.new
|
260
|
+
a.one.should == 1
|
261
|
+
end
|
262
|
+
|
222
263
|
end
|