arrest 0.0.9 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
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: