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,157 @@
|
|
1
|
+
=begin
|
2
|
+
Extention to get field value depend on user locale.
|
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
|
+
module PlainRecord::Extra
|
22
|
+
# Extention to get field value depend on user locale.
|
23
|
+
#
|
24
|
+
# You can’t use this filter for texts, because you need to set hash of
|
25
|
+
# language code to translated string. For example in YAML fiels:
|
26
|
+
#
|
27
|
+
# title:
|
28
|
+
# en: Title
|
29
|
+
# ru: Заголовок
|
30
|
+
#
|
31
|
+
# Then just set filter to `virtual` or `field`.
|
32
|
+
#
|
33
|
+
# class Post
|
34
|
+
# include PlainRecord::Resource
|
35
|
+
# include PlainRecord::Extra::I18n
|
36
|
+
#
|
37
|
+
# field :title, i18n
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# By default, this filter will use current locale from Rails I18n or R18n,
|
41
|
+
# if they are defined. If you need to take locale from another space, just
|
42
|
+
# redefine `locale` model method.
|
43
|
+
#
|
44
|
+
# class Post
|
45
|
+
# def locale
|
46
|
+
# ENV['locale']
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
module I18n
|
50
|
+
class << self
|
51
|
+
def included(base)
|
52
|
+
base.send :extend, Model
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Return default locale. By default it look in R18n or Rails I18n.
|
57
|
+
# Redefine it if you need another logic.
|
58
|
+
def locale
|
59
|
+
if defined? ::R18n::I18n
|
60
|
+
::R18n.get
|
61
|
+
elsif defined? ::I18n
|
62
|
+
::I18n.locale
|
63
|
+
else
|
64
|
+
raise "Can't find R18n or I18n. Redefine `locale` method."
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Return locale code depend on autodetected I18n library.
|
69
|
+
def locale_code
|
70
|
+
code = locale
|
71
|
+
if defined? R18n::I18n and code.is_a? R18n::I18n
|
72
|
+
code.locale.code
|
73
|
+
elsif code.is_a? Symbol
|
74
|
+
code.to_s
|
75
|
+
else
|
76
|
+
code
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Return subvalue of `hash` depend on user locale from `locale` method.
|
81
|
+
#
|
82
|
+
# If R18n or Rails I18n is loaded it will use them logic to translate.
|
83
|
+
def get_translation(name, hash, *params)
|
84
|
+
return hash unless hash.is_a? Hash
|
85
|
+
path = "#{self.class.name}##{name}"
|
86
|
+
|
87
|
+
if defined? R18n::I18n and locale.is_a? R18n::I18n
|
88
|
+
r18n = locale
|
89
|
+
r18n.locales.each do |lang|
|
90
|
+
code = lang.code
|
91
|
+
next unless hash.has_key? code
|
92
|
+
|
93
|
+
result = hash[code]
|
94
|
+
type = self.class.fields_i18n_types[name.to_sym]
|
95
|
+
|
96
|
+
if type
|
97
|
+
return r18n.filter_list.
|
98
|
+
process(:all, type, result, lang, path, params)
|
99
|
+
elsif result.is_a? String
|
100
|
+
result = ::R18n::TranslatedString.new(result, lang, path)
|
101
|
+
return r18n.filter_list.process_string(:all, result, path, params)
|
102
|
+
else
|
103
|
+
return result
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
::R18n::Untranslated.new("#{self.class.name}#", name,
|
108
|
+
locale.locale, locale.filter_list)
|
109
|
+
|
110
|
+
elsif defined? ::I18n
|
111
|
+
hash[locale.to_s]
|
112
|
+
|
113
|
+
else
|
114
|
+
hash[locale]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
module Model
|
119
|
+
# R18n type for fields.
|
120
|
+
attr_accessor :fields_i18n_types
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
# Filter to return value depend on model locale.
|
125
|
+
#
|
126
|
+
# If you use R18n, you can set `type` to specify filters.
|
127
|
+
#
|
128
|
+
# field comment_count, i18n('pl')
|
129
|
+
def i18n(r18n_type = nil)
|
130
|
+
proc do |model, field, type|
|
131
|
+
if :text == type
|
132
|
+
raise ArgumentError, "You can't set i18n filter for text"
|
133
|
+
end
|
134
|
+
|
135
|
+
model.fields_i18n_types ||= { }
|
136
|
+
model.fields_i18n_types[field] = r18n_type if r18n_type
|
137
|
+
|
138
|
+
model.send :alias_method, "untraslated_#{field}", field
|
139
|
+
model.send :alias_method, "untraslated_#{field}=", "#{field}="
|
140
|
+
|
141
|
+
model.add_accessors <<-EOS, __FILE__, __LINE__
|
142
|
+
def #{field}(*params)
|
143
|
+
get_translation("#{field}", super, *params)
|
144
|
+
end
|
145
|
+
def #{field}=(value)
|
146
|
+
if untraslated_#{field}
|
147
|
+
untraslated_#{field}[locale_code] = value
|
148
|
+
else
|
149
|
+
super({ locale_code => value })
|
150
|
+
end
|
151
|
+
end
|
152
|
+
EOS
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
=begin
|
2
|
-
Extention to get
|
2
|
+
Extention to get field from entry file path.
|
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
|
@@ -18,18 +19,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
19
|
=end
|
19
20
|
|
20
21
|
module PlainRecord
|
21
|
-
# Extention to get
|
22
|
+
# Extention to get fields from enrty file path. For example, your blog
|
22
23
|
# post may stored in <tt>_name_/post.md</tt>, and post model will have +name+
|
23
|
-
#
|
24
|
+
# field. Also if you set name field to Model#first or Model#all method,
|
24
25
|
# they will load entry directly only by it file.
|
25
26
|
#
|
26
|
-
# To define filepath
|
27
|
+
# To define filepath field:
|
27
28
|
# 1. Use <tt>*</tt> or <tt>**</tt> pattern in model path in +enrty_in+ or
|
28
29
|
# +list_in+.
|
29
|
-
# 2. In +virtual+ method use <tt>in_filepath(i)</tt>
|
30
|
+
# 2. In +virtual+ method use <tt>in_filepath(i)</tt> filter after name with
|
30
31
|
# <tt>*</tt> or <tt>**</tt> number (start from 1).
|
31
32
|
#
|
32
|
-
# Define filepath
|
33
|
+
# Define filepath field only after +entry_in+ or +list_in+ call.
|
33
34
|
#
|
34
35
|
# class Post
|
35
36
|
# include PlainRecord::Resource
|
@@ -48,21 +49,31 @@ module PlainRecord
|
|
48
49
|
#
|
49
50
|
# bests = Post.all(category: 'best') # Look up only in best/ dir
|
50
51
|
module Filepath
|
51
|
-
attr_accessor :
|
52
|
+
attr_accessor :filepath_fields
|
52
53
|
attr_accessor :filepath_regexp
|
53
54
|
|
54
55
|
private
|
55
56
|
|
56
|
-
# Return
|
57
|
+
# Return filter for filepath field for +number+ <tt>*</tt> or
|
57
58
|
# <tt>**</tt> pattern in path.
|
58
59
|
def in_filepath(number)
|
59
|
-
proc do |
|
60
|
-
if :virtual !=
|
61
|
-
raise ArgumentError, "You must create filepath
|
60
|
+
proc do |model, field, type|
|
61
|
+
if :virtual != type
|
62
|
+
raise ArgumentError, "You must create filepath field #{field}" +
|
62
63
|
' virtual creator'
|
63
64
|
end
|
64
|
-
|
65
|
-
|
65
|
+
|
66
|
+
Filepath.install(model) unless model.filepath_fields
|
67
|
+
model.filepath_fields[number] = field
|
68
|
+
|
69
|
+
model.add_accessors <<-EOS, __FILE__, __LINE__
|
70
|
+
def #{field}
|
71
|
+
@filepath_data[:#{field}]
|
72
|
+
end
|
73
|
+
def #{field}=(value)
|
74
|
+
@filepath_data[:#{field}] = value
|
75
|
+
end
|
76
|
+
EOS
|
66
77
|
end
|
67
78
|
end
|
68
79
|
|
@@ -70,7 +81,7 @@ module PlainRecord
|
|
70
81
|
# Define class variables and events in +klass+. It should be call once on
|
71
82
|
# same class after +entry_in+ or +list_in+ call.
|
72
83
|
def install(klass)
|
73
|
-
klass.
|
84
|
+
klass.filepath_fields = { }
|
74
85
|
|
75
86
|
path = Regexp.escape(klass.path).gsub(/\\\*\\\*(\/|$)/, '(.*)').
|
76
87
|
gsub('\\*', '([^/]+)')
|
@@ -84,12 +95,12 @@ module PlainRecord
|
|
84
95
|
if entry.path
|
85
96
|
data = klass.filepath_regexp.match(entry.path)
|
86
97
|
entry.filepath_data = { }
|
87
|
-
klass.
|
98
|
+
klass.filepath_fields.each_pair do |number, name|
|
88
99
|
entry.filepath_data[name] = data[number]
|
89
100
|
end
|
90
101
|
else
|
91
102
|
entry.filepath_data = { }
|
92
|
-
klass.
|
103
|
+
klass.filepath_fields.each_value do |name|
|
93
104
|
entry.filepath_data[name] = entry.data[name]
|
94
105
|
entry.data.delete(name)
|
95
106
|
end
|
@@ -101,9 +112,9 @@ module PlainRecord
|
|
101
112
|
i = 0
|
102
113
|
path.gsub /(\*\*(\/|$)|\*)/ do |pattern|
|
103
114
|
i += 1
|
104
|
-
|
105
|
-
unless matchers[
|
106
|
-
matchers[
|
115
|
+
field = klass.filepath_fields[i]
|
116
|
+
unless matchers[field].is_a? Regexp or matchers[field].nil?
|
117
|
+
matchers[field]
|
107
118
|
else
|
108
119
|
pattern
|
109
120
|
end
|
@@ -117,25 +128,6 @@ module PlainRecord
|
|
117
128
|
end
|
118
129
|
end
|
119
130
|
end
|
120
|
-
|
121
|
-
# Define in +klass+ filepath property with +name+ for +number+ <tt>*</tt>
|
122
|
-
# or <tt>**</tt> pattern in path.
|
123
|
-
def define_property(klass, name, number)
|
124
|
-
unless klass.filepath_properties
|
125
|
-
install(klass)
|
126
|
-
end
|
127
|
-
|
128
|
-
klass.filepath_properties[number] = name
|
129
|
-
|
130
|
-
klass.class_eval <<-EOS, __FILE__, __LINE__
|
131
|
-
def #{name}
|
132
|
-
@filepath_data[:#{name}]
|
133
|
-
end
|
134
|
-
def #{name}=(value)
|
135
|
-
@filepath_data[:#{name}] = value
|
136
|
-
end
|
137
|
-
EOS
|
138
|
-
end
|
139
131
|
end
|
140
132
|
end
|
141
133
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
=begin
|
2
2
|
Class with static methods for entry_in model class.
|
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
|
@@ -1,7 +1,8 @@
|
|
1
1
|
=begin
|
2
2
|
Class with static methods for list_in model class.
|
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
|
data/lib/plain_record/model.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
=begin
|
2
2
|
Class with static methods for model class.
|
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
|
@@ -28,16 +29,18 @@ module PlainRecord
|
|
28
29
|
autoload :List, (dir + 'list').to_s
|
29
30
|
|
30
31
|
include PlainRecord::Callbacks
|
32
|
+
include PlainRecord::Default
|
31
33
|
include PlainRecord::Filepath
|
32
34
|
include PlainRecord::Associations
|
35
|
+
include PlainRecord::Type
|
33
36
|
|
34
|
-
# YAML
|
35
|
-
attr_accessor :
|
37
|
+
# YAML fields names.
|
38
|
+
attr_accessor :fields
|
36
39
|
|
37
|
-
# Name of special
|
40
|
+
# Name of special fields with big text.
|
38
41
|
attr_accessor :texts
|
39
42
|
|
40
|
-
#
|
43
|
+
# Fields names with dynamic value.
|
41
44
|
attr_accessor :virtuals
|
42
45
|
|
43
46
|
# Storage type: +:entry+ or +:list+.
|
@@ -46,11 +49,15 @@ module PlainRecord
|
|
46
49
|
# Content of already loaded files.
|
47
50
|
attr_accessor :loaded
|
48
51
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
base.
|
52
|
+
# Named modules, created by +add_accessors+.
|
53
|
+
attr_accessor :accessors_modules
|
54
|
+
|
55
|
+
def self.extended(base)
|
56
|
+
base.fields = []
|
57
|
+
base.virtuals = []
|
58
|
+
base.texts = []
|
59
|
+
base.loaded = { }
|
60
|
+
base.accessors_modules = { }
|
54
61
|
end
|
55
62
|
|
56
63
|
# Load and return all entries in +file+.
|
@@ -87,7 +94,7 @@ module PlainRecord
|
|
87
94
|
# Return all entries, which is match for +matchers+ and return true on
|
88
95
|
# +block+.
|
89
96
|
#
|
90
|
-
# Matchers is a Hash with
|
97
|
+
# Matchers is a Hash with field name in key and String or Regexp for
|
91
98
|
# match in value.
|
92
99
|
#
|
93
100
|
# Post.all(title: 'Post title')
|
@@ -103,7 +110,7 @@ module PlainRecord
|
|
103
110
|
# Return first entry, which is match for +matchers+ and return true on
|
104
111
|
# +block+.
|
105
112
|
#
|
106
|
-
# Matchers is a Hash with
|
113
|
+
# Matchers is a Hash with field name in key and String or Regexp for
|
107
114
|
# match in value.
|
108
115
|
#
|
109
116
|
# Post.first(title: 'Post title')
|
@@ -137,6 +144,50 @@ module PlainRecord
|
|
137
144
|
end
|
138
145
|
end
|
139
146
|
|
147
|
+
# Create new anonymous module and include in model.
|
148
|
+
#
|
149
|
+
# You can set +name+ and it will old module, if it was created with same
|
150
|
+
# name.
|
151
|
+
#
|
152
|
+
# It is helper to create model fields accessors and filters for it with
|
153
|
+
# +super+ support.
|
154
|
+
#
|
155
|
+
# add_accessors <<-EOS, __FILE__, __LINE__
|
156
|
+
# def #{name}
|
157
|
+
# @data['#{name}']
|
158
|
+
# end
|
159
|
+
# EOS
|
160
|
+
def add_accessors(name = nil, file = nil, line = nil, code = nil)
|
161
|
+
if name.is_a? String
|
162
|
+
code = line
|
163
|
+
line = file
|
164
|
+
file = name
|
165
|
+
name = nil
|
166
|
+
end
|
167
|
+
|
168
|
+
if file and code.nil?
|
169
|
+
code = file
|
170
|
+
file = line = nil
|
171
|
+
end
|
172
|
+
|
173
|
+
if name and @accessors_modules.has_key? name
|
174
|
+
mod = @accessors_modules[name]
|
175
|
+
else
|
176
|
+
mod = Module.new
|
177
|
+
if name
|
178
|
+
@accessors_modules[name] = mod
|
179
|
+
end
|
180
|
+
include mod
|
181
|
+
end
|
182
|
+
|
183
|
+
if file and code
|
184
|
+
mod.module_eval(file, line, code)
|
185
|
+
elsif code
|
186
|
+
mod.module_eval(code)
|
187
|
+
end
|
188
|
+
mod
|
189
|
+
end
|
190
|
+
|
140
191
|
private
|
141
192
|
|
142
193
|
# Return all model entries, which is may be match for +matchers+.
|
@@ -200,13 +251,12 @@ module PlainRecord
|
|
200
251
|
self.extend PlainRecord::Model::List
|
201
252
|
end
|
202
253
|
|
203
|
-
# Add virtual
|
254
|
+
# Add virtual field with some +name+ to model. It value willn’t be in
|
204
255
|
# file and will be calculated dynamically.
|
205
256
|
#
|
206
|
-
# You _must_ provide your own define logic by +
|
207
|
-
# will be call with
|
208
|
-
#
|
209
|
-
# to access to property.
|
257
|
+
# You _must_ provide your own define logic by +filters+. Filter Proc
|
258
|
+
# will be call with models class as first argument, field name as second and
|
259
|
+
# field type as second.
|
210
260
|
#
|
211
261
|
# class Post
|
212
262
|
# include PlainRecord::Resource
|
@@ -215,61 +265,53 @@ module PlainRecord
|
|
215
265
|
#
|
216
266
|
# virtual :name, in_filepath(1)
|
217
267
|
# end
|
218
|
-
def virtual(name, *
|
268
|
+
def virtual(name, *filters)
|
219
269
|
@virtuals ||= []
|
220
270
|
@virtuals << name
|
221
271
|
|
222
|
-
|
223
|
-
|
224
|
-
if accessors[:reader] or accessors[:writer]
|
272
|
+
if filters.length.zero?
|
225
273
|
raise ArgumentError, 'You must provide you own accessors for virtual ' +
|
226
|
-
"
|
274
|
+
"field #{name} by any filter"
|
227
275
|
end
|
276
|
+
|
277
|
+
field_filters(filters, name, :virtual)
|
228
278
|
end
|
229
279
|
|
230
|
-
# Add
|
280
|
+
# Add field with some +name+ to model. It will be stored as YAML.
|
231
281
|
#
|
232
|
-
# You
|
233
|
-
#
|
234
|
-
#
|
235
|
-
# to access to property.
|
282
|
+
# You may provide your own define logic by +filters+. Filter Proc will be
|
283
|
+
# call with models class as first argument, field name as second and
|
284
|
+
# field type as second.
|
236
285
|
#
|
237
286
|
# class Post
|
238
287
|
# include PlainRecord::Resource
|
239
288
|
#
|
240
289
|
# entry_in 'posts/*/post.md'
|
241
290
|
#
|
242
|
-
#
|
291
|
+
# field :title
|
243
292
|
# end
|
244
|
-
def
|
245
|
-
@
|
246
|
-
@
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
class_eval <<-EOS, __FILE__, __LINE__
|
259
|
-
def #{name}=(value)
|
260
|
-
@data['#{name}'] = value
|
261
|
-
end
|
262
|
-
EOS
|
263
|
-
end
|
293
|
+
def field(name, *filters)
|
294
|
+
@fields ||= []
|
295
|
+
@fields << name
|
296
|
+
|
297
|
+
add_accessors :main, <<-EOS, __FILE__, __LINE__
|
298
|
+
def #{name}(*params)
|
299
|
+
@data['#{name}']
|
300
|
+
end
|
301
|
+
def #{name}=(value)
|
302
|
+
@data['#{name}'] = value
|
303
|
+
end
|
304
|
+
EOS
|
305
|
+
|
306
|
+
field_filters(filters, name, :field)
|
264
307
|
end
|
265
308
|
|
266
|
-
# Add special
|
267
|
-
# will stored after 3 dashes (<tt>---</tt>).
|
309
|
+
# Add special field with big text (for example, blog entry content).
|
310
|
+
# It will stored after 3 dashes (<tt>---</tt>).
|
268
311
|
#
|
269
|
-
# You
|
270
|
-
#
|
271
|
-
#
|
272
|
-
# to access to property.
|
312
|
+
# You may provide your own define logic by +filter+. Filter Proc will be
|
313
|
+
# call with models class as first argument, field name as second and
|
314
|
+
# field type as second.
|
273
315
|
#
|
274
316
|
# Note, that text is supported by only +entry_in+ models, which entry store
|
275
317
|
# in separated files.
|
@@ -283,9 +325,9 @@ module PlainRecord
|
|
283
325
|
#
|
284
326
|
# entry_in 'posts/*/post.md'
|
285
327
|
#
|
286
|
-
#
|
287
|
-
# text
|
288
|
-
# text
|
328
|
+
# field :title
|
329
|
+
# text :summary
|
330
|
+
# text :content
|
289
331
|
# end
|
290
332
|
#
|
291
333
|
# File:
|
@@ -295,7 +337,7 @@ module PlainRecord
|
|
295
337
|
# Post summary
|
296
338
|
# ---
|
297
339
|
# Post text
|
298
|
-
def text(name, *
|
340
|
+
def text(name, *filters)
|
299
341
|
if :list == @storage
|
300
342
|
raise ArgumentError, 'Text is supported by only entry_in models'
|
301
343
|
end
|
@@ -304,41 +346,28 @@ module PlainRecord
|
|
304
346
|
@texts << name
|
305
347
|
number = @texts.length - 1
|
306
348
|
|
307
|
-
|
349
|
+
add_accessors :main, <<-EOS, __FILE__, __LINE__
|
350
|
+
def #{name}
|
351
|
+
@texts[#{number}]
|
352
|
+
end
|
353
|
+
def #{name}=(value)
|
354
|
+
@texts[#{number}] = value
|
355
|
+
end
|
356
|
+
EOS
|
308
357
|
|
309
|
-
|
310
|
-
class_eval <<-EOS, __FILE__, __LINE__
|
311
|
-
def #{name}
|
312
|
-
@texts[#{number}]
|
313
|
-
end
|
314
|
-
EOS
|
315
|
-
end
|
316
|
-
if accessors[:writer]
|
317
|
-
class_eval <<-EOS, __FILE__, __LINE__
|
318
|
-
def #{name}=(value)
|
319
|
-
@texts[#{number}] = value
|
320
|
-
end
|
321
|
-
EOS
|
322
|
-
end
|
358
|
+
field_filters(filters, name, :text)
|
323
359
|
end
|
324
360
|
|
325
|
-
# Call +
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
if :writer == access or access.nil?
|
334
|
-
accessors[:reader] = false
|
335
|
-
end
|
336
|
-
if :reader == access or access.nil?
|
337
|
-
accessors[:writer] = false
|
361
|
+
# Call all +filters+ for some +field+ with +type+.
|
362
|
+
def field_filters(filters, field, type)
|
363
|
+
filters.each do |filter|
|
364
|
+
if filter.is_a? Hash
|
365
|
+
filter = filter.map { |name, param| send(name, param) }
|
366
|
+
field_filters(filter, field, type)
|
367
|
+
else
|
368
|
+
filter.call(self, field, type)
|
338
369
|
end
|
339
370
|
end
|
340
|
-
|
341
|
-
accessors
|
342
371
|
end
|
343
372
|
end
|
344
373
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
=begin
|
2
2
|
Module to be included into model class.
|
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
|
@@ -29,7 +30,7 @@ module PlainRecord
|
|
29
30
|
# * <tt>save(entry)</tt> – write entry to file.
|
30
31
|
# See PlainRecord::Callbacks for details.
|
31
32
|
#
|
32
|
-
# You can define
|
33
|
+
# You can define fields from entry file path, by +in_filepath+ filter.
|
33
34
|
# See PlainRecord::Filepath for details.
|
34
35
|
#
|
35
36
|
# class Post
|
@@ -42,18 +43,18 @@ module PlainRecord
|
|
42
43
|
# end
|
43
44
|
#
|
44
45
|
# virtual :name, in_filepath(1)
|
45
|
-
#
|
46
|
-
# text
|
47
|
-
# text
|
46
|
+
# field :title
|
47
|
+
# text :summary
|
48
|
+
# text :content
|
48
49
|
# end
|
49
50
|
module Resource
|
50
51
|
class << self
|
51
|
-
def included(base)
|
52
|
+
def included(base)
|
52
53
|
base.send :extend, Model
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
56
|
-
#
|
57
|
+
# Fields values.
|
57
58
|
attr_reader :data
|
58
59
|
|
59
60
|
# Texts values.
|
@@ -102,7 +103,7 @@ module PlainRecord
|
|
102
103
|
self.file = self.class.path
|
103
104
|
else
|
104
105
|
raise ArgumentError, "There isn't file to save entry. " +
|
105
|
-
"Set filepath
|
106
|
+
"Set filepath fields or file."
|
106
107
|
end
|
107
108
|
end
|
108
109
|
|
@@ -122,7 +123,7 @@ module PlainRecord
|
|
122
123
|
@data.to_yaml(opts)
|
123
124
|
end
|
124
125
|
|
125
|
-
# Compare if its
|
126
|
+
# Compare if its fields and texts are equal.
|
126
127
|
def eql?(other)
|
127
128
|
return false unless other.kind_of?(self.class)
|
128
129
|
@file == other.file and @data == other.data and @texts == @texts
|