morpheus 0.3.8 → 0.3.9

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/.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