ohm-contrib 0.1.2 → 1.0.rc0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/ohm/{contrib/callbacks.rb → callbacks.rb} +20 -65
- data/lib/ohm/contrib.rb +9 -17
- data/lib/ohm/datatypes.rb +38 -0
- data/lib/ohm/{contrib/locking.rb → locking.rb} +1 -2
- data/lib/ohm/plugin.rb +54 -0
- data/lib/ohm/{contrib/scope.rb → scope.rb} +7 -6
- data/lib/ohm/{contrib/slug.rb → slug.rb} +11 -6
- data/lib/ohm/{contrib/soft_delete.rb → softdelete.rb} +23 -19
- data/lib/ohm/timestamping.rb +41 -0
- data/ohm-contrib.gemspec +30 -0
- data/rakefile +6 -0
- data/test/{instance_callbacks_test.rb → instance_callbacks.rb} +2 -6
- data/test/{macro_callbacks_test.rb → macro_callbacks.rb} +1 -9
- data/test/plugin.rb +212 -0
- data/test/{scope_test.rb → scope.rb} +2 -3
- data/test/slug.rb +24 -0
- data/test/{soft_delete_test.rb → soft_delete.rb} +13 -3
- data/test/{timestamping_test.rb → timestamping.rb} +5 -6
- metadata +33 -70
- data/Rakefile +0 -8
- data/lib/ohm/contrib/active_model_extension.rb +0 -87
- data/lib/ohm/contrib/boundaries.rb +0 -41
- data/lib/ohm/contrib/date_validations.rb +0 -23
- data/lib/ohm/contrib/extra_validations.rb +0 -48
- data/lib/ohm/contrib/fulltext_searching.rb +0 -80
- data/lib/ohm/contrib/length_validations.rb +0 -32
- data/lib/ohm/contrib/number_validations.rb +0 -14
- data/lib/ohm/contrib/timestamping.rb +0 -38
- data/lib/ohm/contrib/typecast.rb +0 -350
- data/lib/ohm/contrib/web_validations.rb +0 -52
- data/test/activemodel_test.rb +0 -27
- data/test/boundaries_test.rb +0 -45
- data/test/callbacks_lint.rb +0 -141
- data/test/date_validations_test.rb +0 -29
- data/test/fixtures/ascii8bit.txt +0 -1
- data/test/fulltext_searching_test.rb +0 -63
- data/test/length_validations_test.rb +0 -31
- data/test/membership_validation_test.rb +0 -31
- data/test/number_validations_test.rb +0 -37
- data/test/slug_test.rb +0 -30
- data/test/typecast_array_test.rb +0 -146
- data/test/typecast_boolean_test.rb +0 -43
- data/test/typecast_date_test.rb +0 -82
- data/test/typecast_decimal_test.rb +0 -82
- data/test/typecast_existing_attribute_test.rb +0 -22
- data/test/typecast_float_test.rb +0 -57
- data/test/typecast_hash_test.rb +0 -120
- data/test/typecast_integer_test.rb +0 -71
- data/test/typecast_string_test.rb +0 -43
- data/test/typecast_time_test.rb +0 -72
- data/test/typecast_timezone_test.rb +0 -37
- data/test/web_validations_test.rb +0 -79
@@ -1,80 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require "text"
|
3
|
-
rescue LoadError
|
4
|
-
raise LoadError,
|
5
|
-
"Type `[sudo] gem install text` to use Ohm::FulltextSearching."
|
6
|
-
end
|
7
|
-
|
8
|
-
module Ohm
|
9
|
-
module FulltextSearching
|
10
|
-
def self.included(model)
|
11
|
-
model.extend ClassMethods
|
12
|
-
end
|
13
|
-
|
14
|
-
module ClassMethods
|
15
|
-
def search(hash)
|
16
|
-
find(hash_to_metaphones(hash))
|
17
|
-
end
|
18
|
-
|
19
|
-
def hash_to_metaphones(hash)
|
20
|
-
ret = Hash.new { |h, k| h[k] = [] }
|
21
|
-
|
22
|
-
hash.each do |att, string|
|
23
|
-
metaphones(string).each { |m| ret[:"fulltext_#{att}"] << m }
|
24
|
-
end
|
25
|
-
|
26
|
-
return ret
|
27
|
-
end
|
28
|
-
|
29
|
-
def double_metaphone(str)
|
30
|
-
return [] if STOPWORDS.include?(str.to_s.downcase)
|
31
|
-
|
32
|
-
Text::Metaphone.double_metaphone(str).compact
|
33
|
-
end
|
34
|
-
|
35
|
-
def metaphones(str)
|
36
|
-
str.to_s.strip.split(/\s+/).map { |s| double_metaphone(s) }.flatten
|
37
|
-
end
|
38
|
-
|
39
|
-
def fulltext(att)
|
40
|
-
field = :"fulltext_#{att}"
|
41
|
-
|
42
|
-
define_method(field) { self.class.metaphones(send(att)) }
|
43
|
-
index(field)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
STOPWORDS = %w{a about above according across actually adj after
|
48
|
-
afterwards again against all almost alone along already also although
|
49
|
-
always among amongst an and another any anyhow anyone anything anywhere
|
50
|
-
are aren't around as at b be became because become becomes becoming
|
51
|
-
been before beforehand begin behind being below beside besides between
|
52
|
-
beyond both but by c can can't cannot caption co co. could couldn't d
|
53
|
-
did didn't do does doesn't don't down during e each eg eight eighty
|
54
|
-
either else elsewhere end ending enough etc even ever every everyone
|
55
|
-
everything everywhere except f few first for found from further g h
|
56
|
-
had has hasn't have haven't he he'd he'll he's hence her here here's
|
57
|
-
hereafter hereby herein hereupon hers herself him himself his how
|
58
|
-
however hundred i i'd i'll i'm i've ie if in inc. indeed instead into is
|
59
|
-
isn't it it's its itself j k l last later latter latterly least less let
|
60
|
-
let's like likely ltd m made make makes many maybe me meantime meanwhile
|
61
|
-
might miss more moreover most mostly mr mrs much must my myself n namely
|
62
|
-
neither never nevertheless next nine ninety no nobody none nonetheless
|
63
|
-
noone nor not nothing now nowhere o of off often on once one one's only
|
64
|
-
onto or other others otherwise our ours ourselves out over overall own
|
65
|
-
p per perhaps q r rather recent recently s same seem seemed seeming
|
66
|
-
seems seven several she she'd she'll she's should shouldn't since so
|
67
|
-
some somehow someone something sometime sometimes somewhere still such
|
68
|
-
t taking than that that'll that's that've the their them themselves then
|
69
|
-
thence there there'd there'll there're there's there've thereafter thereby
|
70
|
-
therefore therein thereupon these they they'd they'll they're they've
|
71
|
-
thirty this those though three through throughout thru thus to together
|
72
|
-
too toward towards u under unless unlike unlikely until up upon us used
|
73
|
-
using v very via w was wasn't we we'd we'll we're we've well were weren't
|
74
|
-
what what'll what's what've whatever when whence whenever where where's
|
75
|
-
whereafter whereas whereby wherein whereupon wherever whether which while
|
76
|
-
whither who who'd who'll who's whoever whole whom whomever whose why will
|
77
|
-
with within without won't would wouldn't x y yes yet you you'd you'll
|
78
|
-
you're you've your yours yourself yourselves z}
|
79
|
-
end
|
80
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module Ohm
|
2
|
-
module LengthValidations
|
3
|
-
|
4
|
-
def assert_min_length(att, length, error = [att, :too_short])
|
5
|
-
if assert_present(att, error)
|
6
|
-
m = send(att).to_s
|
7
|
-
assert is_long_enough?(m, length), error
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def assert_max_length(att, length, error = [att, :too_long])
|
12
|
-
if assert_present(att, error)
|
13
|
-
m = send(att).to_s
|
14
|
-
assert is_too_long?(m, length), error
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
def is_too_long?(string, length)
|
20
|
-
string.size <= length
|
21
|
-
rescue ArgumentError
|
22
|
-
return false
|
23
|
-
end
|
24
|
-
|
25
|
-
def is_long_enough?(string, length)
|
26
|
-
string.size >= length
|
27
|
-
rescue ArgumentError
|
28
|
-
return false
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module Ohm
|
2
|
-
# This module will include all numeric validation needs.
|
3
|
-
# As of VERSION 0.0.27, Ohm::NumberValidations#assert_decimal
|
4
|
-
# is the only method provided.
|
5
|
-
module NumberValidations
|
6
|
-
DECIMAL_REGEX = /^(\d+)?(\.\d+)?$/
|
7
|
-
|
8
|
-
protected
|
9
|
-
def assert_decimal(att, error = [att, :not_decimal])
|
10
|
-
assert_format att, DECIMAL_REGEX, error
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
@@ -1,38 +0,0 @@
|
|
1
|
-
module Ohm
|
2
|
-
# Provides created_at / updated_at timestamps.
|
3
|
-
#
|
4
|
-
# @example
|
5
|
-
#
|
6
|
-
# class Post < Ohm::Model
|
7
|
-
# include Ohm::Timestamping
|
8
|
-
# end
|
9
|
-
#
|
10
|
-
# post = Post.create
|
11
|
-
# post.created_at.to_s == Time.now.utc.to_s
|
12
|
-
# # => true
|
13
|
-
#
|
14
|
-
# post = Post[post.id]
|
15
|
-
# post.save
|
16
|
-
# post.updated_at.to_s == Time.now.utc.to_s
|
17
|
-
# # => true
|
18
|
-
module Timestamping
|
19
|
-
def self.included(base)
|
20
|
-
base.attribute :created_at
|
21
|
-
base.attribute :updated_at
|
22
|
-
end
|
23
|
-
|
24
|
-
def create
|
25
|
-
self.created_at ||= Time.now.utc.to_s
|
26
|
-
|
27
|
-
super
|
28
|
-
end
|
29
|
-
|
30
|
-
protected
|
31
|
-
def write
|
32
|
-
self.updated_at = Time.now.utc.to_s
|
33
|
-
|
34
|
-
super
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
data/lib/ohm/contrib/typecast.rb
DELETED
@@ -1,350 +0,0 @@
|
|
1
|
-
require 'bigdecimal'
|
2
|
-
require 'time'
|
3
|
-
require 'date'
|
4
|
-
require 'forwardable'
|
5
|
-
require "json"
|
6
|
-
|
7
|
-
module Ohm
|
8
|
-
# Provides all the primitive types. The following are included:
|
9
|
-
#
|
10
|
-
# * String
|
11
|
-
# * Decimal
|
12
|
-
# * Integer
|
13
|
-
# * Float
|
14
|
-
# * Date
|
15
|
-
# * Time
|
16
|
-
# * Hash
|
17
|
-
# * Array
|
18
|
-
# * Boolean
|
19
|
-
module Types
|
20
|
-
def self.defined?(type)
|
21
|
-
@_constants ||= constants.map { |c| c.to_sym }
|
22
|
-
@_constants.include?(type.to_sym)
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.[](type)
|
26
|
-
const_get(type.to_s.split('::').last)
|
27
|
-
end
|
28
|
-
|
29
|
-
class Base < BasicObject
|
30
|
-
class Exception < ::Exception; end
|
31
|
-
|
32
|
-
extend ::Forwardable
|
33
|
-
|
34
|
-
@@delegation_blacklist = [
|
35
|
-
:==, :to_s, :initialize, :inspect, :object_id, :__send__, :__id__,
|
36
|
-
:respond_to?
|
37
|
-
]
|
38
|
-
|
39
|
-
def self.[](value)
|
40
|
-
return empty if value.to_s.empty?
|
41
|
-
|
42
|
-
new(value)
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.empty
|
46
|
-
defined?(self::RAW) ? self::RAW.new : nil
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.delegate_to(klass, except = @@delegation_blacklist)
|
50
|
-
methods = klass.public_instance_methods.map { |e| e.to_sym } - except
|
51
|
-
def_delegators :object, *methods
|
52
|
-
end
|
53
|
-
|
54
|
-
def inspect
|
55
|
-
@raw.inspect
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
class Primitive < Base
|
60
|
-
def initialize(value)
|
61
|
-
@raw = value
|
62
|
-
end
|
63
|
-
|
64
|
-
def to_s
|
65
|
-
@raw.to_s
|
66
|
-
end
|
67
|
-
|
68
|
-
def ==(other)
|
69
|
-
to_s == other.to_s
|
70
|
-
end
|
71
|
-
|
72
|
-
def respond_to?(method)
|
73
|
-
object.respond_to?(method)
|
74
|
-
rescue ::ArgumentError
|
75
|
-
@raw.respond_to?(method)
|
76
|
-
end
|
77
|
-
|
78
|
-
def object
|
79
|
-
@raw
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
class String < Primitive
|
84
|
-
delegate_to ::String
|
85
|
-
|
86
|
-
def type
|
87
|
-
::String
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
class Decimal < Primitive
|
92
|
-
delegate_to ::BigDecimal
|
93
|
-
|
94
|
-
def object
|
95
|
-
::Kernel::BigDecimal(@raw)
|
96
|
-
end
|
97
|
-
|
98
|
-
def type
|
99
|
-
::BigDecimal
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
class Integer < Primitive
|
104
|
-
delegate_to ::Fixnum
|
105
|
-
|
106
|
-
def object
|
107
|
-
::Kernel::Integer(@raw)
|
108
|
-
end
|
109
|
-
|
110
|
-
def type
|
111
|
-
::Fixnum
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
class Float < Primitive
|
116
|
-
delegate_to ::Float
|
117
|
-
|
118
|
-
def object
|
119
|
-
::Kernel::Float(@raw)
|
120
|
-
end
|
121
|
-
|
122
|
-
def type
|
123
|
-
::Float
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
class Time < Primitive
|
128
|
-
delegate_to ::Time
|
129
|
-
|
130
|
-
def object
|
131
|
-
::Time.parse(@raw).utc
|
132
|
-
end
|
133
|
-
|
134
|
-
def type
|
135
|
-
::Time
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
class Date < Primitive
|
140
|
-
delegate_to ::Date
|
141
|
-
|
142
|
-
def object
|
143
|
-
::Date.parse(@raw)
|
144
|
-
end
|
145
|
-
|
146
|
-
def type
|
147
|
-
::Date
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
class Boolean
|
152
|
-
def self.[](value)
|
153
|
-
case value
|
154
|
-
when 'false', false, '0', 0 then false
|
155
|
-
when 'true', true, '1', 1 then true
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
class Serialized < Base
|
161
|
-
attr :object
|
162
|
-
|
163
|
-
def initialize(raw)
|
164
|
-
@object = case raw
|
165
|
-
when self.class::RAW
|
166
|
-
raw
|
167
|
-
when ::String
|
168
|
-
begin
|
169
|
-
::JSON.parse(raw)
|
170
|
-
rescue ::JSON::ParserError
|
171
|
-
raw
|
172
|
-
end
|
173
|
-
when self.class
|
174
|
-
raw.object
|
175
|
-
else
|
176
|
-
::Kernel.raise ::TypeError,
|
177
|
-
"%s does not accept %s" % [self.class, raw.inspect]
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
def ==(other)
|
182
|
-
object == other
|
183
|
-
end
|
184
|
-
|
185
|
-
def to_s
|
186
|
-
object.to_json
|
187
|
-
end
|
188
|
-
alias :inspect :to_s
|
189
|
-
|
190
|
-
def respond_to?(method)
|
191
|
-
object.respond_to?(method)
|
192
|
-
end
|
193
|
-
|
194
|
-
def type
|
195
|
-
self.class::RAW
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
class Hash < Serialized
|
200
|
-
RAW = ::Hash
|
201
|
-
|
202
|
-
delegate_to ::Hash
|
203
|
-
|
204
|
-
# @private since basic object doesn't include a #class we need
|
205
|
-
# to define this manually
|
206
|
-
def class
|
207
|
-
::Ohm::Types::Hash
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
class Array < Serialized
|
212
|
-
RAW = ::Array
|
213
|
-
|
214
|
-
delegate_to ::Array
|
215
|
-
|
216
|
-
# @private since basic object doesn't include a #class we need
|
217
|
-
# to define this manually
|
218
|
-
def class
|
219
|
-
::Ohm::Types::Array
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
# Provides unobtrusive, non-explosive typecasting. Instead of exploding on
|
225
|
-
# set of an invalid value, this module takes the approach of just taking in
|
226
|
-
# parameters and letting you do validation yourself. The only thing this
|
227
|
-
# module does for you is the boilerplate casting you might need to do.
|
228
|
-
#
|
229
|
-
# @example
|
230
|
-
#
|
231
|
-
# # without typecasting
|
232
|
-
# class Item < Ohm::Model
|
233
|
-
# attribute :price
|
234
|
-
# attribute :posted
|
235
|
-
# end
|
236
|
-
#
|
237
|
-
# item = Item.create(:price => 299, :posted => Time.now.utc)
|
238
|
-
# item = Item[item.id]
|
239
|
-
#
|
240
|
-
# # now when you try and grab `item.price`, its a string.
|
241
|
-
# "299" == item.price
|
242
|
-
# # => true
|
243
|
-
#
|
244
|
-
# # you can opt to manually cast everytime, or do it in the model, i.e.
|
245
|
-
#
|
246
|
-
# class Item
|
247
|
-
# def price
|
248
|
-
# BigDecimal(read_local(:price))
|
249
|
-
# end
|
250
|
-
# end
|
251
|
-
#
|
252
|
-
# The Typecasted way
|
253
|
-
# ------------------
|
254
|
-
#
|
255
|
-
# class Item < Ohm::Model
|
256
|
-
# include Ohm::Typecast
|
257
|
-
#
|
258
|
-
# attribute :price, Decimal
|
259
|
-
# attribute :posted, Time
|
260
|
-
# end
|
261
|
-
#
|
262
|
-
# item = Item.create(:price => "299", :posted => Time.now.utc)
|
263
|
-
# item = Item[item.id]
|
264
|
-
# item.price.class == BigDecimal
|
265
|
-
# # => true
|
266
|
-
#
|
267
|
-
# item.price.to_s == "299"
|
268
|
-
# # => true
|
269
|
-
#
|
270
|
-
# item.price * 2 == 598
|
271
|
-
# # => true
|
272
|
-
#
|
273
|
-
# item.posted.strftime('%m/%d/%Y')
|
274
|
-
# # => works!!!
|
275
|
-
module Typecast
|
276
|
-
def self.included(base)
|
277
|
-
base.extend ClassMethods
|
278
|
-
end
|
279
|
-
|
280
|
-
module ClassMethods
|
281
|
-
# Defines a typecasted attribute.
|
282
|
-
#
|
283
|
-
# @example
|
284
|
-
#
|
285
|
-
# class User < Ohm::Model
|
286
|
-
# include Ohm::Typecast
|
287
|
-
#
|
288
|
-
# attribute :birthday, Date
|
289
|
-
# attribute :last_login, Time
|
290
|
-
# attribute :age, Integer
|
291
|
-
# attribute :spending, Decimal
|
292
|
-
# attribute :score, Float
|
293
|
-
# end
|
294
|
-
#
|
295
|
-
# user = User.new(:birthday => "2000-01-01")
|
296
|
-
# user.birthday.month == 1
|
297
|
-
# # => true
|
298
|
-
#
|
299
|
-
# user.birthday.year == 2000
|
300
|
-
# # => true
|
301
|
-
#
|
302
|
-
# user.birthday.day == 1
|
303
|
-
# # => true
|
304
|
-
#
|
305
|
-
# user = User.new(:age => 20)
|
306
|
-
# user.age - 1 == 19
|
307
|
-
# => true
|
308
|
-
#
|
309
|
-
# @param [Symbol] name the name of the attribute to define.
|
310
|
-
# @param [Class] type (defaults to Ohm::Types::String) a class defined in
|
311
|
-
# Ohm::Types. You may define custom types in Ohm::Types if
|
312
|
-
# you need to.
|
313
|
-
# @return [Array] the array of attributes already defined.
|
314
|
-
# @return [nil] if the attribute is already defined.
|
315
|
-
def attribute(name, type = Ohm::Types::String, klass = Ohm::Types[type])
|
316
|
-
# Primitive types maintain a reference to the original object
|
317
|
-
# stored in @_attributes[att]. Hence mutation works for the
|
318
|
-
# Primitive case. For cases like Hash, Array where the value
|
319
|
-
# is `JSON.parse`d, we need to set the actual Ohm::Types::Hash
|
320
|
-
# (or similar) to @_attributes[att] for mutation to work.
|
321
|
-
if klass.superclass == Ohm::Types::Primitive
|
322
|
-
define_method(name) { klass[read_local(name)] }
|
323
|
-
else
|
324
|
-
define_method(name) { write_local(name, klass[read_local(name)]) }
|
325
|
-
end
|
326
|
-
|
327
|
-
define_method(:"#{name}=") do |value|
|
328
|
-
write_local(name, klass[value].to_s)
|
329
|
-
end
|
330
|
-
|
331
|
-
attributes << name unless attributes.include?(name)
|
332
|
-
types[name] = type
|
333
|
-
end
|
334
|
-
alias :typecast :attribute
|
335
|
-
|
336
|
-
def types
|
337
|
-
@types ||= {}
|
338
|
-
end
|
339
|
-
|
340
|
-
private
|
341
|
-
def const_missing(name)
|
342
|
-
if Ohm::Types.defined?(name)
|
343
|
-
Ohm::Types[name]
|
344
|
-
else
|
345
|
-
super
|
346
|
-
end
|
347
|
-
end
|
348
|
-
end
|
349
|
-
end
|
350
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
module Ohm
|
2
|
-
# All credit goes to gnrfan of github
|
3
|
-
# Basically an extraction from http://github.com/gnrfan/ohm_extra_validations
|
4
|
-
#
|
5
|
-
# * 2010-05-29 Updated Email Regex, Extracted out regexs to constants
|
6
|
-
#
|
7
|
-
# This module provides the following:
|
8
|
-
# * assert_slug
|
9
|
-
# * assert_email
|
10
|
-
# * assert_url
|
11
|
-
# * assert_ipv4
|
12
|
-
module WebValidations
|
13
|
-
# @see http://fightingforalostcause.net/misc/2006/compare-email-regex.php
|
14
|
-
EMAIL_REGEX = /^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i
|
15
|
-
|
16
|
-
SLUG_REGEX = /^[-\w]+$/
|
17
|
-
|
18
|
-
URL_REGEX = /^(http|https):\/\/([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}|(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}|localhost)(:[0-9]{1,5})?(\/.*)?$/ix
|
19
|
-
|
20
|
-
IPV4_REGEX = /^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$/
|
21
|
-
|
22
|
-
protected
|
23
|
-
def assert_slug(att, error = [att, :not_slug])
|
24
|
-
if assert_present(att, error) and assert_unique(att)
|
25
|
-
assert_format(att, SLUG_REGEX, error)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def assert_email(att, error = [att, :not_email])
|
30
|
-
if assert_present(att, error)
|
31
|
-
assert_format(att, EMAIL_REGEX, error)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def assert_url(att, error = [att, :not_url])
|
36
|
-
if assert_present(att, error)
|
37
|
-
assert_format(att, URL_REGEX, error)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def assert_ipv4(att, error = [att, :not_ipv4])
|
42
|
-
if assert_present(att, error)
|
43
|
-
assert_format(att, IPV4_REGEX, error)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def assert_ipaddr(att, error = [att, :not_ipaddr])
|
48
|
-
assert_ipv4(att, error)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
data/test/activemodel_test.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require File.expand_path("./helper", File.dirname(__FILE__))
|
4
|
-
|
5
|
-
require "test/unit"
|
6
|
-
require "active_model"
|
7
|
-
|
8
|
-
class ActiveModelTest < Test::Unit::TestCase
|
9
|
-
include ActiveModel::Lint::Tests
|
10
|
-
|
11
|
-
class Post < Ohm::Model
|
12
|
-
include Ohm::ActiveModelExtension
|
13
|
-
|
14
|
-
attribute :body
|
15
|
-
list :related, Post
|
16
|
-
|
17
|
-
def validate
|
18
|
-
assert_present :body
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def setup
|
23
|
-
@model = Post.new
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
|
data/test/boundaries_test.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require File.expand_path("./helper", File.dirname(__FILE__))
|
4
|
-
|
5
|
-
class Person < Ohm::Model
|
6
|
-
include Ohm::Boundaries
|
7
|
-
|
8
|
-
attribute :name
|
9
|
-
index :name
|
10
|
-
end
|
11
|
-
|
12
|
-
test "first / last are nil when no records" do
|
13
|
-
assert nil == Person.first
|
14
|
-
assert nil == Person.last
|
15
|
-
end
|
16
|
-
|
17
|
-
test "first / last returns the only record when just 1 record" do
|
18
|
-
matz = Person.create(:name => "matz")
|
19
|
-
|
20
|
-
assert matz == Person.first
|
21
|
-
assert matz == Person.last
|
22
|
-
end
|
23
|
-
|
24
|
-
test "has chronological order by default" do
|
25
|
-
matz = Person.create(:name => "matz")
|
26
|
-
linus = Person.create(:name => "linus")
|
27
|
-
|
28
|
-
assert matz == Person.first
|
29
|
-
assert linus == Person.last
|
30
|
-
end
|
31
|
-
|
32
|
-
test "respects filters passed in" do
|
33
|
-
matz = Person.create(:name => "matz")
|
34
|
-
linus = Person.create(:name => "linus")
|
35
|
-
|
36
|
-
assert matz == Person.first(:name => "matz")
|
37
|
-
assert matz == Person.last(:name => "matz")
|
38
|
-
|
39
|
-
assert linus == Person.first(:name => "linus")
|
40
|
-
assert linus == Person.last(:name => "linus")
|
41
|
-
|
42
|
-
assert nil == Person.first(:name => "quentin")
|
43
|
-
assert nil == Person.last(:name => "quentin")
|
44
|
-
end
|
45
|
-
|