morpheus 0.3.8 → 0.3.9

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - rbx-18mode
data/Gemfile CHANGED
@@ -1,3 +1,8 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
3
  gemspec
4
+
5
+ group :development do
6
+ gem 'simplecov', '~> 0.5.4'
7
+ gem 'autotest-standalone', '~> 4.5.9'
8
+ end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Morpheus
1
+ # Morpheus [![Travis CI Build Status](https://secure.travis-ci.org/ryanmoran/morpheus.png)](http://travis-ci.org/#!/ryanmoran/morpheus)
2
2
  ## A RESTful API Client library built over Typhoeus
3
3
  * The project is working toward a DSL that is very ActiveResource/ActiveRecord-like with some features stolen from other great libraries like DataMapper.
4
4
  * We started working on this at a point when we felt we were pushing ActiveResource to its limits.
data/Rakefile CHANGED
@@ -7,12 +7,4 @@ task :default => :spec
7
7
 
8
8
  desc 'Run specs'
9
9
  RSpec::Core::RakeTask.new do |t|
10
- t.pattern = './spec/**/*_spec.rb'
11
- end
12
-
13
- desc 'Generate code coverage'
14
- RSpec::Core::RakeTask.new(:coverage) do |t|
15
- t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
16
- t.rcov = true
17
- t.rcov_opts = ['--exclude', 'spec']
18
10
  end
@@ -85,7 +85,7 @@ module Morpheus
85
85
  # request will be made.
86
86
  def loaded_target
87
87
  @target ||= load_target!
88
- if Array === @target && !@filters.empty?
88
+ if ::Array === @target && !@filters.empty?
89
89
  @filters.uniq.inject(@target.dup) do |target, filter|
90
90
  filter.call(target)
91
91
  end
@@ -46,7 +46,7 @@ module Morpheus
46
46
  end
47
47
 
48
48
  def method_missing(m, *args, &block)
49
- if Array.method_defined?(m)
49
+ if ::Array.method_defined?(m)
50
50
  loaded_target.send(m, *args, &block)
51
51
  else
52
52
  loaded_target.send(m, *args, &block)
@@ -2,7 +2,7 @@ module Morpheus
2
2
  class Request < Typhoeus::Request
3
3
  attr_reader :path, :params, :method
4
4
 
5
- def initialize(path, options = {})
5
+ def initialize(path, options = {})
6
6
  if options[:method] == :put
7
7
  options[:method] = :post
8
8
  options[:params].merge!(:_method => :put)
@@ -12,30 +12,30 @@ module Morpheus
12
12
  options[:password] = Configuration.password if Configuration.password
13
13
 
14
14
  super(Configuration.host + path, options)
15
- end
15
+ end
16
16
 
17
- def cache_key
18
- [method, url, params].hash
19
- end
17
+ def cache_key
18
+ Digest::SHA1.hexdigest([method, url, params].inspect)
19
+ end
20
20
 
21
- def response=(response)
21
+ def response=(response)
22
22
  RequestCache.cache[cache_key] = response
23
23
  response.tag_for_caching!
24
24
  super
25
- end
25
+ end
26
26
 
27
- def response
27
+ def response
28
28
  RequestQueue.run! if RequestQueue.has_request?(self)
29
29
  RequestCache.cache[cache_key]|| super
30
- end
30
+ end
31
31
 
32
- def self.enqueue(method, path, params)
32
+ def self.enqueue(method, path, params)
33
33
  options = { :method => method }
34
34
  options.merge!(:params => params) unless params.blank?
35
35
  new(path, options).tap do |request|
36
36
  RequestQueue.enqueue(request)
37
37
  end
38
- end
38
+ end
39
39
 
40
40
  end
41
41
  end
@@ -1,79 +1,76 @@
1
1
  module Morpheus
2
- class TypeCaster
2
+ module TypeCaster
3
+ extend self
3
4
 
4
- class << self
5
-
6
- def cast(value, typecast_class)
7
- case typecast_class
8
- when NilClass
9
- value
10
- when :string
11
- parse_string(value)
12
- when :integer
13
- parse_integer(value)
14
- when :datetime
15
- parse_datetime(value)
16
- when :date
17
- parse_date(value)
18
- when :time
19
- parse_time(value)
20
- when :boolean
21
- parse_boolean(value)
22
- else
23
- raise UnrecognizedTypeCastClass, "Can't typecast to #{typecast_class}!"
24
- end
5
+ def cast(value, typecast_class)
6
+ case typecast_class
7
+ when NilClass
8
+ value
9
+ when :string
10
+ parse_string(value)
11
+ when :integer
12
+ parse_integer(value)
13
+ when :datetime
14
+ parse_datetime(value)
15
+ when :date
16
+ parse_date(value)
17
+ when :time
18
+ parse_time(value)
19
+ when :boolean
20
+ parse_boolean(value)
21
+ else
22
+ raise UnrecognizedTypeCastClass, "Can't typecast to #{typecast_class}!"
25
23
  end
24
+ end
26
25
 
27
- private
26
+ private
28
27
 
29
- def parse_string(value)
30
- value.to_s
31
- end
32
-
33
- def parse_integer(value)
34
- if value.respond_to?(:to_i)
35
- value.to_i
36
- else
37
- case value
38
- when TrueClass then 1
39
- when FalseClass then 0
40
- when Date then value.to_time.utc.to_i
41
- end
42
- end
43
- end
28
+ def parse_string(value)
29
+ value.to_s
30
+ end
44
31
 
45
- def parse_datetime(value)
46
- if value.respond_to?(:to_datetime)
47
- value.to_datetime
48
- else
49
- DateTime.parse(value) unless [TrueClass, FalseClass, NilClass, Fixnum].include?(value.class)
32
+ def parse_integer(value)
33
+ if value.respond_to?(:to_i)
34
+ value.to_i
35
+ else
36
+ case value
37
+ when TrueClass then 1
38
+ when FalseClass then 0
39
+ when Date then value.to_time.utc.to_i
50
40
  end
51
- rescue ArgumentError
52
- nil
53
41
  end
42
+ end
54
43
 
55
- def parse_date(value)
56
- if value.respond_to?(:to_time)
57
- parse_time(value).try(:to_date)
58
- else
59
- Date.parse(value) unless [TrueClass, FalseClass, NilClass, Fixnum].include?(value.class)
60
- end
44
+ def parse_datetime(value)
45
+ if value.respond_to?(:to_datetime)
46
+ value.to_datetime
47
+ else
48
+ DateTime.parse(value) unless [TrueClass, FalseClass, NilClass, Fixnum].include?(value.class)
61
49
  end
50
+ rescue ArgumentError
51
+ nil
52
+ end
62
53
 
63
- def parse_time(value)
64
- if value.respond_to?(:to_time)
65
- value.to_time
66
- else
67
- Time.parse(value) unless [TrueClass, FalseClass, NilClass, Fixnum].include?(value.class)
68
- end
69
- rescue ArgumentError
70
- nil
54
+ def parse_date(value)
55
+ if value.respond_to?(:to_time)
56
+ parse_time(value).try(:to_date)
57
+ else
58
+ Date.parse(value) unless [TrueClass, FalseClass, NilClass, Fixnum].include?(value.class)
71
59
  end
60
+ end
72
61
 
73
- def parse_boolean(value)
74
- !["nil", nil, "false", false, "0", 0].include?(value)
62
+ def parse_time(value)
63
+ if value.respond_to?(:to_time)
64
+ value.to_time
65
+ else
66
+ Time.parse(value) unless [TrueClass, FalseClass, NilClass, Fixnum].include?(value.class)
75
67
  end
68
+ rescue ArgumentError
69
+ nil
70
+ end
76
71
 
72
+ def parse_boolean(value)
73
+ !["nil", nil, "false", false, "0", 0].include?(value)
77
74
  end
78
75
 
79
76
  end
@@ -1,51 +1,48 @@
1
1
  module Morpheus
2
- class UrlBuilder
2
+ module UrlBuilder
3
+ extend self
3
4
 
4
- class << self
5
-
6
- def find_one(klass, id)
7
- "/#{klass.plural_url_name}/#{id}"
8
- end
9
-
10
- def find_some(klass, ids)
11
- ["/#{klass.plural_url_name}", { :ids => ids }]
12
- end
5
+ def find_one(klass, id)
6
+ "/#{klass.plural_url_name}/#{id}"
7
+ end
13
8
 
14
- def find_all(klass)
15
- "/#{klass.plural_url_name}"
16
- end
9
+ def find_some(klass, ids)
10
+ ["/#{klass.plural_url_name}", { :ids => ids }]
11
+ end
17
12
 
18
- def save(klass, id, parameters)
19
- url_base = "/#{klass.plural_url_name}"
20
- url_base << "/#{id}" if id
21
- [url_base, parameters]
22
- end
13
+ def find_all(klass)
14
+ "/#{klass.plural_url_name}"
15
+ end
23
16
 
24
- def belongs_to(klass, id)
25
- "/#{klass.plural_url_name}/#{id}"
26
- end
17
+ def save(klass, id, parameters)
18
+ url_base = "/#{klass.plural_url_name}"
19
+ url_base << "/#{id}" if id
20
+ [url_base, parameters]
21
+ end
27
22
 
28
- def has_one(primary_class, primary_key, foreign_class)
29
- "/#{primary_class.plural_url_name}/#{primary_key}/#{foreign_class.singular_url_name}"
30
- end
23
+ def belongs_to(klass, id)
24
+ "/#{klass.plural_url_name}/#{id}"
25
+ end
31
26
 
32
- def has_many(primary_class, primary_key, foreign_class)
33
- "/#{primary_class.plural_url_name}/#{primary_key}/#{foreign_class.plural_url_name}"
34
- end
27
+ def has_one(primary_class, primary_key, foreign_class)
28
+ "/#{primary_class.plural_url_name}/#{primary_key}/#{foreign_class.singular_url_name}"
29
+ end
35
30
 
36
- def relation(klass, parameters = {})
37
- url_base = "/#{klass.plural_url_name}"
38
- if parameters.empty?
39
- url_base
40
- else
41
- [url_base, parameters]
42
- end
43
- end
31
+ def has_many(primary_class, primary_key, foreign_class)
32
+ "/#{primary_class.plural_url_name}/#{primary_key}/#{foreign_class.plural_url_name}"
33
+ end
44
34
 
45
- def destroy(klass, id)
46
- "/#{klass.plural_url_name}/#{id}"
35
+ def relation(klass, parameters = {})
36
+ url_base = "/#{klass.plural_url_name}"
37
+ if parameters.empty?
38
+ url_base
39
+ else
40
+ [url_base, parameters]
47
41
  end
42
+ end
48
43
 
44
+ def destroy(klass, id)
45
+ "/#{klass.plural_url_name}/#{id}"
49
46
  end
50
47
 
51
48
  end
@@ -1,3 +1,3 @@
1
1
  module Morpheus
2
- VERSION = '0.3.8'
2
+ VERSION = '0.3.9'
3
3
  end
data/lib/morpheus.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # We need to be able to use digest for cache keys.
2
+ require 'digest'
3
+
1
4
  # We are using Yalj::Ruby for its JSON parsing hotness.
2
5
  require 'yajl/json_gem'
3
6
 
data/morpheus.gemspec CHANGED
@@ -25,6 +25,4 @@ Gem::Specification.new do |gem|
25
25
  gem.add_development_dependency 'rails', '>= 3.0.0'
26
26
  gem.add_development_dependency 'sqlite3', '~> 1.3.3'
27
27
  gem.add_development_dependency 'rspec-rails', '~> 2.8.1'
28
- gem.add_development_dependency 'rcov', '~> 0.9.11'
29
- gem.add_development_dependency 'autotest-standalone', '~> 4.5.9'
30
28
  end
@@ -83,8 +83,7 @@ describe Morpheus::Base do
83
83
  @auto.attributes.should eql(HashWithIndifferentAccess.new({ :id => nil, :bhp => nil, :wheels => nil, :hybrid => nil, :name => nil }))
84
84
  end
85
85
  end
86
-
87
- context 'when an attributes hash is supplied' do
86
+ context 'when an attributes hash is supplied' do
88
87
  before(:each) do
89
88
  @auto = Automobile.new(
90
89
  :bhp => 300,
@@ -115,7 +114,44 @@ describe Morpheus::Base do
115
114
  end
116
115
 
117
116
  describe Morpheus::Base, '#==' do
118
- pending
117
+ let(:attributes) { { :id => 1, :name => 'Fido' } }
118
+
119
+ context 'when comparing objects that are actually referencing the same memory' do
120
+ it 'returns true' do
121
+ dog_1 = Dog.new(attributes)
122
+ dog_2 = dog_1
123
+ dog_1.should ==(dog_2)
124
+ end
125
+ end
126
+
127
+ context 'when comparing objects that are of the same class' do
128
+ context 'that have the same id' do
129
+ context 'that are not new records' do
130
+ it 'returns true' do
131
+ dog_1 = Dog.new(attributes)
132
+ dog_2 = Dog.new(attributes)
133
+ dog_1.should ==(dog_2)
134
+ end
135
+ end
136
+
137
+ context 'that are new records' do
138
+ it 'returns false' do
139
+ dog_1 = Dog.new(attributes.except(:id))
140
+ dog_2 = Dog.new(attributes.except(:id))
141
+ dog_1.should_not ==(dog_2)
142
+ end
143
+ end
144
+ end
145
+
146
+ context 'that do not have the same id' do
147
+ it 'returns false' do
148
+ dog_1 = Dog.new(attributes)
149
+ dog_2 = Dog.new(attributes)
150
+ dog_2.id = 2
151
+ dog_1.should_not ==(dog_2)
152
+ end
153
+ end
154
+ end
119
155
  end
120
156
 
121
157
  describe Morpheus::Base, '.base_class' do
@@ -1,37 +1,83 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Morpheus::RequestQueue do
4
+ let(:rq) { Morpheus::RequestQueue }
5
+ let(:app) { mock.tap { |a| a.stub(:call) } }
6
+ let(:request) { mock(:cache_key => 321) }
7
+ let(:env) { mock }
8
+ let(:cached_request) { mock(:cache_key => 123) }
9
+ let(:response) { mock }
10
+ let(:queue) { rq.new(app) }
4
11
 
5
12
  describe '#initialize' do
6
- pending
13
+ it 'acts as Rack Middleware, taking an app initialization params' do
14
+ queue = rq.new(app)
15
+ queue.instance_variable_get('@app').should eql(app)
16
+ end
7
17
  end
8
18
 
9
19
  describe '#call' do
10
- pending
20
+ it 'clears the queue' do
21
+ rq.enqueue(request)
22
+ rq.queue.length.should eql(1)
23
+ queue.call(env)
24
+ rq.queue.length.should eql(0)
25
+ end
26
+
27
+ it 'calls #call on the @app instance variable' do
28
+ app.should_receive(:call).with(env)
29
+ queue.call(env)
30
+ end
11
31
  end
12
32
 
13
33
  describe '.enqueue' do
14
- pending
34
+ it 'puts the passed parameter onto the queue' do
35
+ rq.enqueue(request)
36
+ rq.queue.should include(request)
37
+ end
15
38
  end
16
39
 
17
40
  describe '.queue' do
18
- pending
41
+ it 'defaults to an empty array' do
42
+ rq.queue.length.should eql(0)
43
+ end
44
+
45
+ it 'returns the array stored in the @queue instance variable' do
46
+ rq.enqueue(request)
47
+ rq.queue.should include(request)
48
+ end
19
49
  end
20
50
 
21
51
  describe '.uncached_queue' do
22
- pending
52
+ it 'returns an array of requests that have been queued, but are not in the cache' do
53
+ Morpheus::RequestCache.cache[cached_request.cache_key] = response
54
+ rq.enqueue(request)
55
+ rq.enqueue(cached_request)
56
+ rq.uncached_queue.should include(request)
57
+ rq.uncached_queue.should_not include(cached_request)
58
+ end
23
59
  end
24
60
 
25
61
  describe '.hydra' do
26
- pending
62
+ it 'returns the hydra contained in the Configuration' do
63
+ rq.hydra.should eql(Morpheus::Configuration.hydra)
64
+ end
27
65
  end
28
66
 
29
67
  describe '.run!' do
30
- pending
68
+ it 'queues each uncached request into the hydra' do
69
+ rq.enqueue(request)
70
+ rq.hydra.should_receive(:queue).with(request)
71
+ rq.run!
72
+ end
31
73
  end
32
74
 
33
75
  describe '.has_request?' do
34
- pending
76
+ it 'returns true if the request is in the queue' do
77
+ rq.enqueue(request)
78
+ rq.should have_request(request)
79
+ rq.should_not have_request(cached_request)
80
+ end
35
81
  end
36
82
 
37
83
  end
@@ -12,8 +12,7 @@ describe Morpheus::Request do
12
12
 
13
13
  describe '#cache_key' do
14
14
  it 'returns a hash of the array [method, url, params]' do
15
- key = [request.method, request.url, request.params].hash
16
- request.cache_key.should eql(key)
15
+ request.cache_key.should eql('ad2b05e950b4cf408f6980799d67b7c968044068')
17
16
  end
18
17
  end
19
18
 
@@ -1,75 +1,71 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Morpheus::Response do
4
-
5
- describe '#initialize' do
6
- pending
7
- end
4
+ let(:response) { Morpheus::Response.new(:code => 200, :headers => '', :body => '', :time => 0.3) }
8
5
 
9
6
  describe '#cached?' do
10
7
  context 'when the response is marked as cached' do
11
- before(:each) do
12
- @response = Morpheus::Response.new({ :code => 200, :headers => '', :body => '', :time => 0.3 }, true)
13
- end
8
+ let(:response) { Morpheus::Response.new({ :code => 200, :headers => '', :body => '', :time => 0.3 }, true) }
14
9
 
15
10
  it 'returns true' do
16
- @response.should be_cached
11
+ response.should be_cached
17
12
  end
18
13
  end
19
14
 
20
15
  context 'when the response is marked as not cached' do
21
- before(:each) do
22
- @response = Morpheus::Response.new({ :code => 200, :headers => '', :body => '', :time => 0.3 }, false)
23
- end
16
+ let(:response) { Morpheus::Response.new({ :code => 200, :headers => '', :body => '', :time => 0.3 }, false) }
24
17
 
25
18
  it 'returns false' do
26
- @response.should_not be_cached
19
+ response.should_not be_cached
27
20
  end
28
21
  end
29
22
 
30
23
  context 'when the response is not marked as cached or otherwise' do
31
- before(:each) do
32
- @response = Morpheus::Response.new(:code => 200, :headers => '', :body => '', :time => 0.3)
33
- end
34
-
35
24
  it 'returns false' do
36
- @response.should_not be_cached
25
+ response.should_not be_cached
37
26
  end
38
27
  end
39
28
  end
40
29
 
41
30
  describe '#tag_for_caching!' do
42
- pending
31
+ it 'sets the @tagged_for_caching instance variable to true' do
32
+ response.should_not be_tagged_for_caching
33
+ response.tag_for_caching!
34
+ response.should be_tagged_for_caching
35
+ end
43
36
  end
44
37
 
45
38
  describe '#tagged_for_caching?' do
46
- pending
39
+ it 'returns false as a default value' do
40
+ response.should_not be_tagged_for_caching
41
+ end
42
+
43
+ it 'returns true when a response has been tagged for caching' do
44
+ response.tag_for_caching!
45
+ response.should be_tagged_for_caching
46
+ end
47
47
  end
48
48
 
49
49
  describe '#respond_to?' do
50
- before(:each) do
51
- @typhoeus_response = Typhoeus::Response.new(:code => 200, :headers => '', :body => '', :time => 0.3)
52
- @response = Morpheus::Response.new(:code => 200, :headers => '', :body => '', :time => 0.3)
53
- end
50
+ let(:typhoeus_response) { Typhoeus::Response.new(:code => 200, :headers => '', :body => '', :time => 0.3) }
54
51
 
55
52
  it 'responds to all methods defined on itself' do
56
- @response.methods.reject { |method| method == :respond_to? }.each do |method|
57
- @response.should respond_to(method)
53
+ response.methods.reject { |method| method == :respond_to? }.each do |method|
54
+ response.should respond_to(method)
58
55
  end
59
56
  end
60
57
 
61
58
  it 'responds to all methods defined on the Typhoeus::Response object it wraps' do
62
- @typhoeus_response.methods.each do |method|
63
- @response.should respond_to(method)
59
+ typhoeus_response.methods.each do |method|
60
+ response.should respond_to(method)
64
61
  end
65
62
  end
66
63
  end
67
64
 
68
65
  describe '#method_missing' do
69
66
  it 'wraps a Typhoeus::Response object' do
70
- @response = Morpheus::Response.new
71
67
  Typhoeus::Response.new.methods.each do |method|
72
- @response.should respond_to(method.to_sym)
68
+ response.should respond_to(method.to_sym)
73
69
  end
74
70
  end
75
71
  end
@@ -3,70 +3,54 @@ require 'spec_helper'
3
3
  describe Morpheus::TypeCaster do
4
4
 
5
5
  describe '.cast' do
6
- context 'when the typecast_class is nil' do
7
- it 'casts "hello" to "hello"' do
8
- Morpheus::TypeCaster.cast('hello', nil).should eql('hello')
9
- end
10
-
11
- it 'casts "2011-04-10" to "2011-04-10"' do
12
- Morpheus::TypeCaster.cast('2011-04-10', nil).should eql('2011-04-10')
13
- end
6
+ let(:object) { Object.new }
14
7
 
15
- it 'cast "3" to "3"' do
16
- Morpheus::TypeCaster.cast('3', nil).should eql('3')
17
- end
18
-
19
- it 'casts "10-04-2011T05:00:00Z" to "10-04-2011T05:00:00Z"' do
20
- Morpheus::TypeCaster.cast('10-04-2011T05:00:00Z', nil).should eql('10-04-2011T05:00:00Z')
21
- end
22
-
23
- it 'casts "true" to "true"' do
24
- Morpheus::TypeCaster.cast('true', nil).should eql('true')
25
- end
26
-
27
- it 'casts 4 to 4' do
28
- Morpheus::TypeCaster.cast(4, nil).should eql(4)
29
- end
30
-
31
- it 'casts true to true' do
32
- Morpheus::TypeCaster.cast(true, nil).should eql(true)
33
- end
34
-
35
- it 'cast DateTime to DateTime' do
36
- Morpheus::TypeCaster.cast(DateTime.parse('10-04-2011T05:00:00Z'), nil).should eql(DateTime.parse('10-04-2011T05:00:00Z'))
37
- end
38
-
39
- it 'casts Date to Date' do
40
- Morpheus::TypeCaster.cast(Date.parse('2011-04-10'), nil).should eql(Date.parse('2011-04-10'))
41
- end
42
-
43
- it 'casts Time to Time' do
44
- Morpheus::TypeCaster.cast(Time.parse('10-04-2011T05:00:00Z'), nil).should eql(Time.parse('10-04-2011T05:00:00Z'))
8
+ context 'when the typecast_class is nil' do
9
+ it 'returns the given value unchanged' do
10
+ Morpheus::TypeCaster.cast(object, nil).should eql(object)
45
11
  end
46
12
  end
47
13
 
48
14
  context 'when the typecast_class is String' do
49
- pending
15
+ it 'delegates to parse_string with the given value' do
16
+ Morpheus::TypeCaster.should_receive(:parse_string).with(object)
17
+ Morpheus::TypeCaster.cast(object, :string)
18
+ end
50
19
  end
51
20
 
52
21
  context 'when the typecast_class is Integer' do
53
- pending
22
+ it 'delegates to parse_integer with the given value' do
23
+ Morpheus::TypeCaster.should_receive(:parse_integer).with(object)
24
+ Morpheus::TypeCaster.cast(object, :integer)
25
+ end
54
26
  end
55
27
 
56
28
  context 'when the typecast_class is DateTime' do
57
- pending
29
+ it 'delegates to parse_datetime with the given value' do
30
+ Morpheus::TypeCaster.should_receive(:parse_datetime).with(object)
31
+ Morpheus::TypeCaster.cast(object, :datetime)
32
+ end
58
33
  end
59
34
 
60
35
  context 'when the typecast_class is Date' do
61
- pending
36
+ it 'delegates to parse_date with the given value' do
37
+ Morpheus::TypeCaster.should_receive(:parse_date).with(object)
38
+ Morpheus::TypeCaster.cast(object, :date)
39
+ end
62
40
  end
63
41
 
64
42
  context 'when the typecast_class is Time' do
65
- pending
43
+ it 'delegates to parse_time with the given value' do
44
+ Morpheus::TypeCaster.should_receive(:parse_time).with(object)
45
+ Morpheus::TypeCaster.cast(object, :time)
46
+ end
66
47
  end
67
48
 
68
49
  context 'when the typecast_class is Boolean' do
69
- pending
50
+ it 'delegates to parse_boolean with the given value' do
51
+ Morpheus::TypeCaster.should_receive(:parse_boolean).with(object)
52
+ Morpheus::TypeCaster.cast(object, :boolean)
53
+ end
70
54
  end
71
55
 
72
56
  context 'when the typecast_class is unknown' do
@@ -116,7 +100,8 @@ describe Morpheus::TypeCaster do
116
100
  end
117
101
 
118
102
  it 'casts Time to "10-04-2011T05:00:00Z"' do
119
- Morpheus::TypeCaster.cast(Time.parse('10-04-2011T05:00:00Z'), :string).should eql('Sun Apr 10 05:00:00 UTC 2011')
103
+ time = Time.parse('10-04-2011T05:00:00Z')
104
+ Morpheus::TypeCaster.cast(time, :string).should eql(time.to_s)
120
105
  end
121
106
  end
122
107
 
@@ -158,7 +143,8 @@ describe Morpheus::TypeCaster do
158
143
  end
159
144
 
160
145
  it 'casts Date to 1302393600' do
161
- Morpheus::TypeCaster.cast(Date.parse('2011-04-10'), :integer).should eql(1302418800)
146
+ date = Date.parse('2011-04-10')
147
+ Morpheus::TypeCaster.cast(date, :integer).should eql(date.to_time.utc.to_i)
162
148
  end
163
149
 
164
150
  it 'casts Time to 1302411600' do
@@ -246,7 +232,8 @@ describe Morpheus::TypeCaster do
246
232
  end
247
233
 
248
234
  it 'casts Time to Date' do
249
- Morpheus::TypeCaster.cast(Time.parse('10-04-2011T05:00:00Z'), :date).should eql(Date.parse('10-04-2011T05:00:00Z'))
235
+ time = Time.parse('10-04-2011T05:00:00Z')
236
+ Morpheus::TypeCaster.cast(time, :date).should eql(time.to_time.to_date)
250
237
  end
251
238
  end
252
239
 
@@ -3,39 +3,127 @@ require 'spec_helper'
3
3
  describe Morpheus::UrlBuilder do
4
4
 
5
5
  describe '.find_one' do
6
- pending
6
+ let(:find_one) { Morpheus::UrlBuilder.find_one(Dog, 1) }
7
+
8
+ it 'returns a string matching "/plural_class_name/id"' do
9
+ find_one.should eql('/dogs/1')
10
+ end
7
11
  end
8
12
 
9
13
  describe '.find_some' do
10
- pending
14
+ let(:find_some) { Morpheus::UrlBuilder.find_some(Dog, [1,2,3]) }
15
+
16
+ it 'returns an array' do
17
+ find_some.should be_kind_of(Array)
18
+ end
19
+
20
+ context 'within the returned array' do
21
+ it 'contains a string matching "/plural_class_name"' do
22
+ find_some.should include('/dogs')
23
+ end
24
+
25
+ it 'contains an array containing a hash with key :ids' do
26
+ find_some.should include({ :ids => [1,2,3] })
27
+ end
28
+ end
11
29
  end
12
30
 
13
31
  describe '.find_all' do
14
- pending
32
+ let(:find_all) { Morpheus::UrlBuilder.find_all(Dog) }
33
+
34
+ it 'returns a string matching "/plural_class_name"' do
35
+ find_all.should eql('/dogs')
36
+ end
15
37
  end
16
38
 
17
39
  describe '.save' do
18
- pending
40
+ let(:parameters) { { :name => 'Fido' } }
41
+ let(:save) { Morpheus::UrlBuilder.save(Dog, 1, parameters) }
42
+
43
+ it 'returns an array' do
44
+ save.should be_kind_of(Array)
45
+ end
46
+
47
+ context 'within the returned array' do
48
+ context 'when there is an id' do
49
+ it 'contains a string matching "/plural_class_name/id"' do
50
+ save.should include('/dogs/1')
51
+ end
52
+ end
53
+
54
+ context 'when there is no id' do
55
+ let(:save) { Morpheus::UrlBuilder.save(Dog, nil, parameters) }
56
+
57
+ it 'contains a string matching "/plural_class_name"' do
58
+ save.should include('/dogs')
59
+ end
60
+ end
61
+
62
+ it 'contains the parameters passed in as arguments' do
63
+ save.should include(parameters)
64
+ end
65
+ end
19
66
  end
20
67
 
21
68
  describe '.belongs_to' do
22
- pending
69
+ let(:belongs_to) { Morpheus::UrlBuilder.belongs_to(Dog, 1) }
70
+
71
+ it 'returns a string matching "/plural_class_name/id"' do
72
+ belongs_to.should eql('/dogs/1')
73
+ end
23
74
  end
24
75
 
25
76
  describe '.has_one' do
26
- pending
77
+ let(:has_one) { Morpheus::UrlBuilder.has_one(Meeting, 1, Speaker) }
78
+
79
+ it 'returns a string matching "/plural_class_name/id/singular_foreign_class_name"' do
80
+ has_one.should eql('/meetings/1/speaker')
81
+ end
27
82
  end
28
83
 
29
84
  describe '.has_many' do
30
- pending
85
+ let(:has_many) { Morpheus::UrlBuilder.has_many(Meeting, 1, Attendee) }
86
+
87
+ it 'returns a string matching "/plural_class_name/id/plural_foreign_class_name"' do
88
+ has_many.should eql('/meetings/1/attendees')
89
+ end
31
90
  end
32
91
 
33
92
  describe '.relation' do
34
- pending
93
+ context 'when there are parameters' do
94
+ let(:relation) { Morpheus::UrlBuilder.relation(Dog) }
95
+
96
+ it 'returns a string matching "/plural_class_name"' do
97
+ relation.should eql('/dogs')
98
+ end
99
+ end
100
+
101
+ context 'when there are no parameters' do
102
+ let(:parameters) { { :name => 'Fido' } }
103
+ let(:relation) { Morpheus::UrlBuilder.relation(Dog, parameters) }
104
+
105
+ it 'returns an Array' do
106
+ relation.should be_kind_of(Array)
107
+ end
108
+
109
+ context 'within the returned array' do
110
+ it 'contains a string matching "/plural_class_name"' do
111
+ relation.should include('/dogs')
112
+ end
113
+
114
+ it 'contains the parameters that were passed in as arguments' do
115
+ relation.should include(parameters)
116
+ end
117
+ end
118
+ end
35
119
  end
36
120
 
37
121
  describe '.destroy' do
38
- pending
122
+ let(:destroy) { Morpheus::UrlBuilder.destroy(Dog, 1) }
123
+
124
+ it 'returns a string matching "/plural_class_name/id"' do
125
+ destroy.should eql('/dogs/1')
126
+ end
39
127
  end
40
128
 
41
129
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,13 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  ENV['RAILS_ENV'] = 'test'
3
3
 
4
+ if ENV['COVERAGE']
5
+ require 'simplecov'
6
+ SimpleCov.start do
7
+ add_filter '/spec/'
8
+ end
9
+ end
10
+
4
11
  require File.expand_path('../dummy/config/environment.rb', __FILE__)
5
12
  require 'rails/test_help'
6
13
  require 'rspec/rails'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: morpheus
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
4
+ hash: 1
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 8
10
- version: 0.3.8
9
+ - 9
10
+ version: 0.3.9
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ryan Moran
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-02-09 00:00:00 -08:00
18
+ date: 2012-02-22 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -146,38 +146,6 @@ dependencies:
146
146
  version: 2.8.1
147
147
  type: :development
148
148
  version_requirements: *id008
149
- - !ruby/object:Gem::Dependency
150
- name: rcov
151
- prerelease: false
152
- requirement: &id009 !ruby/object:Gem::Requirement
153
- none: false
154
- requirements:
155
- - - ~>
156
- - !ruby/object:Gem::Version
157
- hash: 45
158
- segments:
159
- - 0
160
- - 9
161
- - 11
162
- version: 0.9.11
163
- type: :development
164
- version_requirements: *id009
165
- - !ruby/object:Gem::Dependency
166
- name: autotest-standalone
167
- prerelease: false
168
- requirement: &id010 !ruby/object:Gem::Requirement
169
- none: false
170
- requirements:
171
- - - ~>
172
- - !ruby/object:Gem::Version
173
- hash: 57
174
- segments:
175
- - 4
176
- - 5
177
- - 9
178
- version: 4.5.9
179
- type: :development
180
- version_requirements: *id010
181
149
  description: RESTful API Client
182
150
  email:
183
151
  - ryan.moran@revolutionprep.com
@@ -191,6 +159,7 @@ files:
191
159
  - .autotest
192
160
  - .gitignore
193
161
  - .rspec
162
+ - .travis.yml
194
163
  - Gemfile
195
164
  - LICENSE.txt
196
165
  - README.md