arrest 0.0.1

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 ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in arrest.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1 @@
1
+ Consume a rest API in a AR like fashion
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/arrest.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "arrest/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "arrest"
7
+ s.version = Arrest::VERSION
8
+ s.authors = ["Axel Tetzlaff"]
9
+ s.email = ["axel.tetzlaff@fortytools.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Another ruby rest client}
12
+ s.description = %q{Consume a rest API in a AR like fashion}
13
+
14
+ s.rubyforge_project = "arrest"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ end
data/lib/arrest.rb ADDED
@@ -0,0 +1,18 @@
1
+ require "arrest/version"
2
+
3
+ require "arrest/http_source"
4
+ require "arrest/mem_source"
5
+ require "arrest/abstract_resource"
6
+ require "arrest/root_resource"
7
+ require "arrest/rest_child"
8
+
9
+ module Arrest
10
+
11
+ class Source
12
+
13
+ cattr_accessor :source
14
+
15
+ end
16
+ Source.source= MemSource.new
17
+
18
+ end
@@ -0,0 +1,42 @@
1
+ module Arrest
2
+ class AbstractResource
3
+ extend ActiveModel::Naming
4
+
5
+ attr_accessor :keys
6
+
7
+ class << self
8
+
9
+ def source
10
+ Arrest::Source::source
11
+ end
12
+
13
+
14
+ def body_root response
15
+ all = JSON.parse response
16
+ all["result"]
17
+ end
18
+
19
+ def build hash
20
+ raise "override in subclass with a method, that converts the given hash to an object of the desired class"
21
+ end
22
+
23
+ def resource_name
24
+ self.name.sub(/.*:/,'').downcase.pluralize
25
+ end
26
+ end
27
+
28
+ def save
29
+ if self.respond_to?(:id) && self.id.present?
30
+ AbstractResource::source().put self
31
+ else
32
+ AbstractResource::source().post self
33
+ end
34
+ end
35
+
36
+
37
+ def to_hash
38
+ raise "override symmetrically to build, to create a hash representation from self"
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,62 @@
1
+ module Arrest
2
+ class HttpSource
3
+
4
+ def initialize base
5
+ @base = base
6
+ end
7
+
8
+ def add_headers headers
9
+ puts "FOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"
10
+ headers['X-SplinkUser'] = '0'
11
+ headers['Content-Type'] = 'application/json'
12
+ end
13
+
14
+ def get sub
15
+ response = self.connection().get do |req|
16
+ req.url sub
17
+ add_headers req.headers
18
+ end
19
+ response.body
20
+ end
21
+
22
+ def put rest_resource
23
+ raise "To change an object it must have an id" unless rest_resource.respond_to?(:id) && rest_resource.id.present?
24
+ hash = rest_resource.to_hash
25
+ hash.delete(:id)
26
+ hash.delete("id")
27
+
28
+ response = self.connection().put do |req|
29
+ req.url "#{rest_resource.class.path}/#{rest_resource.id}"
30
+ add_headers req.headers
31
+ req.body = hash.to_json
32
+ end
33
+ response.env[:status] == 200
34
+ end
35
+
36
+ def post rest_resource
37
+ raise "new object must have setter for id" unless rest_resource.respond_to?(:id=)
38
+ raise "new object must not have id" if rest_resource.respond_to?(:id) && rest_resource.id.present?
39
+ hash = rest_resource.to_hash
40
+
41
+ response = self.connection().post do |req|
42
+ req.url rest_resource.class.path
43
+ add_headers req.headers
44
+ req.body = hash.to_json
45
+ end
46
+ location = response.env[:response_headers][:location]
47
+ id = location.gsub(/^.*\//, '')
48
+ rest_resource.id= id
49
+ response.env[:status] == 201
50
+ end
51
+
52
+ def connection
53
+ conn = Faraday.new(:url => @base) do |builder|
54
+ builder.request :url_encoded
55
+ builder.request :json
56
+ builder.response :logger
57
+ builder.adapter :net_http
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,87 @@
1
+ module Arrest
2
+ class MemSource
3
+
4
+ attr_accessor :data
5
+
6
+ @@data = {}
7
+
8
+ def data
9
+ @@data
10
+ end
11
+
12
+ def initialize
13
+ end
14
+
15
+ def wrap content,count
16
+ "{
17
+ \"queryTime\" : \"0.01866644\",
18
+ \"resultCount\" : #{count},
19
+ \"results\" : #{content} }"
20
+
21
+ end
22
+
23
+ def get sub
24
+ idx = sub.rindex(/\/[0-9]*$/)
25
+ if idx.present?
26
+ ps = [sub[0..(idx-1)], sub[(idx+1)..sub.length]]
27
+ else
28
+ ps = [sub]
29
+ end
30
+ val = traverse @@data,ps
31
+ if val.is_a?(Hash)
32
+ wrap collection_json(val.values), val.length
33
+ elsif val.blank?
34
+ wrap "{}", 0
35
+ else
36
+ wrap val.to_hash.to_json, 1
37
+ end
38
+ end
39
+
40
+ def collection_json values
41
+ single_jsons = values.map do |v|
42
+ v.to_hash.to_json
43
+ end
44
+ "[#{single_jsons.join(',')}]"
45
+ end
46
+
47
+ def traverse hash, keys
48
+ if keys.empty?
49
+ return hash
50
+ end
51
+ key = keys.first
52
+ if hash.blank?
53
+ nil
54
+ else
55
+ traverse hash[key.to_s],keys.drop(1)
56
+ end
57
+ end
58
+
59
+
60
+ def put rest_resource
61
+ @@data[rest_resource.resource_path()][rest_resource.id.to_s] = rest_resource
62
+ raise "To change an object it must have an id" unless rest_resource.respond_to?(:id) && rest_resource.id.present?
63
+ rest_resource
64
+ end
65
+
66
+ def post rest_resource
67
+ raise "new object must have setter for id" unless rest_resource.respond_to?(:id=)
68
+ raise "new object must not have id" if rest_resource.respond_to?(:id) && rest_resource.id.present?
69
+ if @@data[rest_resource.resource_path()].present?
70
+ last_id = @@data[rest_resource.resource_path()].values.map(&:id).sort.last
71
+ else
72
+ last_id = 42
73
+ end
74
+ if last_id.is_a?(Integer)
75
+ next_id = last_id + 1
76
+ else
77
+ next_id = "#{last_id}x"
78
+ end
79
+ rest_resource.id = next_id
80
+ unless @@data[rest_resource.resource_path()].present?
81
+ @@data[rest_resource.resource_path()] = {}
82
+ end
83
+ @@data[rest_resource.resource_path()][next_id.to_s] = rest_resource
84
+ next_id
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,42 @@
1
+ module Arrest
2
+ class RestChild < AbstractResource
3
+ attr_accessor :parent
4
+ def initialize parent
5
+ @parent = parent
6
+ end
7
+
8
+ class << self
9
+ # class method to generate path to a child resource of aonther resource
10
+ def resource_path_for parent
11
+ "#{parent.location}/#{self.resource_name}"
12
+ end
13
+
14
+
15
+ def all_for parent
16
+ body_root(source().get self.resource_path_for(parent)).map do |h|
17
+ self.build(parent, h)
18
+ end
19
+ end
20
+
21
+ def find_for parent,id
22
+ r = source().get "#{self.resource_path_for(parent)}/#{id}"
23
+ body = body_root(r)
24
+ self.build body
25
+ end
26
+
27
+ end
28
+
29
+ # instance method to generate path to a child resource of another resource
30
+ def resource_path
31
+ self.class.resource_path_for @parent
32
+ end
33
+
34
+ # unique url for one instance of this class
35
+ def location
36
+ "#{self.class.resource_path}/#{self.id.to_s}"
37
+ end
38
+
39
+
40
+ end
41
+ end
42
+
@@ -0,0 +1,34 @@
1
+ module Arrest
2
+ class RootResource < AbstractResource
3
+
4
+ class << self
5
+
6
+ def resource_path
7
+ "#{self.resource_name}"
8
+ end
9
+
10
+ def all
11
+ body_root(source().get self.resource_path).map do |h|
12
+ self.build h
13
+ end
14
+ end
15
+
16
+ def find id
17
+ r = source().get "#{self.resource_path}/#{id}"
18
+ body = body_root(r)
19
+ self.build body
20
+ end
21
+
22
+ end
23
+
24
+ def resource_path
25
+ "#{self.class.resource_name}"
26
+ end
27
+
28
+ def location
29
+ self.class.resource_path + '/' + self.id.to_s
30
+ end
31
+
32
+ end
33
+ end
34
+
@@ -0,0 +1,3 @@
1
+ module Arrest
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: arrest
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Axel Tetzlaff
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-03 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: Consume a rest API in a AR like fashion
15
+ email:
16
+ - axel.tetzlaff@fortytools.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - README.md
24
+ - Rakefile
25
+ - arrest.gemspec
26
+ - lib/arrest.rb
27
+ - lib/arrest/abstract_resource.rb
28
+ - lib/arrest/http_source.rb
29
+ - lib/arrest/mem_source.rb
30
+ - lib/arrest/rest_child.rb
31
+ - lib/arrest/root_resource.rb
32
+ - lib/arrest/version.rb
33
+ homepage: ''
34
+ licenses: []
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubyforge_project: arrest
53
+ rubygems_version: 1.8.10
54
+ signing_key:
55
+ specification_version: 3
56
+ summary: Another ruby rest client
57
+ test_files: []