arrest 0.0.9 → 0.0.11

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/.gitignore CHANGED
@@ -4,3 +4,4 @@ Gemfile.lock
4
4
  pkg/*
5
5
  *.swp
6
6
  coverage
7
+ log/*
data/lib/arrest.rb CHANGED
@@ -1,18 +1,25 @@
1
+ require 'logger'
2
+
1
3
  require "arrest/version"
4
+ require 'arrest/helper/logger'
2
5
 
3
6
  require "arrest/attributes/belongs_to"
4
7
  require "arrest/attributes/has_attributes"
5
8
  require "arrest/attributes/converter"
6
9
  require "arrest/source"
10
+ require "arrest/helper/filter"
7
11
  require "arrest/helper/child_collection"
12
+ require "arrest/helper/has_many_collection"
8
13
  require "arrest/exceptions"
9
14
  require "arrest/http_source"
10
15
  require "arrest/mem_source"
11
16
  require "arrest/source"
12
17
  require "arrest/nested_resource"
18
+ require "arrest/validations/validator"
19
+ require "arrest/validations/presence_of"
20
+ require "arrest/validations/inclusion_of"
21
+ require "arrest/validations/validatable"
13
22
  require "arrest/abstract_resource"
14
23
  require "arrest/root_resource"
15
24
  require "arrest/rest_child"
16
25
 
17
- module Arrest
18
- end
@@ -9,7 +9,11 @@ module Arrest
9
9
  class AbstractResource
10
10
  extend ActiveModel::Naming
11
11
  include HasAttributes
12
+ include Validatable
12
13
  attribute :id, String
14
+
15
+ attr_accessor :errors
16
+
13
17
  class << self
14
18
  attr_reader :scopes
15
19
 
@@ -46,6 +50,31 @@ module Arrest
46
50
  end
47
51
 
48
52
  def has_many(*args)
53
+ method_name, options = args
54
+ singular = (StringUtils.singular(method_name.to_s) + '_ids').to_sym
55
+ method_name = method_name.to_sym
56
+
57
+ clazz_name = method_name.to_s
58
+ if options
59
+ clazz = options[:class_name]
60
+ if clazz
61
+ clazz_name = clazz.to_s
62
+ end
63
+ end
64
+ attribute singular, Array
65
+ send :define_method, method_name do
66
+ if @has_many_collections == nil
67
+ @has_many_collections = {}
68
+ end
69
+ if @has_many_collections[method_name] == nil
70
+ @has_many_collections[method_name] = HasManyCollection.new(self, (StringUtils.classify (StringUtils.singular clazz_name)))
71
+ end
72
+
73
+ @has_many_collections[method_name]
74
+ end
75
+ end
76
+
77
+ def children(*args)
49
78
  method_name, options = args
50
79
  method_name = method_name.to_sym
51
80
 
@@ -100,8 +129,13 @@ module Arrest
100
129
  end
101
130
 
102
131
  def save
103
- verb = new_record? ? :post : :put
104
- !!AbstractResource::source.send(verb, self)
132
+ self.errors = self.validate
133
+ if self.errors.empty?
134
+ verb = new_record? ? :post : :put
135
+ !!AbstractResource::source.send(verb, self)
136
+ else
137
+ false
138
+ end
105
139
  end
106
140
 
107
141
  def new_record?
@@ -18,10 +18,12 @@ module Arrest
18
18
  class_name = params[:class_name].to_s unless params[:class_name] == nil
19
19
  read_only = params[:read_only] == true
20
20
  end
21
- attributes({field_name.to_sym => String})
22
21
  add_attribute(Attribute.new(field_name.to_sym, read_only, String))
23
22
  send :define_method, name do
24
23
  val = self.send(field_name)
24
+ if val == nil || val == ""
25
+ return nil
26
+ end
25
27
  begin
26
28
  Arrest::Source.mod.const_get(class_name).find(val)
27
29
  rescue Errors::DocumentNotFoundError => e
@@ -109,6 +109,10 @@ module Arrest
109
109
  target Integer
110
110
  end
111
111
 
112
+ class ArrayConv < IdentConv
113
+ target Array
114
+ end
115
+
112
116
  class TimeConv < Converter
113
117
  target Time
114
118
 
@@ -0,0 +1,13 @@
1
+ module Arrest
2
+ # A filter is a named predicate to limit a collection to a subset with
3
+ # certain features
4
+ class Filter
5
+ attr_accessor :name
6
+ attr_accessor :block
7
+
8
+ def initialize name, block = nil
9
+ @name = name
10
+ @block = block
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,56 @@
1
+ module Arrest
2
+ class HasManyCollection #< BasicObject
3
+ def initialize parent, clazz_name
4
+ @parent = parent
5
+ @clazz_name = clazz_name
6
+ @children = nil
7
+ @foreign_key_name = (StringUtils.underscore(@parent.class.name).gsub(/^.*\//, '') + '_id').to_sym
8
+ define_filters
9
+ end
10
+
11
+ def build attributes = {}
12
+ extended_attrs = attributes.merge({@foreign_key_name => @parent.id})
13
+ resolved_class.new extended_attrs
14
+ end
15
+
16
+ def method_missing(*args, &block)
17
+ children.send(*args, &block)
18
+ end
19
+
20
+ def inspect
21
+ children.inspect
22
+ end
23
+
24
+ private
25
+
26
+
27
+ def children
28
+ if @children == nil
29
+ url = @parent.resource_location + '/' + resolved_class.resource_name.to_s
30
+ @children = resolved_class.by_url(url)
31
+ end
32
+ @children
33
+ end
34
+
35
+ def resolved_class
36
+ if @clazz == nil
37
+ @clazz = Source.mod.const_get(@clazz_name)
38
+ end
39
+ @clazz
40
+ end
41
+
42
+
43
+ def define_filters
44
+ resolved_class.all_filters.each do |filter|
45
+ self.instance_eval <<-"end_eval"
46
+ def #{filter.name} *args
47
+ real_args = [children] + args
48
+ #{resolved_class.name}.FILTER_#{filter.name}(real_args)
49
+ end
50
+ end_eval
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+
@@ -0,0 +1,8 @@
1
+ module Arrest
2
+ @@logger = Logger.new('log/arrest.log')
3
+
4
+ def self.logger
5
+ @@logger
6
+ end
7
+ end
8
+
@@ -29,7 +29,11 @@ module Arrest
29
29
  end
30
30
 
31
31
  def get_many sub, filter={}
32
- get_one sub, filter
32
+ response = self.connection().get do |req|
33
+ req.url sub, filter
34
+ add_headers req.headers
35
+ end
36
+ response.body
33
37
  end
34
38
 
35
39
  def delete rest_resource
@@ -43,7 +47,7 @@ module Arrest
43
47
 
44
48
  def put rest_resource
45
49
  raise "To change an object it must have an id" unless rest_resource.respond_to?(:id) && rest_resource.id != nil
46
- hash = rest_resource.to_hash
50
+ hash = rest_resource.to_jhash
47
51
  hash.delete(:id)
48
52
  hash.delete("id")
49
53
 
@@ -88,6 +92,7 @@ module Arrest
88
92
  builder.request :json
89
93
  builder.response :logger
90
94
  builder.adapter :net_http
95
+ builder.use Faraday::Response::Logger, Arrest::logger
91
96
  end
92
97
  end
93
98
 
@@ -145,6 +145,10 @@ module Arrest
145
145
  true
146
146
  end
147
147
 
148
+ def cheat_collection url, ids
149
+ @@collections[url] = ids
150
+ end
151
+
148
152
  def next_id
149
153
  (0...32).map{ ('a'..'z').to_a[@@random.rand(26)] }.join
150
154
  end
@@ -23,8 +23,12 @@ module Arrest
23
23
 
24
24
  def all_for parent
25
25
  raise "Parent has no id yet" unless parent.id
26
- body_root(source().get_many self.resource_path_for(parent)).map do |h|
27
- self.build(parent, h)
26
+ begin
27
+ body_root(source().get_many self.resource_path_for(parent)).map do |h|
28
+ self.build(parent, h)
29
+ end
30
+ rescue Arrest::Errors::DocumentNotFoundError
31
+ []
28
32
  end
29
33
  end
30
34
 
@@ -7,8 +7,26 @@ module Arrest
7
7
  "#{self.resource_name}"
8
8
  end
9
9
 
10
+ def by_url url
11
+ begin
12
+ body = body_root(source().get_many url)
13
+ rescue Arrest::Errors::DocumentNotFoundError
14
+ Arrest::logger.info "DocumentNotFoundError for #{url} gracefully returning []"
15
+ return []
16
+ end
17
+ body ||= []
18
+ body.map do |h|
19
+ self.build h
20
+ end
21
+ end
22
+
10
23
  def all filter={}
11
- body = body_root(source().get_many self.resource_path, filter)
24
+ begin
25
+ body = body_root(source().get_many self.resource_path, filter)
26
+ rescue Arrest::Errors::DocumentNotFoundError
27
+ Arrest::logger.info "DocumentNotFoundError for #{self.resource_path} gracefully returning []"
28
+ return []
29
+ end
12
30
  body ||= []
13
31
  body.map do |h|
14
32
  self.build h
@@ -19,6 +37,7 @@ module Arrest
19
37
  r = source().get_one "#{self.resource_path}/#{id}"
20
38
  body = body_root(r)
21
39
  if body == nil || body.empty?
40
+ Arrest::logger.info "DocumentNotFoundError for #{self.resource_path}/#{id}"
22
41
  raise Errors::DocumentNotFoundError.new
23
42
  end
24
43
  self.build body.merge({:id => id})
@@ -26,7 +45,18 @@ module Arrest
26
45
 
27
46
  def filter name, &aproc
28
47
  if aproc != nil
29
- send :define_singleton_method, name do |args|
48
+ if @filters == nil
49
+ @filters = []
50
+ end
51
+ @filters << Filter.new(name, &aproc)
52
+ send :define_singleton_method, "FILTER_#{name}" do |args = nil|
53
+ collection = args[0]
54
+ call_args = args.drop(1)
55
+ collection.select do |instance|
56
+ instance.instance_exec(call_args, &aproc)
57
+ end
58
+ end
59
+ send :define_singleton_method, name do |args = nil|
30
60
  self.all.select do |instance|
31
61
  instance.instance_exec(args, &aproc)
32
62
  end
@@ -36,6 +66,19 @@ module Arrest
36
66
  end
37
67
  end
38
68
 
69
+ def filters
70
+ @filters
71
+ end
72
+
73
+ def all_filters
74
+ all_filters = @filters
75
+ all_filters ||= []
76
+ if superclass.respond_to?('filters') && superclass.filters
77
+ all_fields += superclass.filters
78
+ end
79
+ all_filters
80
+ end
81
+
39
82
  def scope name, &block
40
83
  super(name)
41
84
  if block_given?
data/lib/arrest/source.rb CHANGED
@@ -16,8 +16,10 @@ module Arrest
16
16
  def source=(host=nil)
17
17
  if host == nil || host.blank?
18
18
  @source = MemSource.new
19
+ Arrest::logger.info "Setting Arrest host empty in-memory-store"
19
20
  else
20
21
  @source = HttpSource.new host
22
+ Arrest::logger.info "Setting Arrest host to #{host}"
21
23
  end
22
24
  @source
23
25
  end
@@ -0,0 +1,25 @@
1
+ module Arrest
2
+ module Validations
3
+ class InclusionOf < Validator
4
+
5
+ def initialize attribute, hash
6
+ super attribute
7
+ @hash = hash
8
+ end
9
+
10
+ def validate input
11
+ errors = []
12
+ if !input.respond_to?(@attribute)
13
+ errors << ValidationError.new(@attribute, "not_responding")
14
+ else
15
+ val = input.send(@attribute)
16
+ unless @hash[:in] != nil && @hash[:in].include?(val)
17
+ errors << ValidationError.new(@attribute,"not_included")
18
+ end
19
+ end
20
+ return errors
21
+ end
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,18 @@
1
+ module Arrest
2
+ module Validations
3
+ class PresenceOf < Validator
4
+ def validate input
5
+ errors = []
6
+ if !input.respond_to?(@attribute)
7
+ errors << ValidationError.new(@attribute, "not_responding")
8
+ else
9
+ val = input.send(@attribute)
10
+ if val == nil || val == ''
11
+ errors << ValidationError.new(@attribute,"not_present")
12
+ end
13
+ end
14
+ return errors
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,69 @@
1
+ module Arrest
2
+ module Validations
3
+ class MethodValidator
4
+ def initialize method = nil, &blk
5
+ @method = method
6
+ end
7
+
8
+ def validate input
9
+ input.send(@method)
10
+ end
11
+ end
12
+ end
13
+
14
+ module Validatable
15
+ def self.included(base) # :nodoc:
16
+ base.extend ValidatableMethods
17
+ end
18
+
19
+ module ValidatableMethods
20
+ def validates_presence_of attribute
21
+ add_validator Validations::PresenceOf.new attribute
22
+ end
23
+
24
+ def validates method_name
25
+ add_validator Validations::MethodValidator.new method_name
26
+ end
27
+
28
+ def validates_inclusion_of attribute, hash = {}
29
+ add_validator Validations::InclusionOf.new attribute, hash
30
+ end
31
+
32
+ def add_validator v
33
+ if @validations == nil
34
+ @validations = []
35
+ end
36
+ @validations << v
37
+ end
38
+
39
+ def validations
40
+ if self.superclass.respond_to? :validations
41
+ super_v = self.superclass.validations
42
+ else
43
+ super_v = []
44
+ end
45
+ if @validations == nil
46
+ @validations = []
47
+ end
48
+
49
+ @validations + super_v
50
+ end
51
+ end
52
+
53
+ # --------- instance methods ---------
54
+ def valid?
55
+ validate.empty?
56
+ end
57
+
58
+
59
+ def validate
60
+ vs = self.class.validations
61
+ return [] if vs == nil
62
+ errors = []
63
+ vs.each do |v|
64
+ errors += v.validate self
65
+ end
66
+ errors
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,27 @@
1
+ module Arrest
2
+ module Validations
3
+ class ValidationError
4
+ attr_accessor :attribute, :message
5
+
6
+ def initialize attribute, message
7
+ @attribute = attribute
8
+ @message = message
9
+ end
10
+
11
+ def translate
12
+ "#{self.attribute} - #{self.message}"
13
+ end
14
+ end
15
+
16
+ class Validator
17
+ def initialize attribute
18
+ @attribute = attribute
19
+ end
20
+
21
+ def validate input
22
+ return []
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module Arrest
2
- VERSION = "0.0.9"
2
+ VERSION = "0.0.11"
3
3
  end
data/test/models.rb CHANGED
@@ -3,10 +3,15 @@ require 'arrest'
3
3
  class Zoo < Arrest::RootResource
4
4
  attributes({ :name => String , :open => Boolean})
5
5
  read_only_attributes({ :ro1 => String})
6
- has_many :animals
6
+ children :animals
7
7
 
8
8
  scope :server_scope
9
9
  scope(:open) { |z| z.open }
10
+ filter(:open_filter) { open }
11
+
12
+ validates_presence_of :name
13
+
14
+ belongs_to :zoo_owner
10
15
  end
11
16
 
12
17
  class Animal < Arrest::RestChild
@@ -20,6 +25,12 @@ class Animal < Arrest::RestChild
20
25
  scope(:males_only){|a| a.male}
21
26
  end
22
27
 
28
+ class ZooOwner < Arrest::RootResource
29
+ attribute :name, String
30
+ has_many :zoos
31
+ end
32
+
33
+
23
34
  class SpecialZoo < Zoo
24
35
  custom_resource_name :zoo3000
25
36
  read_only_attributes({ :ro2 => String})
@@ -73,7 +84,9 @@ class ParentFilter < Arrest::RootResource
73
84
  attribute :afield, String
74
85
 
75
86
  filter(:nnn) {|s| afield == s}
76
- has_many :child_filters
87
+ filter(:no_param){ afield == "Foo"}
88
+ filter(:running){ afield == "Foo"}
89
+ children :child_filters
77
90
  end
78
91
 
79
92
  class ChildFilter < Arrest::RestChild
data/test/unit.rb CHANGED
@@ -42,6 +42,35 @@ class FirstTest < Test::Unit::TestCase
42
42
  assert_equal new_zoo.id, zoo_reloaded.id
43
43
  end
44
44
 
45
+ def test_prsnc_valid
46
+ invalid_params = [
47
+ {},
48
+ {:name => nil},
49
+ {:name => ''}
50
+ ]
51
+
52
+ invalid_params.each do |p|
53
+ zoo_count_before = Zoo.all.length
54
+ new_zoo = Zoo.new(p)
55
+ assert_equal false, new_zoo.save, "zoo without name shouldnt be persistable"
56
+ assert_equal zoo_count_before, Zoo.all.length
57
+ assert_equal :name, new_zoo.errors.first.attribute
58
+ assert_nil new_zoo.id
59
+
60
+ new_zoo.name = "Foo"
61
+
62
+ assert new_zoo.save, "Creating should be possible after setting a name"
63
+ zoo_count_after = Zoo.all.length
64
+ assert_not_nil new_zoo.id
65
+
66
+ assert_equal (zoo_count_before + 1), zoo_count_after
67
+ assert new_zoo.id != nil
68
+
69
+ new_zoo.name = ""
70
+ assert_equal false, new_zoo.save, "Shouldnt be able to update without a name"
71
+ end
72
+ end
73
+
45
74
  def test_delete
46
75
  zoo_count_before = Zoo.all.length
47
76
  new_zoo = Zoo.new({:name => "Foo"})
@@ -261,11 +290,16 @@ class FirstTest < Test::Unit::TestCase
261
290
  new_zoo = Zoo.new({:name => "Foo"})
262
291
  new_zoo.save
263
292
 
293
+ new_zoo2 = Zoo.new({:name => "Boo"})
294
+ new_zoo2.save
295
+
264
296
  animal_kind = "mouse"
265
297
  Animal.new(new_zoo, {:kind => animal_kind, :age => 42, :male => true}).save
266
298
  Animal.new(new_zoo, {:kind => animal_kind, :age => 42, :male => false}).save
299
+ Animal.new(new_zoo2, {:kind => animal_kind, :age => 42, :male => false}).save
267
300
 
268
301
  assert_equal 2, Zoo.all.first.animals.length
302
+ assert_equal 1, Zoo.all.last.animals.length
269
303
  assert_equal 1, Zoo.all.first.animals.males_only.length
270
304
  assert_equal true, Zoo.all.first.animals.males_only.first.male
271
305
 
@@ -297,5 +331,65 @@ class FirstTest < Test::Unit::TestCase
297
331
 
298
332
  assert_equal ["Foo"], reloaded_parent.child_filters.child_nnn("Foo").map(&:bfield)
299
333
  end
334
+
335
+ def test_no_param_filter
336
+ p1 = ParentFilter.new({:afield => "Foo"})
337
+ p2 = ParentFilter.new({:afield => "Bar"})
338
+ p1.save
339
+ p2.save
340
+
341
+ no_param = ParentFilter.no_param
342
+ assert_equal ["Foo"], no_param.map(&:afield)
343
+ end
344
+
345
+ def test_has_many
346
+ Zoo.new(:name => "Foo1").save
347
+ Zoo.new(:name => "Foo2").save
348
+ assert_equal 2, Zoo.all.length
349
+ all_zoo_ids = Zoo.all.map(&:id)
350
+ v1 = ZooOwner.new({:name => "Foo", :zoo_ids => all_zoo_ids})
351
+ v1.save
352
+
353
+ v1_reloaded = ZooOwner.all.first
354
+ assert_equal all_zoo_ids, v1_reloaded.zoo_ids
355
+
356
+ url = v1.resource_location + '/' + Zoo.resource_name
357
+ Arrest::Source.source.cheat_collection(url, v1_reloaded.zoo_ids)
358
+ assert_equal 2,v1_reloaded.zoos.length
359
+ assert_equal "Foo1", v1_reloaded.zoos.first.name
360
+ end
361
+
362
+ def test_build
363
+ v1 = ZooOwner.new({:name => "Foo"})
364
+ v1.save
365
+
366
+ zoo = v1.zoos.build
367
+ assert_equal v1.id, zoo.zoo_owner_id
368
+ end
369
+
370
+ def test_scope_has_many
371
+ z1 = Zoo.new(:name => "Foo1", :open => true)
372
+ z1.save
373
+ z2 = Zoo.new(:name => "Foo2", :open => false)
374
+ z2.save
375
+ z3 = Zoo.new(:name => "Foo3", :open => true)
376
+ z3.save
377
+ assert_equal 3, Zoo.all.length
378
+ all_zoo_ids = [z1.id, z2.id]
379
+ v1 = ZooOwner.new({:name => "Foo", :zoo_ids => all_zoo_ids})
380
+ v1.save
381
+
382
+ v1_reloaded = ZooOwner.all.first
383
+ assert_equal all_zoo_ids, v1_reloaded.zoo_ids
384
+
385
+ url = v1.resource_location + '/' + Zoo.resource_name
386
+ Arrest::Source.source.cheat_collection(url, v1_reloaded.zoo_ids)
387
+ assert_equal 2,v1_reloaded.zoos.length
388
+ assert_equal "Foo1", v1_reloaded.zoos.first.name
389
+
390
+ assert_equal 1, v1_reloaded.zoos.open_filter.length
391
+ assert_equal "Foo1", v1_reloaded.zoos.open_filter.first.name
392
+ assert_equal 3, Zoo.all.length
393
+ end
300
394
  end
301
395
 
@@ -0,0 +1,154 @@
1
+ require 'test/unit'
2
+ require 'arrest'
3
+
4
+ class PresenceOfClass
5
+ include Arrest::Validatable
6
+ attr_accessor :foo
7
+
8
+ validates_presence_of :foo
9
+
10
+ def initialize foo
11
+ @foo = foo
12
+ end
13
+ end
14
+
15
+ class PresenceOfTwo
16
+ include Arrest::Validatable
17
+ attr_accessor :foo, :bar
18
+
19
+ validates_presence_of :foo
20
+ validates_presence_of :bar
21
+
22
+ def initialize foo = nil, bar = nil
23
+ @foo = foo
24
+ @bar = bar
25
+ end
26
+ end
27
+
28
+ class InheritedPresence < PresenceOfClass
29
+ attr_accessor :baz
30
+
31
+ validates_presence_of :baz
32
+
33
+ def initialize foo = nil, baz = nil
34
+ super foo
35
+ @baz = baz
36
+ end
37
+ end
38
+
39
+ class CustomVal
40
+ include Arrest::Validatable
41
+ attr_accessor :foo
42
+
43
+ validates :is_foo
44
+
45
+ def initialize foo=nil
46
+ @foo = foo
47
+ end
48
+
49
+ def is_foo
50
+ if self.foo != "Foo"
51
+ [Arrest::Validations::ValidationError.new(:foo, "is no foo")]
52
+ else
53
+ []
54
+ end
55
+ end
56
+ end
57
+
58
+ class ValidationsTest < Test::Unit::TestCase
59
+
60
+
61
+ def setup
62
+ Arrest::Source.source = nil
63
+ #Arrest::Source.debug = true
64
+ end
65
+
66
+ def test_prsnc
67
+ o0 = PresenceOfClass.new nil
68
+ assert o0.valid? == false, "Foo is '#{o0.foo}' -> not present and thus not valid!"
69
+
70
+ o1 = PresenceOfClass.new "Foo"
71
+ assert o1.valid?, "Foo is present and valid!"
72
+ end
73
+
74
+ def test_presence_of_two
75
+ o = PresenceOfTwo.new
76
+ assert o.valid? == false, "Both missing, must not be valid"
77
+
78
+ o = PresenceOfTwo.new "foo"
79
+ assert o.valid? == false, "bar missing, must not be valid"
80
+
81
+ o = PresenceOfTwo.new nil, "bar"
82
+ assert o.valid? == false, "foo missing, must not be valid"
83
+
84
+ o = PresenceOfTwo.new '', "bar"
85
+ assert o.valid? == false, "foo missing, must not be valid"
86
+
87
+ o = PresenceOfTwo.new "foo", "bar"
88
+ assert o.valid?, "complete -> should be valid"
89
+ end
90
+
91
+ def test_inheritance
92
+ o = InheritedPresence.new
93
+ assert o.valid? == false, "Both missing, shouldnt be valid"
94
+
95
+ o = InheritedPresence.new "Foo"
96
+ assert o.valid? == false, "Baz missing, shouldnt be valid"
97
+
98
+ o = InheritedPresence.new "Foo", ''
99
+ assert o.valid? == false, "Baz missing, shouldnt be valid"
100
+
101
+ o = InheritedPresence.new "", "Baz"
102
+ assert o.valid? == false, "Foo missing, shouldnt be valid"
103
+
104
+ o = InheritedPresence.new nil, "Baz"
105
+ assert o.valid? == false, "Foo missing, shouldnt be valid"
106
+
107
+ o = InheritedPresence.new "Foo", "Baz"
108
+ assert o.valid? , "Nothing missing, should be valid"
109
+ end
110
+
111
+ def test_method_valid
112
+ o = CustomVal.new
113
+ assert o.valid? == false, "no foo is not valid"
114
+
115
+ o = CustomVal.new("Bar")
116
+ assert o.valid? == false, "Bar is not Foo thus is not valid"
117
+
118
+ o = CustomVal.new("Foo")
119
+ assert_equal "Foo", o.foo
120
+ assert o.valid?, "Foo should be valid"
121
+ end
122
+
123
+ # ================ inclusion_of ======
124
+
125
+ class InclusionOfClass
126
+ include Arrest::Validatable
127
+
128
+ attr_accessor :foo
129
+
130
+ validates_inclusion_of :foo, :in => ["Foo", "Bar"]
131
+
132
+ def initialize foo
133
+ @foo = foo
134
+ end
135
+ end
136
+
137
+ def test_inclusion_of
138
+ invalids = [nil, '', "Baz", "foo", 3, true]
139
+
140
+ valids = ["Foo", "Bar"]
141
+
142
+ invalids.each do |iv|
143
+ o = InclusionOfClass.new(iv)
144
+ assert o.valid? == false, "#{iv} is not valid"
145
+ assert o.validate.map(&:attribute).include?(:foo), ":foo should be in list of invalid attributes when created with #{iv}"
146
+ end
147
+
148
+ valids.each do |v|
149
+ o = InclusionOfClass.new(v)
150
+ assert o.valid?
151
+ end
152
+ end
153
+ end
154
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arrest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.11
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-16 00:00:00.000000000Z
12
+ date: 2012-01-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &12008120 !ruby/object:Gem::Requirement
16
+ requirement: &24668020 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *12008120
24
+ version_requirements: *24668020
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: faraday
27
- requirement: &12006980 !ruby/object:Gem::Requirement
27
+ requirement: &24666840 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - =
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.7.5
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *12006980
35
+ version_requirements: *24666840
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: activemodel
38
- requirement: &12006180 !ruby/object:Gem::Requirement
38
+ requirement: &24666120 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '3'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *12006180
46
+ version_requirements: *24666120
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bundler
49
- requirement: &12005700 !ruby/object:Gem::Requirement
49
+ requirement: &24640360 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.0.0
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *12005700
57
+ version_requirements: *24640360
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rake
60
- requirement: &12005200 !ruby/object:Gem::Requirement
60
+ requirement: &24639500 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *12005200
68
+ version_requirements: *24639500
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rdoc
71
- requirement: &12004460 !ruby/object:Gem::Requirement
71
+ requirement: &24639020 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *12004460
79
+ version_requirements: *24639020
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rspec
82
- requirement: &12003960 !ruby/object:Gem::Requirement
82
+ requirement: &24638440 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '2'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *12003960
90
+ version_requirements: *24638440
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: rr
93
- requirement: &12003540 !ruby/object:Gem::Requirement
93
+ requirement: &24637760 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *12003540
101
+ version_requirements: *24637760
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: simplecov
104
- requirement: &12003020 !ruby/object:Gem::Requirement
104
+ requirement: &24637300 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *12003020
112
+ version_requirements: *24637300
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: rack
115
- requirement: &12002560 !ruby/object:Gem::Requirement
115
+ requirement: &24636880 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,7 +120,7 @@ dependencies:
120
120
  version: '0'
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *12002560
123
+ version_requirements: *24636880
124
124
  description: Consume a rest API in a AR like fashion
125
125
  email:
126
126
  - axel.tetzlaff@fortytools.com
@@ -141,6 +141,9 @@ files:
141
141
  - lib/arrest/attributes/has_attributes.rb
142
142
  - lib/arrest/exceptions.rb
143
143
  - lib/arrest/helper/child_collection.rb
144
+ - lib/arrest/helper/filter.rb
145
+ - lib/arrest/helper/has_many_collection.rb
146
+ - lib/arrest/helper/logger.rb
144
147
  - lib/arrest/http_source.rb
145
148
  - lib/arrest/mem_source.rb
146
149
  - lib/arrest/nested_resource.rb
@@ -148,6 +151,10 @@ files:
148
151
  - lib/arrest/root_resource.rb
149
152
  - lib/arrest/source.rb
150
153
  - lib/arrest/string_utils.rb
154
+ - lib/arrest/validations/inclusion_of.rb
155
+ - lib/arrest/validations/presence_of.rb
156
+ - lib/arrest/validations/validatable.rb
157
+ - lib/arrest/validations/validator.rb
151
158
  - lib/arrest/version.rb
152
159
  - spec/arrest_spec.rb
153
160
  - spec/spec_helper.rb
@@ -156,6 +163,7 @@ files:
156
163
  - test/models.rb
157
164
  - test/nested_resource.rb
158
165
  - test/unit.rb
166
+ - test/validations.rb
159
167
  homepage: ''
160
168
  licenses: []
161
169
  post_install_message: