arrest 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,4 +21,5 @@ Gem::Specification.new do |s|
21
21
  # specify any dependencies here; for example:
22
22
  # s.add_development_dependency "rspec"
23
23
  s.add_runtime_dependency "json"
24
+ s.add_runtime_dependency "faraday", '0.7.5'
24
25
  end
@@ -9,51 +9,4 @@ require "arrest/rest_child"
9
9
 
10
10
  module Arrest
11
11
 
12
- String.class_eval do
13
-
14
- PLURALS = [['(quiz)$', '\1zes'],['(ox)$', '\1en'],['([m|l])ouse$', '\1ice'],['(matr|vert|ind)ix|ex$', '\1ices'],
15
- ['(x|ch|ss|sh)$', '\1es'],['([^aeiouy]|qu)ies$', '\1y'],['([^aeiouy]|q)y$$', '\1ies'],['(hive)$', '\1s'],
16
- ['(?:[^f]fe|([lr])f)$', '\1\2ves'],['(sis)$', 'ses'],['([ti])um$', '\1a'],['(buffal|tomat)o$', '\1oes'],['(bu)s$', '\1es'],
17
- ['(alias|status)$', '\1es'],['(octop|vir)us$', '\1i'],['(ax|test)is$', '\1es'],['s$', 's'],['$', 's']]
18
- SINGULARS =[['(quiz)zes$', '\1'],['(matr)ices$', '\1ix'],['(vert|ind)ices$', '\1ex'],['^(ox)en$', '\1'],['(alias|status)es$', '\1'],
19
- ['(octop|vir)i$', '\1us'],['(cris|ax|test)es$', '\1is'],['(shoe)s$', '\1'],['[o]es$', '\1'],['[bus]es$', '\1'],['([m|l])ice$', '\1ouse'],
20
- ['(x|ch|ss|sh)es$', '\1'],['(m)ovies$', '\1ovie'],['[s]eries$', '\1eries'],['([^aeiouy]|qu)ies$', '\1y'],['[lr]ves$', '\1f'],
21
- ['(tive)s$', '\1'],['(hive)s$', '\1'],['([^f])ves$', '\1fe'],['(^analy)ses$', '\1sis'],
22
- ['([a]naly|[b]a|[d]iagno|[p]arenthe|[p]rogno|[s]ynop|[t]he)ses$', '\1\2sis'],['([ti])a$', '\1um'],['(news)$', '\1ews'], ['(.*)s$', '\1'], ['^(.*)$', '\1']]
23
-
24
- def singular()
25
- SINGULARS.each { |match_exp, replacement_exp| return gsub(Regexp.compile(match_exp), replacement_exp) unless match(Regexp.compile(match_exp)).nil?}
26
- end
27
-
28
- def plural()
29
- PLURALS.each { |match_exp, replacement_exp| return gsub(Regexp.compile(match_exp), replacement_exp) unless match(Regexp.compile(match_exp)).nil? }
30
- end
31
-
32
- def plural?
33
- PLURALS.each {|match_exp, replacement_exp| return true if match(Regexp.compile(match_exp))}
34
- false
35
- end
36
-
37
- def blank?
38
- self == nil || self == ""
39
- end
40
-
41
- def classify(upper_first = true)
42
- result = ""
43
- upperNext = false
44
- self.singular.each_char do |c|
45
- if c == "_"
46
- upperNext = true
47
- else
48
- if upperNext || (result.blank? && upper_first)
49
- result << c.upcase
50
- else
51
- result << c
52
- end
53
- upperNext = false
54
- end
55
- end
56
- result
57
- end
58
- end
59
12
  end
@@ -1,6 +1,10 @@
1
1
  require 'json'
2
+ require 'arrest/string_utils'
2
3
 
3
4
  module Arrest
5
+
6
+ Attribute = Struct.new(:name, :read_only)
7
+
4
8
  class AbstractResource
5
9
  class << self
6
10
 
@@ -11,16 +15,23 @@ module Arrest
11
15
  end
12
16
 
13
17
  def body_root response
18
+ if response == nil
19
+ return nil
20
+ end
14
21
  all = JSON.parse response
15
22
  all["result"]
16
23
  end
17
24
 
18
25
  def build hash
19
- self.new hash
26
+ underscored_hash = {}
27
+ hash.each_pair do |k, v|
28
+ underscored_hash[StringUtils.underscore k] = v
29
+ end
30
+ self.new underscored_hash
20
31
  end
21
32
 
22
33
  def resource_name
23
- self.name.sub(/.*:/,'').downcase.plural
34
+ StringUtils.plural self.name.sub(/.*:/,'').downcase
24
35
  end
25
36
 
26
37
  def has_many(*args)
@@ -35,7 +46,7 @@ module Arrest
35
46
  end
36
47
  end
37
48
  send :define_method, method_name do
38
- Arrest::Source.mod.const_get(clazz_name.classify).all_for self
49
+ Arrest::Source.mod.const_get(StringUtils.classify clazz_name).all_for self
39
50
  end
40
51
  end
41
52
 
@@ -46,17 +57,33 @@ module Arrest
46
57
  end
47
58
  end
48
59
 
49
- def add_attribute attribute_name
60
+ def add_attribute attribute
50
61
  if @fields == nil
51
62
  @fields = []
52
63
  end
53
- @fields << attribute_name
64
+ @fields << attribute
65
+ end
66
+
67
+ def all_fields
68
+ if self.superclass.respond_to?('fields') && self.superclass.fields != nil
69
+ self.fields + self.superclass.fields
70
+ else
71
+ self.fields
72
+ end
73
+
74
+ end
75
+
76
+ def read_only_attributes(*args)
77
+ args.each do |arg|
78
+ self.send :attr_accessor,arg
79
+ add_attribute Attribute.new(arg, true)
80
+ end
54
81
  end
55
82
 
56
83
  def attributes(*args)
57
84
  args.each do |arg|
58
85
  self.send :attr_accessor,arg
59
- add_attribute arg
86
+ add_attribute Attribute.new(arg, false)
60
87
  end
61
88
  end
62
89
 
@@ -66,7 +93,7 @@ module Arrest
66
93
  attributes "#{name}_id".to_sym
67
94
  send :define_method, name do
68
95
  val = self.instance_variable_get("@#{name}_id")
69
- Arrest::Source.mod.const_get(name.classify).find(val)
96
+ Arrest::Source.mod.const_get(StringUtils.classify name).find(val)
70
97
  end
71
98
  end
72
99
  end
@@ -78,11 +105,9 @@ module Arrest
78
105
  as_i.each_pair do |k,v|
79
106
  as[k.to_sym] = v
80
107
  end
81
- unless self.class.fields == nil
82
- self.class.fields.each do |field|
83
- json_name = field.to_s.classify(false)
84
- json_name[0] = json_name[0].downcase
85
- self.instance_variable_set("@#{field.to_s}", as[json_name.to_sym])
108
+ unless self.class.all_fields == nil
109
+ self.class.all_fields.each do |field|
110
+ self.send("#{field.name.to_s}=", as[field.name.to_sym])
86
111
  end
87
112
  end
88
113
  self.id = as[:id]
@@ -90,10 +115,10 @@ module Arrest
90
115
 
91
116
  def to_hash
92
117
  result = {}
93
- unless self.class.fields == nil
94
- self.class.fields.each do |field|
95
- json_name = field.to_s.classify(false)
96
- result[json_name] = self.instance_variable_get("@#{field.to_s}")
118
+ unless self.class.all_fields == nil
119
+ self.class.all_fields.find_all{|a| !a.read_only}.each do |field|
120
+ json_name = StringUtils.classify(field.name.to_s,false)
121
+ result[json_name] = self.instance_variable_get("@#{field.name.to_s}")
97
122
  end
98
123
  end
99
124
  result[:id] = self.id
@@ -109,5 +134,9 @@ module Arrest
109
134
  end
110
135
  end
111
136
 
137
+ def delete
138
+ AbstractResource::source().delete self
139
+ end
140
+
112
141
  end
113
142
  end
@@ -1,3 +1,5 @@
1
+ require 'faraday'
2
+
1
3
  module Arrest
2
4
  class HttpSource
3
5
 
@@ -6,9 +8,9 @@ module Arrest
6
8
  end
7
9
 
8
10
  def add_headers headers
9
- puts "FOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"
10
- headers['X-SplinkUser'] = '0'
11
- headers['Content-Type'] = 'application/json'
11
+ Arrest::Source.header_decorator.headers.each_pair do |k,v|
12
+ headers[k.to_s] = v.to_s
13
+ end
12
14
  end
13
15
 
14
16
  def get sub
@@ -19,6 +21,15 @@ module Arrest
19
21
  response.body
20
22
  end
21
23
 
24
+ def delete rest_resource
25
+ raise "To delete an object it must have an id" unless rest_resource.respond_to?(:id) && rest_resource.id != nil
26
+ response = self.connection().delete do |req|
27
+ req.url rest_resource.location
28
+ add_headers req.headers
29
+ end
30
+ response.env[:status] == 200
31
+ end
32
+
22
33
  def put rest_resource
23
34
  raise "To change an object it must have an id" unless rest_resource.respond_to?(:id) && rest_resource.id != nil
24
35
  hash = rest_resource.to_hash
@@ -37,16 +48,28 @@ module Arrest
37
48
  raise "new object must have setter for id" unless rest_resource.respond_to?(:id=)
38
49
  raise "new object must not have id" if rest_resource.respond_to?(:id) && rest_resource.id != nil
39
50
  hash = rest_resource.to_hash
51
+ hash.delete(:id)
52
+ hash.delete('id')
53
+
54
+ hash.delete_if{|k,v| v == nil}
40
55
 
56
+ puts "URL:#{rest_resource.class.resource_path}"
57
+ body = hash.to_json
58
+ puts "Body:#{body}"
41
59
  response = self.connection().post do |req|
42
60
  req.url rest_resource.class.resource_path
43
61
  add_headers req.headers
44
- req.body = hash.to_json
62
+ req.body = body
63
+ end
64
+ if (response.env[:status] == 201)
65
+ location = response.env[:response_headers][:location]
66
+ id = location.gsub(/^.*\//, '')
67
+ rest_resource.id= id
68
+ else
69
+ puts "unable to create: #{response.env[:response_headers]} body: #{response.body} "
70
+ false
45
71
  end
46
- location = response.env[:response_headers][:location]
47
- id = location.gsub(/^.*\//, '')
48
- rest_resource.id= id
49
- response.env[:status] == 201
72
+
50
73
  end
51
74
 
52
75
  def connection
@@ -57,9 +57,15 @@ module Arrest
57
57
  end
58
58
 
59
59
 
60
+ def delete rest_resource
61
+ raise "To change an object it must have an id" unless rest_resource.respond_to?(:id) && rest_resource.id != nil
62
+ @@data[rest_resource.resource_path()].delete(rest_resource.id.to_s)
63
+ rest_resource
64
+ end
65
+
60
66
  def put rest_resource
61
- @@data[rest_resource.resource_path()][rest_resource.id.to_s] = rest_resource
62
67
  raise "To change an object it must have an id" unless rest_resource.respond_to?(:id) && rest_resource.id != nil
68
+ @@data[rest_resource.resource_path()][rest_resource.id.to_s] = rest_resource
63
69
  rest_resource
64
70
  end
65
71
 
@@ -4,6 +4,7 @@ module Arrest
4
4
  class << self
5
5
  attr_reader :source
6
6
  attr_reader :mod
7
+ attr_reader :header_decorator
7
8
 
8
9
  def source=(host=nil)
9
10
  if host == nil || host.blank?
@@ -24,7 +25,23 @@ module Arrest
24
25
  end
25
26
  end
26
27
 
28
+ def header_decorator=(hd=nil)
29
+ puts "Setting headerd to #{hd}"
30
+ if hd == nil
31
+ @header_decorator = self
32
+ elsif hd.respond_to?(:headers)
33
+ @header_decorator = hd
34
+ else
35
+ raise "Header_decorator must be an object that returns an hash for the method headers"
36
+ end
37
+ end
38
+
39
+ def headers
40
+ {}
41
+ end
42
+
27
43
  end
28
44
  end
29
45
  Source.mod = nil
46
+ Source.header_decorator = Source
30
47
  end
@@ -0,0 +1,63 @@
1
+ class StringUtils
2
+ class << self
3
+
4
+ PLURALS = [['(quiz)$', '\1zes'],['(ox)$', '\1en'],['([m|l])ouse$', '\1ice'],['(matr|vert|ind)ix|ex$', '\1ices'],
5
+ ['(x|ch|ss|sh)$', '\1es'],['([^aeiouy]|qu)ies$', '\1y'],['([^aeiouy]|q)y$$', '\1ies'],['(hive)$', '\1s'],
6
+ ['(?:[^f]fe|([lr])f)$', '\1\2ves'],['(sis)$', 'ses'],['([ti])um$', '\1a'],['(buffal|tomat)o$', '\1oes'],['(bu)s$', '\1es'],
7
+ ['(alias|status)$', '\1es'],['(octop|vir)us$', '\1i'],['(ax|test)is$', '\1es'],['s$', 's'],['$', 's']]
8
+ SINGULARS =[['(quiz)zes$', '\1'],['(matr)ices$', '\1ix'],['(vert|ind)ices$', '\1ex'],['^(ox)en$', '\1'],['(alias|status)es$', '\1'],
9
+ ['(octop|vir)i$', '\1us'],['(cris|ax|test)es$', '\1is'],['(shoe)s$', '\1'],['[o]es$', '\1'],['[bus]es$', '\1'],['([m|l])ice$', '\1ouse'],
10
+ ['(x|ch|ss|sh)es$', '\1'],['(m)ovies$', '\1ovie'],['[s]eries$', '\1eries'],['([^aeiouy]|qu)ies$', '\1y'],['[lr]ves$', '\1f'],
11
+ ['(tive)s$', '\1'],['(hive)s$', '\1'],['([^f])ves$', '\1fe'],['(^analy)ses$', '\1sis'],
12
+ ['([a]naly|[b]a|[d]iagno|[p]arenthe|[p]rogno|[s]ynop|[t]he)ses$', '\1\2sis'],['([ti])a$', '\1um'],['(news)$', '\1ews'], ['(.*)s$', '\1'], ['^(.*)$', '\1']]
13
+
14
+ def singular(str)
15
+ SINGULARS.each { |match_exp, replacement_exp| return str.gsub(Regexp.compile(match_exp), replacement_exp) unless str.match(Regexp.compile(match_exp)).nil?}
16
+ end
17
+
18
+ def plural(str)
19
+ PLURALS.each { |match_exp, replacement_exp| return str.gsub(Regexp.compile(match_exp), replacement_exp) unless str.match(Regexp.compile(match_exp)).nil? }
20
+ end
21
+
22
+ def plural?
23
+ PLURALS.each {|match_exp, replacement_exp| return true if str.match(Regexp.compile(match_exp))}
24
+ false
25
+ end
26
+
27
+ def blank? str
28
+ str == nil || str == ""
29
+ end
30
+
31
+ def is_upper? str
32
+ str == str.upcase
33
+ end
34
+
35
+ def underscore str
36
+ word = str.to_s.dup
37
+ word.gsub!(/::/, '/')
38
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
39
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
40
+ word.tr!("-", "_")
41
+ word.downcase!
42
+ word
43
+ end
44
+
45
+ def classify(str, upper_first = true)
46
+ result = ""
47
+ upperNext = false
48
+ (singular str) .each_char do |c|
49
+ if c == "_"
50
+ upperNext = true
51
+ else
52
+ if upperNext || (result == "" && upper_first)
53
+ result << c.upcase
54
+ else
55
+ result << c
56
+ end
57
+ upperNext = false
58
+ end
59
+ end
60
+ result
61
+ end
62
+ end
63
+ end
@@ -1,3 +1,3 @@
1
1
  module Arrest
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -2,19 +2,19 @@ require 'arrest'
2
2
  require 'test/unit'
3
3
 
4
4
  class Zoo < Arrest::RootResource
5
-
6
5
  attributes :name
7
-
6
+ read_only_attributes :ro1
8
7
  has_many :animals
9
-
10
8
  end
11
9
 
12
10
  class Animal < Arrest::RestChild
13
-
14
11
  attributes :kind, :age
15
-
16
12
  parent :zoo
13
+ end
17
14
 
15
+ class SpecialZoo < Zoo
16
+ read_only_attributes :ro2
17
+ attributes :is_magic
18
18
  end
19
19
 
20
20
  class FirstTest < Test::Unit::TestCase
@@ -51,6 +51,25 @@ class FirstTest < Test::Unit::TestCase
51
51
  assert_equal new_zoo.name, zoo_reloaded.name
52
52
  end
53
53
 
54
+ def test_delete
55
+ zoo_count_before = Zoo.all.length
56
+ new_zoo = Zoo.new({:name => "Foo"})
57
+ new_zoo.save
58
+ zoo_count_after = Zoo.all.length
59
+
60
+ assert_equal (zoo_count_before + 1), zoo_count_after
61
+ assert new_zoo.id != nil
62
+
63
+ zoo_the_last = Zoo.all.last
64
+ assert_equal new_zoo.name, zoo_the_last.name
65
+
66
+ zoo_reloaded = Zoo.find(new_zoo.id)
67
+ assert_equal new_zoo.name, zoo_reloaded.name
68
+
69
+ zoo_reloaded.delete
70
+ assert_equal zoo_count_before, Zoo.all.length
71
+ end
72
+
54
73
  def test_create_and_load
55
74
  zoo_count_before = Zoo.all.length
56
75
  new_zoo = Zoo.new({:name => "Foo"})
@@ -118,10 +137,49 @@ class FirstTest < Test::Unit::TestCase
118
137
 
119
138
  animal_retry = new_zoo.animals.last
120
139
  assert_equal animal_kind, animal_retry.kind
140
+ end
121
141
 
142
+ def test_inheritance
143
+ new_zoo = SpecialZoo.new({:name => "Foo", :is_magic => true})
144
+ new_zoo.save
122
145
 
146
+ assert new_zoo.id != nil, "Zoo must have id after save"
147
+ zoo_reloaded = SpecialZoo.find(new_zoo.id)
148
+ assert_equal true, zoo_reloaded.is_magic
149
+ assert_equal "Foo", zoo_reloaded.name
150
+ end
151
+
152
+ def test_inheritance_update
153
+ new_zoo = SpecialZoo.new({:name => "Foo", :is_magic => true})
154
+ new_zoo.save
155
+
156
+ assert new_zoo.id != nil, "Zoo must have id after save"
157
+ zoo_reloaded = SpecialZoo.find(new_zoo.id)
158
+ assert_equal true, zoo_reloaded.is_magic
159
+ assert_equal "Foo", zoo_reloaded.name
123
160
 
161
+ new_name = "Bar"
162
+ zoo_reloaded.name = new_name
163
+ zoo_reloaded.is_magic = !zoo_reloaded.is_magic
164
+ zoo_reloaded.save
165
+
166
+ updated_zoo = SpecialZoo.find(zoo_reloaded.id)
167
+ assert_equal new_name, updated_zoo.name
168
+ assert_equal !new_zoo.is_magic, updated_zoo.is_magic
124
169
  end
125
170
 
171
+ def test_read_only_attributes
172
+ zoo = SpecialZoo.new({:name => "Zoo", :ro1 => "one", :ro2 => "two", :is_magic => true})
173
+
174
+ assert_equal "Zoo", zoo.name
175
+ assert_equal "one", zoo.ro1
176
+ assert_equal "two", zoo.ro2
177
+ assert_equal true, zoo.is_magic
178
+
179
+ hash = zoo.to_hash
180
+
181
+ assert_nil hash[:ro1]
182
+ assert_nil hash[:ro2]
183
+ end
126
184
  end
127
185
 
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.2
4
+ version: 0.0.3
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-11-07 00:00:00.000000000Z
12
+ date: 2011-11-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &18515300 !ruby/object:Gem::Requirement
16
+ requirement: &2161032680 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,18 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *18515300
24
+ version_requirements: *2161032680
25
+ - !ruby/object:Gem::Dependency
26
+ name: faraday
27
+ requirement: &2161031520 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - =
31
+ - !ruby/object:Gem::Version
32
+ version: 0.7.5
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2161031520
25
36
  description: Consume a rest API in a AR like fashion
26
37
  email:
27
38
  - axel.tetzlaff@fortytools.com
@@ -41,6 +52,7 @@ files:
41
52
  - lib/arrest/rest_child.rb
42
53
  - lib/arrest/root_resource.rb
43
54
  - lib/arrest/source.rb
55
+ - lib/arrest/string_utils.rb
44
56
  - lib/arrest/version.rb
45
57
  - test/unit.rb
46
58
  homepage: ''
@@ -67,4 +79,5 @@ rubygems_version: 1.8.10
67
79
  signing_key:
68
80
  specification_version: 3
69
81
  summary: Another ruby rest client
70
- test_files: []
82
+ test_files:
83
+ - test/unit.rb