Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Develop #2

Merged
merged 29 commits into from over 1 year ago

3 participants

Rimian Perkins Mikel Lindsaar Sean Geoghegan
Rimian Perkins

No description provided.

Rimian Perkins rimian commented on the diff December 02, 2012
lib/switchvox/base.rb
((44 lines not shown))
  83
+    json = JSON.parse body
  84
+    convert_to_obj(json["response"]["result"])
  85
+  end
  86
+
  87
+  def convert_to_obj(arg)
  88
+    if arg.is_a? Hash
  89
+      arg.each { |k, v| arg[k] = convert_to_obj(v) }
  90
+      o = OpenStruct.new
  91
+      o.marshal_load Hash[arg.map { |k, v| [k.to_sym, v] }]
  92
+      return o
  93
+    elsif arg.is_a? Array
  94
+      arg.map! { |v| convert_to_obj(v) }
  95
+    else
  96
+      arg
  97
+    end
  98
+  end
3
Rimian Perkins
rimian added a note December 02, 2012

I wanna refactor this out into its own concern.

Sean Geoghegan
seangeo added a note December 02, 2012

Is it used anywhere else?

Rimian Perkins
rimian added a note December 02, 2012

Nah, but it seems like something the base class should delegate to. I'm OK with leaving it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Rimian Perkins rimian commented on the diff December 02, 2012
test/test_json_to_obj.rb
((21 lines not shown))
21  
-  
22  
-  def test_deep_nest_mixed
23  
-    json = {"kennels" => [
24  
-            {"dallas" => [
25  
-             {"name" => "north"},
26  
-             {"name"  => "east"},
27  
-            ]},
28  
-            {"frisco" => [
29  
-             {"name" => "south"},
30  
-             {"name"  => "west"}
31  
-            ],
32  
-            "company" => "Doggie Daze"
33  
-            }
34  
-          ]}.to_json
35  
-    obj  = JSON.parse(json).to_obj
36  
-    assert_equal("west", obj.kennels[1].frisco[0].name)
2
Rimian Perkins
rimian added a note December 02, 2012

Note: This spec is wrong, yes? It should be "south". Or am I missing something? This error does not persist in the new code.

Mikel Lindsaar Owner
mikel added a note December 02, 2012

Good catch, you are right.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/switchvox/base.rb
((38 lines not shown))
88 77
       else raise UnhandledResponse, "Can't handle response #{response}"
89 78
     end
90 79
   end
91 80
 
  81
+  # TODO - cover this with specs and return json not call other method
  82
+  def json_parse(body)
  83
+    json = JSON.parse body
  84
+    convert_to_obj(json["response"]["result"])
  85
+  end
  86
+
  87
+  def convert_to_obj(arg)
  88
+    if arg.is_a? Hash
  89
+      arg.each { |k, v| arg[k] = convert_to_obj(v) }
  90
+      o = OpenStruct.new
2
Sean Geoghegan
seangeo added a note December 02, 2012

You should be able to pass the hash in as an argument to the constructor instead of using marshal_load.

Rimian Perkins
rimian added a note December 02, 2012

Done! Much less code. No longer need the keys to symbols either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Manifest.txt
((1 lines not shown))
1  
-History.txt
2  
-Manifest.txt
3  
-README.rdoc
4  
-Rakefile
5  
-lib/switchvox.rb
6  
-lib/switchvox/array.rb
7  
-lib/switchvox/base.rb
8  
-lib/switchvox/hash.rb
9  
-lib/switchvox/net_http_digest_auth.rb
10  
-lib/switchvox/object.rb
11  
-script/console
12  
-script/destroy
13  
-script/generate
14  
-test/test_helper.rb
15  
-test/test_json_to_obj.rb
16  
-test/test_switchvox.rb
1
Mikel Lindsaar Owner
mikel added a note December 02, 2012

Why are you deleting this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
History.txt
... ...
@@ -1,4 +0,0 @@
1  
-=== 0.0.1 2010-04-22
2  
-
3  
-* 1 major enhancement:
4  
-  * Initial release
1
Mikel Lindsaar Owner
mikel added a note December 02, 2012

Why are you deleting this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Mikel Lindsaar
Owner

Looks good Rimian, please don't delete the Manifest or History though.

:thumbsup:

Mikel Lindsaar mikel commented on the diff December 02, 2012
Gemfile.lock
... ...
@@ -0,0 +1,26 @@
  1
+GEM
1
Mikel Lindsaar Owner
mikel added a note December 02, 2012

OK, remove this file from git and add it to .gitignore. See http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/ for reference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Gemfile
... ...
@@ -0,0 +1,7 @@
  1
+source :rubygems
  2
+
  3
+group :test do
  4
+  gem 'rspec'
  5
+  gem 'ffaker'
  6
+  gem 'webmock'
  7
+end
1
Mikel Lindsaar Owner
mikel added a note December 02, 2012

Should add loose (minor) version numbers to these.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Mikel Lindsaar mikel merged commit 7b59fe1 into from December 09, 2012
Mikel Lindsaar mikel closed this December 09, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 29 unique commits by 1 author.

Nov 29, 2012
Rimian Perkins add rspec helper and ignore rvmrc 68d6199
Rimian Perkins add rspec helper and ignore rvmrc 87e4692
Rimian Perkins initial rspec with stubbed out base class ad063bf
Rimian Perkins migrate test unit into rspec 1fcc01b
Rimian Perkins tidy up request specs 5c3f2d7
Rimian Perkins ignore rvm fe95cf9
Rimian Perkins Merge branch 'feature/rspec' into feature/refactor-array-class 19aa06b
Rimian Perkins assert all levels of object match with input b9b9b58
Rimian Perkins formatting json a bit 56d442e
Dec 01, 2012
Rimian Perkins rename file without class name c1c5280
Rimian Perkins rm debugging code for better readabilititity 1d876cc
Rimian Perkins pull out parse functionality from response method abd04a5
Rimian Perkins parse specs 8bd47c6
Rimian Perkins rename class out of file name 2fdb0ea
Rimian Perkins Index error! This should not be passing.
cd ./test
ruby -Itest test_json_to_obj.rb
d0e2e99
Rimian Perkins run parse tests against base class not JSON 09869ef
Rimian Perkins tidy up 31e4863
Rimian Perkins merge in rspec refactor 9c3a208
Rimian Perkins got nested hash specs passing... 39eab03
Dec 02, 2012
Rimian Perkins process array 2c6f35b
Rimian Perkins nested hash 86f71e8
Rimian Perkins whoops! wrong input for spec beb2768
Rimian Perkins remove hash, array and object class overrides. 87d3558
Rimian Perkins merge in refactor of hash and array. no longer overrides these classe…
…s and uses OpenStruct
04f7f59
Rimian Perkins dont see a need for these. 001a8f2
Dec 03, 2012
Rimian Perkins pass arg to new method instead of marshal_load. d54d41e
Rimian Perkins Revert "dont see a need for these."
This reverts commit 001a8f2.
1222e23
Rimian Perkins manifest and add gem for rake task 4ad0295
Rimian Perkins Incorrect manifest syntax. fixed 82d29d1
This page is out of date. Refresh to see the latest.
1  .gitignore
... ...
@@ -1 +1,2 @@
1 1
 pkg
  2
+.rvmrc
2  .rspec
... ...
@@ -0,0 +1,2 @@
  1
+--color
  2
+--format progress
1  .rvmrc
... ...
@@ -0,0 +1 @@
  1
+rvm use ruby-1.9.3
9  Gemfile
... ...
@@ -0,0 +1,9 @@
  1
+source :rubygems
  2
+
  3
+group :test do
  4
+  gem 'rake', '~> 10.0'
  5
+  gem 'rspec', '~> 2.12'
  6
+  gem 'ffaker', '~> 1.15'
  7
+  gem 'webmock', '~> 1.9'
  8
+  gem 'hoe', '>= 3.3'
  9
+end
31  Gemfile.lock
... ...
@@ -0,0 +1,31 @@
  1
+GEM
  2
+  remote: http://rubygems.org/
  3
+  specs:
  4
+    addressable (2.3.2)
  5
+    crack (0.3.1)
  6
+    diff-lcs (1.1.3)
  7
+    ffaker (1.15.0)
  8
+    hoe (3.3.1)
  9
+      rake (>= 0.8, < 11.0)
  10
+    rake (10.0.1)
  11
+    rspec (2.12.0)
  12
+      rspec-core (~> 2.12.0)
  13
+      rspec-expectations (~> 2.12.0)
  14
+      rspec-mocks (~> 2.12.0)
  15
+    rspec-core (2.12.0)
  16
+    rspec-expectations (2.12.0)
  17
+      diff-lcs (~> 1.1.3)
  18
+    rspec-mocks (2.12.0)
  19
+    webmock (1.9.0)
  20
+      addressable (>= 2.2.7)
  21
+      crack (>= 0.1.7)
  22
+
  23
+PLATFORMS
  24
+  ruby
  25
+
  26
+DEPENDENCIES
  27
+  ffaker (~> 1.15)
  28
+  hoe (>= 3.3)
  29
+  rake (~> 10.0)
  30
+  rspec (~> 2.12)
  31
+  webmock (~> 1.9)
6  History.txt
... ...
@@ -1,3 +1,9 @@
  1
+=== 0.1.0 2012-12-03
  2
+
  3
+* Convert tests to RSpec
  4
+* Remove Hash, Object and Array class over rides.
  5
+* Fix array index error.
  6
+
1 7
 === 0.0.1 2010-04-22
2 8
 
3 9
 * 1 major enhancement:
12  Manifest.txt
... ...
@@ -1,16 +1,16 @@
  1
+.rspec
  2
+.rvmrc
  3
+Gemfile
  4
+Gemfile.lock
1 5
 History.txt
2 6
 Manifest.txt
3 7
 README.rdoc
4 8
 Rakefile
5 9
 lib/switchvox.rb
6  
-lib/switchvox/array.rb
7 10
 lib/switchvox/base.rb
8  
-lib/switchvox/hash.rb
9 11
 lib/switchvox/net_http_digest_auth.rb
10  
-lib/switchvox/object.rb
11 12
 script/console
12 13
 script/destroy
13 14
 script/generate
14  
-test/test_helper.rb
15  
-test/test_json_to_obj.rb
16  
-test/test_switchvox.rb
  15
+spec/spec_helper.rb
  16
+spec/switchvox/base_spec.rb
5  Rakefile
... ...
@@ -1,5 +1,4 @@
1 1
 require 'rubygems'
2  
-gem 'hoe', '>= 2.1.0'
3 2
 require 'hoe'
4 3
 require 'fileutils'
5 4
 require './lib/switchvox'
@@ -18,8 +17,8 @@ $hoe = Hoe.spec 'switchvox' do
18 17
 
19 18
 end
20 19
 
21  
-require 'newgem/tasks'
22  
-Dir['tasks/**/*.rake'].each { |t| load t }
  20
+# require 'newgem/tasks'
  21
+# Dir['tasks/**/*.rake'].each { |t| load t }
23 22
 
24 23
 # TODO - want other tests/tasks run by default? Add them to the list
25 24
 # remove_task :default
3  lib/switchvox.rb
... ...
@@ -1,9 +1,6 @@
1 1
 $:.unshift(File.dirname(__FILE__)) unless
2 2
   $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3 3
 
4  
-require 'switchvox/hash'
5  
-require 'switchvox/array'
6  
-require 'switchvox/object'
7 4
 require 'switchvox/net_http_digest_auth'
8 5
 require 'switchvox/base'
9 6
 
14  lib/switchvox/array.rb
... ...
@@ -1,14 +0,0 @@
1  
-# A fancy way of iterating over an array and converting hashes to objects
2  
-class Array
3  
-  def to_obj
4  
-    # Make a deep copy of the array
5  
-    a = Marshal.load(Marshal.dump(self))
6  
-    a.each do |i|
7  
-      case i.class.to_s
8  
-        when "Hash" then i = i.to_obj
9  
-        when "Array" then i = i.to_obj
10  
-      end
11  
-    end
12  
-    a
13  
-  end
14  
-end
51  lib/switchvox/base.rb
@@ -8,6 +8,7 @@ module Switchvox
8 8
 require 'digest/md5'
9 9
 require 'rubygems'
10 10
 require 'json'
  11
+require 'ostruct'
11 12
 
12 13
 # Raised when credentials are incorrect
13 14
 class LoginError < RuntimeError
@@ -22,7 +23,7 @@ class UnhandledResponse < RuntimeError
22 23
 end
23 24
 
24 25
 # The primary class used to interact with Switchvox.
25  
-class Base 
  26
+class Base
26 27
 
27 28
   URL = "/json"
28 29
   attr :host, true
@@ -44,7 +45,7 @@ def initialize(host, user, pass, options={})
44 45
     @url  = URI.parse("https://" + @host + URL)
45 46
     @ssl  = false
46 47
     @ssl  = true if @url.scheme == "https"
47  
-        
  48
+
48 49
     @connection  = false
49 50
     @auth_header = false
50 51
     login!
@@ -55,40 +56,45 @@ def initialize(host, user, pass, options={})
55 56
   def request(method, parameters={})
56 57
     login! unless logged_in?
57 58
     json = wrap_json(method, parameters)
58  
-    
  59
+
59 60
     # Send the request
60 61
     header   = {'Content-Type' => "text/json"}
  62
+
61 63
     request  = Net::HTTP::Post.new(@url.path, header)
62 64
     request.digest_auth(@user, @pass, @auth_header)
63 65
     request.body = json
64 66
     response = @connection.request(request)
65 67
 
66  
-    if @debug
67  
-      puts "#{method}: Request"
68  
-      puts json
69  
-      puts "\n"
70  
-    end
71  
-
72 68
     case response
73 69
       when Net::HTTPOK
74 70
         raise EmptyResponse unless response.body
75  
-        response_json = JSON.parse response.body
76  
-        if @debug
77  
-          puts "#{method}: Response:"
78  
-          pp response_json 
79  
-          puts "\n\n"
80  
-        end
81  
-        response_obj = response_json["response"]["result"].to_obj
82  
-        return response_obj
  71
+        return json_parse(response.body)
83 72
       when Net::HTTPUnauthorized
84 73
         login!
85 74
         request(method, parameters)
86 75
       when Net::HTTPForbidden
87  
-        raise LoginError, "Invalid Username or Password" 
  76
+        raise LoginError, "Invalid Username or Password"
88 77
       else raise UnhandledResponse, "Can't handle response #{response}"
89 78
     end
90 79
   end
91 80
 
  81
+  # TODO - cover this with specs and return json not call other method
  82
+  def json_parse(body)
  83
+    json = JSON.parse body
  84
+    convert_to_obj(json["response"]["result"])
  85
+  end
  86
+
  87
+  def convert_to_obj(arg)
  88
+    if arg.is_a? Hash
  89
+      arg.each { |k, v| arg[k] = convert_to_obj(v) }
  90
+      OpenStruct.new arg
  91
+    elsif arg.is_a? Array
  92
+      arg.map! { |v| convert_to_obj(v) }
  93
+    else
  94
+      arg
  95
+    end
  96
+  end
  97
+
92 98
   protected
93 99
 
94 100
     # Check to see if we are logged in
@@ -96,7 +102,7 @@ def logged_in?
96 102
       return false unless @auth_header
97 103
       true
98 104
     end
99  
-  
  105
+
100 106
     # Attempt HTTP Digest Authentication with Switchvox
101 107
     def login!
102 108
       connect! unless connected?
@@ -117,9 +123,6 @@ def connect!
117 123
         @connection.use_ssl = true
118 124
         @connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
119 125
       end
120  
-      if @debug
121  
-        #@connection.set_debug_output $stderr
122  
-      end
123 126
       @connection.start
124 127
     end
125 128
 
@@ -137,9 +140,7 @@ def wrap_json(method, parameters={})
137 140
     end
138 141
 
139 142
 end
140  
-  
141  
-end
142  
-
143 143
 
  144
+end
144 145
 
145 146
 
17  lib/switchvox/hash.rb
... ...
@@ -1,17 +0,0 @@
1  
-# A fancy way of iterating over a hash and converting hashes to objects
2  
-class Hash
3  
-  def to_obj
4  
-    o = Object.new
5  
-    self.each do |k,v|
6  
-      # If we're looking at a hash or array, we need to look through them and convert any hashes to objects as well
7  
-      case v.class.to_s
8  
-        when "Hash"  then v = v.to_obj
9  
-        when "Array" then v = v.to_obj
10  
-      end
11  
-      o.instance_variable_set("@#{k}", v)  ## create and initialize an instance variable for this key/value pair
12  
-      o.class.send(:define_method, k, proc{o.instance_variable_get("@#{k}")})  ## create the getter that returns the instance variable
13  
-      o.class.send(:define_method, "#{k}=", proc{|v| o.instance_variable_set("@#{k}", v)})  ## create the setter that sets the instance variable
14  
-    end
15  
-    o
16  
-  end
17  
-end
5  lib/switchvox/object.rb
... ...
@@ -1,5 +0,0 @@
1  
-class Object
2  
-  def to_obj
3  
-    self
4  
-  end
5  
-end
11  spec/spec_helper.rb
... ...
@@ -0,0 +1,11 @@
  1
+require 'ffaker'
  2
+require 'webmock/rspec'
  3
+require 'switchvox'
  4
+
  5
+RSpec.configure do |config|
  6
+  config.treat_symbols_as_metadata_keys_with_true_values = true
  7
+  config.run_all_when_everything_filtered = true
  8
+  config.filter_run :focus
  9
+
  10
+  config.order = 'random'
  11
+end
71  spec/switchvox/base_spec.rb
... ...
@@ -0,0 +1,71 @@
  1
+require 'spec_helper'
  2
+
  3
+describe Switchvox::Base do
  4
+  let(:host) { 'example.com' }
  5
+  let(:switchvox) do
  6
+    stub_request(:head, 'https://' + host + '/json').
  7
+       with(:headers => {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}).
  8
+       to_return(:status => 200, :body => "", :headers => {})
  9
+    req = Net::HTTP.new(host, '8080')
  10
+    Switchvox::Base.new(host ,Faker::Internet.user_name, 'password')
  11
+  end
  12
+
  13
+  def response_json(body)
  14
+    Hash['response', Hash['result', body]].to_json
  15
+  end
  16
+
  17
+  describe 'parse json and return object' do
  18
+    it 'should test_object' do
  19
+      input = {"string" => "value"}
  20
+      obj = switchvox.json_parse(response_json(input))
  21
+      obj.string.should == 'value'
  22
+    end
  23
+
  24
+    it 'should test test_nested_object' do
  25
+      input = {"dogs" => {"retriever" => "sparky", "basset" => "jennie", "pinscher" => "carver"}}
  26
+      obj = switchvox.json_parse(response_json(input))
  27
+      obj.dogs.retriever.should == 'sparky'
  28
+    end
  29
+
  30
+    it 'should test test_array_of_objects' do
  31
+      input = [{"retriever" => "sparky"}, {"basset" => "jennie"}, {"pinscher" => "carver"}]
  32
+      obj = switchvox.json_parse(response_json(input))
  33
+      obj[0].retriever.should == "sparky"
  34
+    end
  35
+
  36
+    it 'should test test_deep_nest_mixed' do
  37
+      input = {
  38
+        "kennels" => [
  39
+          {
  40
+            "dallas" => [
  41
+              {"name" => "north"},
  42
+              {"name"  => "east"},
  43
+            ]
  44
+          },
  45
+          {
  46
+            "frisco" => [
  47
+              {"name" => "south"},
  48
+              {"name"  => "west"}
  49
+            ],
  50
+            "company" => "Doggie Daze"
  51
+          }
  52
+        ]
  53
+      }
  54
+      obj = switchvox.json_parse(response_json(input))
  55
+      obj.kennels[1].frisco[1].name.should == 'west'
  56
+    end
  57
+
  58
+    it 'should test test_deep_nest_hash' do
  59
+      input = {
  60
+        "kennels" => {
  61
+          "kennel" => {
  62
+            "dallas" => ["north", "south"],
  63
+            "frisco" => ["east", "west"]
  64
+          }
  65
+        }
  66
+      }
  67
+      obj = switchvox.json_parse(response_json(input))
  68
+      obj.kennels.kennel.dallas[0].should == 'north'
  69
+    end
  70
+  end
  71
+end
4  test/test_helper.rb
... ...
@@ -1,4 +0,0 @@
1  
-require 'stringio'
2  
-require 'test/unit'
3  
-require 'pp'
4  
-require File.dirname(__FILE__) + '/../lib/switchvox'
49  test/test_json_to_obj.rb
... ...
@@ -1,49 +0,0 @@
1  
-require File.dirname(__FILE__) + '/test_helper.rb'
2  
-
3  
-class TestJson2Object < Test::Unit::TestCase
4  
-  def test_object
5  
-    json = {"string" => "value"}.to_json
6  
-    obj  = JSON.parse(json).to_obj
7  
-    assert_equal("value", obj.string)
8  
-  end
9  
-  
10  
-  def test_nested_object
11  
-    json = {"dogs" => {"retriever" => "sparky", "basset" => "jennie", "pinscher" => "carver"}}.to_json
12  
-    obj  = JSON.parse(json).to_obj
13  
-    assert_equal("sparky", obj.dogs.retriever)
14  
-  end
15  
-  
16  
-  def test_array_of_objects
17  
-    json = [{"retriever" => "sparky"}, {"basset" => "jennie"}, {"pinscher" => "carver"}].to_json
18  
-    obj  = JSON.parse(json).to_obj
19  
-    assert_equal("sparky", obj[0].retriever)
20  
-  end
21  
-  
22  
-  def test_deep_nest_mixed
23  
-    json = {"kennels" => [
24  
-            {"dallas" => [
25  
-             {"name" => "north"},
26  
-             {"name"  => "east"},
27  
-            ]},
28  
-            {"frisco" => [
29  
-             {"name" => "south"},
30  
-             {"name"  => "west"}
31  
-            ],
32  
-            "company" => "Doggie Daze"
33  
-            }
34  
-          ]}.to_json
35  
-    obj  = JSON.parse(json).to_obj
36  
-    assert_equal("west", obj.kennels[1].frisco[0].name)
37  
-  end
38  
-  
39  
-  def test_deep_nest_hash
40  
-    json = {"kennels" => {
41  
-            "kennel" => {
42  
-            "dallas" => ["north", "south"],
43  
-            "frisco" => ["east", "west"]}}
44  
-           }.to_json
45  
-    obj  = JSON.parse(json).to_obj
46  
-    pp obj
47  
-    assert_equal("north", obj.kennels.kennel.dallas[0])
48  
-  end
49  
-end
11  test/test_switchvox.rb
... ...
@@ -1,11 +0,0 @@
1  
-require File.dirname(__FILE__) + '/test_helper.rb'
2  
-
3  
-class TestSwitchvox < Test::Unit::TestCase
4  
-
5  
-  def setup
6  
-  end
7  
-  
8  
-  def test_truth
9  
-    assert true
10  
-  end
11  
-end
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.