amfetamine 0.2.9 → 0.2.11
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/.travis.yml +4 -0
- data/.vagrant +1 -0
- data/CHANGELOG +12 -0
- data/README.md +34 -14
- data/Rakefile +3 -8
- data/Vagrantfile +99 -0
- data/amfetamine.gemspec +3 -3
- data/lib/amfetamine/logger.rb +3 -2
- data/lib/amfetamine/version.rb +1 -1
- data/spec/amfetamine/base_spec.rb +40 -26
- data/spec/amfetamine/caching_spec.rb +6 -3
- data/spec/amfetamine/conditions_spec.rb +17 -7
- data/spec/amfetamine/relationships_spec.rb +4 -2
- data/spec/spec_helper.rb +7 -3
- metadata +46 -34
- data/spec/helpers/fakeweb_responses.rb +0 -120
data/.rspec
CHANGED
data/.travis.yml
ADDED
data/.vagrant
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"active":{"default":"830ee770-ad53-45c1-a747-f6c862a26f6e"}}
|
data/CHANGELOG
CHANGED
@@ -1,2 +1,14 @@
|
|
1
|
+
0.2.11
|
2
|
+
- Rewrote specs to be idempotent when randomized
|
3
|
+
- Fixed a lot of specs for travis in general
|
4
|
+
|
5
|
+
0.2.10
|
6
|
+
- Removed verbosity from tests
|
7
|
+
- Dropped support for Ruby 1.8.7
|
8
|
+
- Sourcecode is now available on github
|
9
|
+
|
10
|
+
0.2.9
|
11
|
+
- Cleaning up
|
12
|
+
|
1
13
|
0.2.8
|
2
14
|
- Attributes are now set dynamically. This OVERIDES anything you set on 'amfetamine_attributes'. This should reduce a lot of bloat.
|
data/README.md
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
Amfetamine, A REST object abstractavaganza
|
2
2
|
====================================
|
3
3
|
|
4
|
-
>
|
4
|
+
> Rest abstraction on steroids that makes shit go boom!
|
5
5
|
|
6
|
-
|
6
|
+
[![Build Status](https://secure.travis-ci.org/Exvo/amfetamine.png)](http://travis-ci.org/Exvo/amfetamine)
|
7
|
+
|
8
|
+
|
9
|
+
Amfetamine adds an ActiveModel like interface to your REST services with support for any HTTP(arty) client and caching using memcached.
|
10
|
+
|
11
|
+
Sometimes you just quickly need to wrap up a REST api without having to worry about persistancy or the data. And since you want caching …
|
12
|
+
|
13
|
+
Note that the cache invalidates only when local changes are made. You could use a distributed cache or, more easilly, set a TTL on Dalli.
|
7
14
|
|
8
15
|
Features
|
9
16
|
--------
|
@@ -16,9 +23,9 @@ It is still in beta and under heavy development. Some features:
|
|
16
23
|
* It has a lot of methods that you expect from ActiveModel objects. Find, all, save, create, new, destroy, update_attributes, update.
|
17
24
|
* It supports all validation methods ActiveModel provides, thanks to ActiveModel -red.
|
18
25
|
* You can fully configure your memcached client, it uses Dalli.
|
19
|
-
* Although the client has been tested and build with JSON, it should support XML as well.
|
26
|
+
* Although the client has been tested and build with JSON, it should support XML or Bson as well.
|
20
27
|
* It supports single nested resources for now.
|
21
|
-
* It supports conditions in the all
|
28
|
+
* It supports conditions in the all and find method, just provide a :conditions hash like you're used to.
|
22
29
|
* Supports global HTTP and Memcached client as well as per object overriding.
|
23
30
|
* If a request passes validation on client side and not on service side, the client properly sets error messages from the service.
|
24
31
|
* Provides testing helpers
|
@@ -28,16 +35,17 @@ Setup
|
|
28
35
|
=====
|
29
36
|
|
30
37
|
### 1)
|
31
|
-
Add it to your gemfile
|
38
|
+
Add it to your gemfile:
|
32
39
|
|
33
40
|
```ruby
|
34
41
|
gem 'amfetamine'
|
35
42
|
```
|
36
43
|
|
37
44
|
### 2)
|
38
|
-
Create an initializer
|
45
|
+
Create an initializer, note that you can also do this on a per object basis:
|
39
46
|
|
40
47
|
```ruby
|
48
|
+
#config/initializers/amfetamine_config.rb
|
41
49
|
Amfetamine::Config.configure do |config|
|
42
50
|
config.memcached_instance = [HOST:PORT, OPTION1,OPTION2] || HOST:PORT
|
43
51
|
config.rest_client = REST_CLIENT
|
@@ -53,9 +61,7 @@ Configure your object:
|
|
53
61
|
|
54
62
|
```ruby
|
55
63
|
class Banana < Amfetamine::Base
|
56
|
-
#
|
57
|
-
amfetamine_attributes :name, :shape, :color, :created_at, :updated_at
|
58
|
-
|
64
|
+
# Right now methods are set dynamically, the older syntax is deprecated. Will move to an or/or situation.
|
59
65
|
# OPTIONAL: Per object configuration
|
60
66
|
amfetamine_configure memcached_instance: 'localhost:11211',
|
61
67
|
rest_client: BananaRestclient
|
@@ -168,29 +174,43 @@ end
|
|
168
174
|
|
169
175
|
TODO
|
170
176
|
|
171
|
-
Future Features
|
172
|
-
|
177
|
+
Future Features & TODO
|
178
|
+
======================
|
173
179
|
|
174
180
|
* Smarter caching
|
175
181
|
* Better support for custom methods
|
176
|
-
* Support for
|
182
|
+
* Support for Redis
|
177
183
|
* Automatic determining of attributes and validations
|
178
184
|
* Supporting any amount of nested relationships
|
179
185
|
* Supporting interobject relationship (database versus service)
|
180
186
|
* More callbacks
|
181
187
|
* Better typecasting, it doesn't always work.
|
188
|
+
* Asynchronous requests
|
189
|
+
* Started out a lot smaller, metaprogramming needs to go composited.
|
182
190
|
|
183
191
|
Licence
|
184
192
|
=======
|
185
193
|
|
186
|
-
|
194
|
+
|
195
|
+
Copyright (C) 2012 Exvo.com, Timon Vonk
|
196
|
+
|
197
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
198
|
+
|
199
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
200
|
+
|
201
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
187
202
|
|
188
203
|
Contributing
|
189
204
|
============
|
190
205
|
|
191
|
-
|
206
|
+
* Fork
|
207
|
+
* Test
|
208
|
+
* Code
|
209
|
+
* Test
|
210
|
+
* Pull Request
|
192
211
|
|
193
212
|
Contributors
|
194
213
|
============
|
195
214
|
|
196
215
|
* Timon Vonk
|
216
|
+
* Matt Bridges
|
data/Rakefile
CHANGED
@@ -1,11 +1,6 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
+
require 'rspec/core/rake_task'
|
2
3
|
|
3
|
-
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
4
5
|
|
5
|
-
task :
|
6
|
-
sh "bundle"
|
7
|
-
end
|
8
|
-
|
9
|
-
task :rspec do
|
10
|
-
sh "rspec spec"
|
11
|
-
end
|
6
|
+
task :default => [:spec]
|
data/Vagrantfile
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
Vagrant::Config.run do |config|
|
5
|
+
# All Vagrant configuration is done here. The most common configuration
|
6
|
+
# options are documented and commented below. For a complete reference,
|
7
|
+
# please see the online documentation at vagrantup.com.
|
8
|
+
|
9
|
+
# Every Vagrant virtual environment requires a box to build off of.
|
10
|
+
config.vm.box = "base"
|
11
|
+
|
12
|
+
# The url from where the 'config.vm.box' box will be fetched if it
|
13
|
+
# doesn't already exist on the user's system.
|
14
|
+
# config.vm.box_url = "http://domain.com/path/to/above.box"
|
15
|
+
|
16
|
+
# Boot with a GUI so you can see the screen. (Default is headless)
|
17
|
+
# config.vm.boot_mode = :gui
|
18
|
+
|
19
|
+
# Assign this VM to a host-only network IP, allowing you to access it
|
20
|
+
# via the IP. Host-only networks can talk to the host machine as well as
|
21
|
+
# any other machines on the same network, but cannot be accessed (through this
|
22
|
+
# network interface) by any external networks.
|
23
|
+
# config.vm.network :hostonly, "192.168.33.10"
|
24
|
+
|
25
|
+
# Assign this VM to a bridged network, allowing you to connect directly to a
|
26
|
+
# network using the host's network device. This makes the VM appear as another
|
27
|
+
# physical device on your network.
|
28
|
+
# config.vm.network :bridged
|
29
|
+
|
30
|
+
# Forward a port from the guest to the host, which allows for outside
|
31
|
+
# computers to access the VM, whereas host only networking does not.
|
32
|
+
# config.vm.forward_port 80, 8080
|
33
|
+
|
34
|
+
# Share an additional folder to the guest VM. The first argument is
|
35
|
+
# an identifier, the second is the path on the guest to mount the
|
36
|
+
# folder, and the third is the path on the host to the actual folder.
|
37
|
+
# config.vm.share_folder "v-data", "/vagrant_data", "../data"
|
38
|
+
|
39
|
+
# Enable provisioning with Puppet stand alone. Puppet manifests
|
40
|
+
# are contained in a directory path relative to this Vagrantfile.
|
41
|
+
# You will need to create the manifests directory and a manifest in
|
42
|
+
# the file base.pp in the manifests_path directory.
|
43
|
+
#
|
44
|
+
# An example Puppet manifest to provision the message of the day:
|
45
|
+
#
|
46
|
+
# # group { "puppet":
|
47
|
+
# # ensure => "present",
|
48
|
+
# # }
|
49
|
+
# #
|
50
|
+
# # File { owner => 0, group => 0, mode => 0644 }
|
51
|
+
# #
|
52
|
+
# # file { '/etc/motd':
|
53
|
+
# # content => "Welcome to your Vagrant-built virtual machine!
|
54
|
+
# # Managed by Puppet.\n"
|
55
|
+
# # }
|
56
|
+
#
|
57
|
+
# config.vm.provision :puppet do |puppet|
|
58
|
+
# puppet.manifests_path = "manifests"
|
59
|
+
# puppet.manifest_file = "base.pp"
|
60
|
+
# end
|
61
|
+
|
62
|
+
# Enable provisioning with chef solo, specifying a cookbooks path, roles
|
63
|
+
# path, and data_bags path (all relative to this Vagrantfile), and adding
|
64
|
+
# some recipes and/or roles.
|
65
|
+
#
|
66
|
+
# config.vm.provision :chef_solo do |chef|
|
67
|
+
# chef.cookbooks_path = "../my-recipes/cookbooks"
|
68
|
+
# chef.roles_path = "../my-recipes/roles"
|
69
|
+
# chef.data_bags_path = "../my-recipes/data_bags"
|
70
|
+
# chef.add_recipe "mysql"
|
71
|
+
# chef.add_role "web"
|
72
|
+
#
|
73
|
+
# # You may also specify custom JSON attributes:
|
74
|
+
# chef.json = { :mysql_password => "foo" }
|
75
|
+
# end
|
76
|
+
|
77
|
+
# Enable provisioning with chef server, specifying the chef server URL,
|
78
|
+
# and the path to the validation key (relative to this Vagrantfile).
|
79
|
+
#
|
80
|
+
# The Opscode Platform uses HTTPS. Substitute your organization for
|
81
|
+
# ORGNAME in the URL and validation key.
|
82
|
+
#
|
83
|
+
# If you have your own Chef Server, use the appropriate URL, which may be
|
84
|
+
# HTTP instead of HTTPS depending on your configuration. Also change the
|
85
|
+
# validation key to validation.pem.
|
86
|
+
#
|
87
|
+
# config.vm.provision :chef_client do |chef|
|
88
|
+
# chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
|
89
|
+
# chef.validation_key_path = "ORGNAME-validator.pem"
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# If you're using the Opscode platform, your validator client is
|
93
|
+
# ORGNAME-validator, replacing ORGNAME with your organization name.
|
94
|
+
#
|
95
|
+
# IF you have your own Chef Server, the default validation client name is
|
96
|
+
# chef-validator, unless you changed the configuration.
|
97
|
+
#
|
98
|
+
# chef.validation_client_name = "ORGNAME-validator"
|
99
|
+
end
|
data/amfetamine.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.authors = ["Timon Vonk"]
|
9
9
|
s.email = ["timon@exvo.com"]
|
10
10
|
s.homepage = "http://www.github.com/exvo/amfetamine"
|
11
|
-
s.summary = %q{
|
12
|
-
s.description = %q{
|
11
|
+
s.summary = %q{REST object abstraction on steroids the makes shit go boom!}
|
12
|
+
s.description = %q{Provides an interface to REST apis with objects and a cache. Zero effort!}
|
13
13
|
|
14
14
|
s.rubyforge_project = "amfetamine"
|
15
15
|
|
@@ -22,12 +22,12 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.add_development_dependency "rspec"
|
23
23
|
s.add_development_dependency "guard"
|
24
24
|
s.add_development_dependency "guard-rspec"
|
25
|
-
#s.add_development_dependency "growl_notify"
|
26
25
|
s.add_development_dependency "ruby_gntp"
|
27
26
|
s.add_development_dependency "httparty"
|
28
27
|
s.add_development_dependency "fakeweb"
|
29
28
|
s.add_development_dependency "simplecov"
|
30
29
|
s.add_development_dependency "simplecov-rcov"
|
30
|
+
s.add_development_dependency "pry"
|
31
31
|
|
32
32
|
|
33
33
|
# Runtime dependencies
|
data/lib/amfetamine/logger.rb
CHANGED
@@ -8,10 +8,11 @@ module Amfetamine
|
|
8
8
|
args = "[Amfetamine] #{args.to_s}"
|
9
9
|
if defined?(Rails)
|
10
10
|
Rails.logger.send(method,args)
|
11
|
+
# Yeah, temporarilly :-))
|
11
12
|
elsif defined?(Merb)
|
12
13
|
Merb.logger.send(method,args)
|
13
|
-
|
14
|
-
|
14
|
+
else
|
15
|
+
puts args
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
data/lib/amfetamine/version.rb
CHANGED
@@ -46,7 +46,8 @@ describe Amfetamine::Base do
|
|
46
46
|
|
47
47
|
it "should return nil if object not found" do
|
48
48
|
lambda {
|
49
|
-
|
49
|
+
Dummy.prevent_external_connections! do |r|
|
50
|
+
r.get(:code => 404) {}
|
50
51
|
Dummy.find(dummy.id * 2).should be_nil
|
51
52
|
end
|
52
53
|
}.should raise_exception(Amfetamine::RecordNotFound)
|
@@ -59,7 +60,8 @@ describe Amfetamine::Base do
|
|
59
60
|
dummy.instance_variable_set('@notsaved', false)
|
60
61
|
dummy2.instance_variable_set('@notsaved', false)
|
61
62
|
|
62
|
-
|
63
|
+
Dummy.prevent_external_connections! do |r|
|
64
|
+
r.get {[dummy,dummy2]}
|
63
65
|
dummies = Dummy.all
|
64
66
|
end
|
65
67
|
|
@@ -69,35 +71,35 @@ describe Amfetamine::Base do
|
|
69
71
|
end
|
70
72
|
|
71
73
|
it "should return empty array if objects are not present" do
|
72
|
-
|
73
|
-
|
74
|
-
dummies = Dummy.all
|
75
|
-
end
|
74
|
+
Dummy.prevent_external_connections! do |r|
|
75
|
+
r.get(:code => 200) {[]}
|
76
76
|
|
77
|
-
|
77
|
+
Dummy.all.should be_empty
|
78
|
+
end
|
78
79
|
end
|
79
80
|
end
|
80
81
|
|
81
82
|
context "#create" do
|
82
83
|
it "should create an object if data is correct" do
|
83
|
-
|
84
|
-
|
84
|
+
Dummy.prevent_external_connections! do |r|
|
85
|
+
r.post(:code => 201) {}
|
86
|
+
|
85
87
|
new_dummy = Dummy.create({:title => 'test', :description => 'blabla'})
|
88
|
+
new_dummy.should be_a(Dummy)
|
89
|
+
new_dummy.should_not be_new
|
90
|
+
new_dummy.should be_cached
|
86
91
|
end
|
87
|
-
new_dummy.should be_a(Dummy)
|
88
|
-
new_dummy.should_not be_new
|
89
|
-
puts new_dummy.cache_key
|
90
|
-
new_dummy.should be_cached
|
91
92
|
end
|
92
93
|
|
93
94
|
it "should return errors if data is incorrect" do
|
94
|
-
|
95
|
-
|
95
|
+
Dummy.prevent_external_connections! do |r|
|
96
|
+
r.post(:code => 422) {{:description => ['can\'t be blank']}}
|
96
97
|
new_dummy = Dummy.create({:title => 'test'})
|
98
|
+
new_dummy.should be_new
|
99
|
+
new_dummy.errors.messages.should eq({:description => ['can\'t be blank']})
|
100
|
+
new_dummy.should_not be_cached
|
97
101
|
end
|
98
|
-
|
99
|
-
new_dummy.errors.messages.should eq({:description => ['can\'t be blank']})
|
100
|
-
new_dummy.should_not be_cached
|
102
|
+
|
101
103
|
end
|
102
104
|
end
|
103
105
|
|
@@ -107,8 +109,9 @@ describe Amfetamine::Base do
|
|
107
109
|
end
|
108
110
|
|
109
111
|
it "should update if response is succesful" do
|
110
|
-
Dummy.prevent_external_connections! do |
|
111
|
-
|
112
|
+
Dummy.prevent_external_connections! do |r|
|
113
|
+
r.put {}
|
114
|
+
|
112
115
|
dummy.update_attributes({:title => 'zomg'})
|
113
116
|
end
|
114
117
|
|
@@ -118,9 +121,12 @@ describe Amfetamine::Base do
|
|
118
121
|
end
|
119
122
|
|
120
123
|
it "should show errors if response is not succesful" do
|
121
|
-
|
124
|
+
Dummy.prevent_external_connections! do |r|
|
125
|
+
r.put(:code => 422) { [:title => ['can\'t be blank']]}
|
126
|
+
|
122
127
|
dummy.update_attributes({:title => ''})
|
123
128
|
end
|
129
|
+
|
124
130
|
dummy.should_not be_new
|
125
131
|
dummy.errors.messages.should eq({:title => ['can\'t be blank']})
|
126
132
|
end
|
@@ -133,14 +139,18 @@ describe Amfetamine::Base do
|
|
133
139
|
end
|
134
140
|
|
135
141
|
context "#save" do
|
142
|
+
let(:dummy2) { dummy.dup}
|
136
143
|
before(:each) do
|
137
144
|
dummy.send(:notsaved=, true)
|
145
|
+
dummy2 = dummy.dup
|
146
|
+
dummy.send(:id=, nil)
|
138
147
|
end
|
139
148
|
|
140
149
|
it "should update the id if data is received from post" do
|
141
150
|
old_id = dummy.id
|
142
|
-
|
143
|
-
|
151
|
+
Dummy.prevent_external_connections! do |r|
|
152
|
+
r.post(code:201) { dummy2 }
|
153
|
+
|
144
154
|
dummy.save
|
145
155
|
end
|
146
156
|
dummy.id.should == old_id
|
@@ -151,7 +161,8 @@ describe Amfetamine::Base do
|
|
151
161
|
dummy.send(:notsaved=, false)
|
152
162
|
old_id = dummy.id
|
153
163
|
dummy.title = "BLABLABLA"
|
154
|
-
|
164
|
+
Dummy.prevent_external_connections! do |r|
|
165
|
+
r.put {dummy}
|
155
166
|
dummy.title = "BLABLABLA"
|
156
167
|
dummy.save
|
157
168
|
end
|
@@ -167,16 +178,19 @@ describe Amfetamine::Base do
|
|
167
178
|
end
|
168
179
|
|
169
180
|
it "should delete the object if response is succesful" do
|
170
|
-
|
181
|
+
Dummy.prevent_external_connections! do |r|
|
182
|
+
r.delete {}
|
171
183
|
dummy.destroy
|
172
184
|
end
|
185
|
+
|
173
186
|
dummy.should be_new
|
174
187
|
dummy.id.should be_nil
|
175
188
|
dummy.should_not be_cached
|
176
189
|
end
|
177
190
|
|
178
191
|
it "should return false if delete failed" do
|
179
|
-
|
192
|
+
Dummy.prevent_external_connections! do |r|
|
193
|
+
r.delete(code: 422) {}
|
180
194
|
dummy.destroy
|
181
195
|
end
|
182
196
|
dummy.should_not be_new
|
@@ -5,7 +5,8 @@ describe Amfetamine::Cache do
|
|
5
5
|
dummy = build(:dummy)
|
6
6
|
dummy2 = build(:dummy)
|
7
7
|
dummies = nil
|
8
|
-
|
8
|
+
Dummy.prevent_external_connections! do |r|
|
9
|
+
r.get { [dummy, dummy2]}
|
9
10
|
dummies = Dummy.all
|
10
11
|
end
|
11
12
|
dummies_no_request = Dummy.all
|
@@ -15,7 +16,8 @@ describe Amfetamine::Cache do
|
|
15
16
|
it "should return same data after find request has been made" do
|
16
17
|
dummy = build(:dummy)
|
17
18
|
return_dummy = nil
|
18
|
-
|
19
|
+
Dummy.prevent_external_connections! do |r|
|
20
|
+
r.get { dummy }
|
19
21
|
return_dummy = Dummy.find(dummy.id)
|
20
22
|
end
|
21
23
|
dummy_no_request = Dummy.find(dummy.id)
|
@@ -26,7 +28,8 @@ describe Amfetamine::Cache do
|
|
26
28
|
dummy = build(:dummy)
|
27
29
|
dummy.instance_variable_set('@notsaved', false)
|
28
30
|
dummy.title = 'blabla'
|
29
|
-
|
31
|
+
Dummy.prevent_external_connections! do |r|
|
32
|
+
r.put {}
|
30
33
|
dummy.save
|
31
34
|
end
|
32
35
|
dummy2 = Dummy.find(dummy.id)
|
@@ -2,6 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe "Amfetamine REST Helpers with conditions" do
|
4
4
|
it "should work regular #all" do
|
5
|
+
# TODO: Throw away and rewrite. Pfft.
|
5
6
|
Dummy.cache.flush # Just to be uber sure
|
6
7
|
|
7
8
|
query = {:title => 'Dummy'}
|
@@ -9,21 +10,26 @@ describe "Amfetamine REST Helpers with conditions" do
|
|
9
10
|
dummy.instance_variable_set('@notsaved',false)
|
10
11
|
|
11
12
|
result = nil
|
12
|
-
|
13
|
+
|
14
|
+
Dummy.prevent_external_connections! do |rc|
|
15
|
+
rc.get { [dummy]}
|
13
16
|
result = Dummy.all(:conditions => query)
|
14
17
|
end
|
18
|
+
|
15
19
|
result2 = Dummy.all(:conditions => query) # No errors raised means it got it from the cache
|
16
20
|
result.should == result2
|
17
21
|
result.should include(dummy)
|
22
|
+
|
18
23
|
Dummy.prevent_external_connections! do |resource|
|
19
24
|
resource.delete {}
|
20
25
|
dummy.destroy
|
21
26
|
end
|
22
27
|
|
23
|
-
lambda {Dummy.all(:conditions => query) }.should raise_exception
|
28
|
+
lambda {Dummy.all(:conditions => query) }.should raise_exception
|
24
29
|
end
|
25
30
|
|
26
31
|
it "should work with nested resource #all" do
|
32
|
+
# TODO: Throw away and rewrite
|
27
33
|
Dummy.cache.flush # Just to be uber sure
|
28
34
|
Child.cache.flush
|
29
35
|
|
@@ -36,7 +42,8 @@ describe "Amfetamine REST Helpers with conditions" do
|
|
36
42
|
child.instance_variable_set('@notsaved',false)
|
37
43
|
|
38
44
|
result = nil
|
39
|
-
|
45
|
+
Child.prevent_external_connections! do |r|
|
46
|
+
r.get(path: "/dummies/#{dummy.id}/children") {[child]}
|
40
47
|
result = dummy.children.all(:conditions => query)
|
41
48
|
end
|
42
49
|
result2 = dummy.children.all(:conditions => query) # No errors raised means it got it from the cache
|
@@ -44,13 +51,14 @@ describe "Amfetamine REST Helpers with conditions" do
|
|
44
51
|
result.should include(child)
|
45
52
|
|
46
53
|
|
47
|
-
|
54
|
+
Child.prevent_external_connections! do |r|
|
55
|
+
r.delete {}
|
48
56
|
child.destroy
|
49
57
|
end
|
50
58
|
|
51
59
|
child.should_not be_cached
|
52
60
|
|
53
|
-
lambda {dummy.children.all(:conditions => query, :force => true) }.should raise_exception
|
61
|
+
lambda {dummy.children.all(:conditions => query, :force => true) }.should raise_exception
|
54
62
|
end
|
55
63
|
|
56
64
|
it "should work with normal resource #find" do
|
@@ -92,7 +100,8 @@ describe "Amfetamine REST Helpers with conditions" do
|
|
92
100
|
child.instance_variable_set('@notsaved',false)
|
93
101
|
|
94
102
|
result = nil
|
95
|
-
|
103
|
+
Child.prevent_external_connections! do |r|
|
104
|
+
r.get { child }
|
96
105
|
result = dummy.children.find(dummy.id, :conditions => query)
|
97
106
|
end
|
98
107
|
|
@@ -101,7 +110,8 @@ describe "Amfetamine REST Helpers with conditions" do
|
|
101
110
|
result2 = dummy.children.find(dummy.id, :conditions => query)
|
102
111
|
result2.should == result
|
103
112
|
|
104
|
-
|
113
|
+
Child.prevent_external_connections! do |r|
|
114
|
+
r.delete {}
|
105
115
|
child.destroy
|
106
116
|
end
|
107
117
|
|
@@ -58,12 +58,14 @@ describe Amfetamine::Relationships do
|
|
58
58
|
it "should be possible to get all children if not in memory" do
|
59
59
|
Dummy.cache.flush
|
60
60
|
new_dummy = nil
|
61
|
-
|
61
|
+
Dummy.prevent_external_connections! do |r|
|
62
|
+
r.get { dummy }
|
62
63
|
new_dummy = Dummy.find(dummy.id)
|
63
64
|
end
|
64
65
|
|
65
66
|
children = nil
|
66
|
-
|
67
|
+
Dummy.prevent_external_connections! do |r|
|
68
|
+
r.get { [child] }
|
67
69
|
children = new_dummy.children.all
|
68
70
|
end
|
69
71
|
children.should include(child)
|
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
require 'simplecov'
|
2
2
|
require 'simplecov-rcov'
|
3
|
-
|
4
|
-
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
if ENV['COVERAGE'] && (RUBY_ENGINE == "ruby")
|
6
|
+
SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
|
7
|
+
SimpleCov.start
|
8
|
+
end
|
5
9
|
|
6
10
|
require File.expand_path("../../lib/amfetamine.rb", __FILE__)
|
7
11
|
require 'helpers/active_model_lint'
|
@@ -12,10 +16,10 @@ require 'dummy/child'
|
|
12
16
|
require 'dummy/dummy'
|
13
17
|
|
14
18
|
require 'fakeweb'
|
15
|
-
require 'helpers/fakeweb_responses'
|
16
19
|
require 'json'
|
17
20
|
|
18
21
|
#Fakeweb to stub server responses, still want to to integration tests on the rest client
|
22
|
+
FakeWeb.allow_net_connect = false
|
19
23
|
def build(object)
|
20
24
|
{
|
21
25
|
:dummy => lambda { Dummy.new({:title => 'Dummy', :description => 'Crash me!', :id => Dummy.children.length + 1})},
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: amfetamine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.11
|
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: 2012-
|
12
|
+
date: 2012-07-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70139283682680 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70139283682680
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: guard
|
27
|
-
requirement: &
|
27
|
+
requirement: &70139283682240 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70139283682240
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: guard-rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &70139283681740 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70139283681740
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: ruby_gntp
|
49
|
-
requirement: &
|
49
|
+
requirement: &70139283681100 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70139283681100
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: httparty
|
60
|
-
requirement: &
|
60
|
+
requirement: &70139283680460 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70139283680460
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: fakeweb
|
71
|
-
requirement: &
|
71
|
+
requirement: &70139283679920 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70139283679920
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: simplecov
|
82
|
-
requirement: &
|
82
|
+
requirement: &70139283679500 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70139283679500
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: simplecov-rcov
|
93
|
-
requirement: &
|
93
|
+
requirement: &70139283678960 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,21 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70139283678960
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: pry
|
104
|
+
requirement: &70139283678380 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *70139283678380
|
102
113
|
- !ruby/object:Gem::Dependency
|
103
114
|
name: dalli
|
104
|
-
requirement: &
|
115
|
+
requirement: &70139283677660 !ruby/object:Gem::Requirement
|
105
116
|
none: false
|
106
117
|
requirements:
|
107
118
|
- - ! '>='
|
@@ -109,10 +120,10 @@ dependencies:
|
|
109
120
|
version: '0'
|
110
121
|
type: :runtime
|
111
122
|
prerelease: false
|
112
|
-
version_requirements: *
|
123
|
+
version_requirements: *70139283677660
|
113
124
|
- !ruby/object:Gem::Dependency
|
114
125
|
name: activesupport
|
115
|
-
requirement: &
|
126
|
+
requirement: &70139283676700 !ruby/object:Gem::Requirement
|
116
127
|
none: false
|
117
128
|
requirements:
|
118
129
|
- - ! '>='
|
@@ -120,10 +131,10 @@ dependencies:
|
|
120
131
|
version: '0'
|
121
132
|
type: :runtime
|
122
133
|
prerelease: false
|
123
|
-
version_requirements: *
|
134
|
+
version_requirements: *70139283676700
|
124
135
|
- !ruby/object:Gem::Dependency
|
125
136
|
name: activemodel
|
126
|
-
requirement: &
|
137
|
+
requirement: &70139283676120 !ruby/object:Gem::Requirement
|
127
138
|
none: false
|
128
139
|
requirements:
|
129
140
|
- - ! '>='
|
@@ -131,10 +142,10 @@ dependencies:
|
|
131
142
|
version: '0'
|
132
143
|
type: :runtime
|
133
144
|
prerelease: false
|
134
|
-
version_requirements: *
|
145
|
+
version_requirements: *70139283676120
|
135
146
|
- !ruby/object:Gem::Dependency
|
136
147
|
name: json
|
137
|
-
requirement: &
|
148
|
+
requirement: &70139283675160 !ruby/object:Gem::Requirement
|
138
149
|
none: false
|
139
150
|
requirements:
|
140
151
|
- - ! '>='
|
@@ -142,10 +153,10 @@ dependencies:
|
|
142
153
|
version: '0'
|
143
154
|
type: :runtime
|
144
155
|
prerelease: false
|
145
|
-
version_requirements: *
|
156
|
+
version_requirements: *70139283675160
|
146
157
|
- !ruby/object:Gem::Dependency
|
147
158
|
name: rake
|
148
|
-
requirement: &
|
159
|
+
requirement: &70139283674080 !ruby/object:Gem::Requirement
|
149
160
|
none: false
|
150
161
|
requirements:
|
151
162
|
- - ! '>='
|
@@ -153,8 +164,8 @@ dependencies:
|
|
153
164
|
version: '0'
|
154
165
|
type: :runtime
|
155
166
|
prerelease: false
|
156
|
-
version_requirements: *
|
157
|
-
description:
|
167
|
+
version_requirements: *70139283674080
|
168
|
+
description: Provides an interface to REST apis with objects and a cache. Zero effort!
|
158
169
|
email:
|
159
170
|
- timon@exvo.com
|
160
171
|
executables: []
|
@@ -164,10 +175,13 @@ files:
|
|
164
175
|
- .gitignore
|
165
176
|
- .rspec
|
166
177
|
- .rvmrc
|
178
|
+
- .travis.yml
|
179
|
+
- .vagrant
|
167
180
|
- CHANGELOG
|
168
181
|
- Gemfile
|
169
182
|
- README.md
|
170
183
|
- Rakefile
|
184
|
+
- Vagrantfile
|
171
185
|
- amfetamine.gemspec
|
172
186
|
- lib/amfetamine.rb
|
173
187
|
- lib/amfetamine/base.rb
|
@@ -198,7 +212,6 @@ files:
|
|
198
212
|
- spec/dummy/dummy.rb
|
199
213
|
- spec/dummy/dummy_rest_client.rb
|
200
214
|
- spec/helpers/active_model_lint.rb
|
201
|
-
- spec/helpers/fakeweb_responses.rb
|
202
215
|
- spec/spec_helper.rb
|
203
216
|
homepage: http://www.github.com/exvo/amfetamine
|
204
217
|
licenses: []
|
@@ -214,7 +227,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
214
227
|
version: '0'
|
215
228
|
segments:
|
216
229
|
- 0
|
217
|
-
hash:
|
230
|
+
hash: 460912657760222225
|
218
231
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
219
232
|
none: false
|
220
233
|
requirements:
|
@@ -223,13 +236,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
223
236
|
version: '0'
|
224
237
|
segments:
|
225
238
|
- 0
|
226
|
-
hash:
|
239
|
+
hash: 460912657760222225
|
227
240
|
requirements: []
|
228
241
|
rubyforge_project: amfetamine
|
229
242
|
rubygems_version: 1.8.16
|
230
243
|
signing_key:
|
231
244
|
specification_version: 3
|
232
|
-
summary:
|
245
|
+
summary: REST object abstraction on steroids the makes shit go boom!
|
233
246
|
test_files:
|
234
247
|
- spec/amfetamine/base_spec.rb
|
235
248
|
- spec/amfetamine/caching_spec.rb
|
@@ -246,5 +259,4 @@ test_files:
|
|
246
259
|
- spec/dummy/dummy.rb
|
247
260
|
- spec/dummy/dummy_rest_client.rb
|
248
261
|
- spec/helpers/active_model_lint.rb
|
249
|
-
- spec/helpers/fakeweb_responses.rb
|
250
262
|
- spec/spec_helper.rb
|
@@ -1,120 +0,0 @@
|
|
1
|
-
FakeWeb.allow_net_connect = false # No real connects
|
2
|
-
|
3
|
-
# I know, duplication, right? just lazy.
|
4
|
-
|
5
|
-
def stub_single_response(object)
|
6
|
-
FakeWeb.register_uri(:get, %r|http://test\.local/dummies/#{object.id}|, :body => { :dummy => object.to_hash }.to_json, :content_type => 'application/json')
|
7
|
-
yield
|
8
|
-
FakeWeb.clean_registry
|
9
|
-
end
|
10
|
-
|
11
|
-
def stub_all_response(*objects)
|
12
|
-
#json = JSON.generate(objects.inject([]) { |acc,o| acc << })
|
13
|
-
json = objects.inject([]) { |acc, o| acc << o.as_json(:root => o.class.model_name.element, :methods => [:id]) }.to_json
|
14
|
-
FakeWeb.register_uri(:get, "http://test.local/dummies", :body => json, :content_type => 'application/json')
|
15
|
-
yield
|
16
|
-
FakeWeb.clean_registry
|
17
|
-
end
|
18
|
-
|
19
|
-
def stub_all_nil_response
|
20
|
-
FakeWeb.register_uri(:get, 'http://test.local/dummies', :body => [].to_json, :content_type => 'application/json')
|
21
|
-
yield
|
22
|
-
FakeWeb.clean_registry
|
23
|
-
end
|
24
|
-
|
25
|
-
def stub_nil_response
|
26
|
-
FakeWeb.register_uri(:get, %r|http://test\.local/dummies/\d*|, :body => nil, :status => ["404", "Not Found"], :content_type => 'application/json')
|
27
|
-
yield
|
28
|
-
FakeWeb.clean_registry
|
29
|
-
end
|
30
|
-
|
31
|
-
def stub_post_response(object=nil)
|
32
|
-
path = '/dummies'
|
33
|
-
if object
|
34
|
-
path = object.rest_path
|
35
|
-
if object.belongs_to_relationship?
|
36
|
-
path = object.belongs_to_relationships.first.rest_path
|
37
|
-
end
|
38
|
-
end
|
39
|
-
FakeWeb.register_uri(:post, "http://test.local#{path}", :body => object ? object.to_json : nil, :status => ["201", "Object created"], :content_type => 'application/json')
|
40
|
-
yield
|
41
|
-
FakeWeb.clean_registry
|
42
|
-
end
|
43
|
-
|
44
|
-
def stub_post_errornous_response
|
45
|
-
FakeWeb.register_uri(:post, "http://test.local/dummies", :body => {:description => 'can\'t be empty'}.to_json, :status => ["422", "Validation Errors"], :content_type => 'application/json')
|
46
|
-
yield
|
47
|
-
FakeWeb.clean_registry
|
48
|
-
end
|
49
|
-
|
50
|
-
def stub_update_response(object=nil)
|
51
|
-
FakeWeb.register_uri(:put, %r|http://test\.local/dummies/\d*|, :body => object ? object.to_json : nil, :status => ["200", "Object updated"], :content_type => 'application/json')
|
52
|
-
yield
|
53
|
-
FakeWeb.clean_registry
|
54
|
-
end
|
55
|
-
|
56
|
-
def stub_update_errornous_response
|
57
|
-
FakeWeb.register_uri(:put, %r|http://test\.local/dummies/\d*|, :body => {:title => 'can\'t be empty'}.to_json, :status => ["422", "Validation Errors"], :content_type => 'application/json')
|
58
|
-
yield
|
59
|
-
FakeWeb.clean_registry
|
60
|
-
end
|
61
|
-
|
62
|
-
def stub_delete_response(object=nil)
|
63
|
-
path = '/dummies'
|
64
|
-
if object
|
65
|
-
path = object.rest_path
|
66
|
-
if object.belongs_to_relationship?
|
67
|
-
path = object.belongs_to_relationships.first.rest_path
|
68
|
-
end
|
69
|
-
end
|
70
|
-
FakeWeb.register_uri(:delete, %r|http://test\.local#{path}/\d*|, :body => nil, :status => ["200", "Object deleted"], :content_type => 'application/json')
|
71
|
-
yield
|
72
|
-
FakeWeb.clean_registry
|
73
|
-
end
|
74
|
-
|
75
|
-
def stub_delete_errornous_response
|
76
|
-
FakeWeb.register_uri(:delete, %r|http://test\.local/dummies/\d*|, :body => nil, :status => ["500", "Can't delete it :("], :content_type => 'application/json')
|
77
|
-
yield
|
78
|
-
FakeWeb.clean_registry
|
79
|
-
end
|
80
|
-
|
81
|
-
def stub_nested_all_response(parent,*children)
|
82
|
-
json = children.inject([]) { |acc, o| acc << o.as_json(:root => o.class.model_name.element, :methods => [:id]) }.to_json
|
83
|
-
FakeWeb.register_uri(:get, "http://test.local/#{parent.class.name.to_s.downcase.pluralize}/#{parent.id}/#{children.first.class.name.downcase.pluralize}", :body => json, :content_type => 'application/json')
|
84
|
-
yield
|
85
|
-
FakeWeb.clean_registry
|
86
|
-
end
|
87
|
-
|
88
|
-
def stub_nested_single_response(parent,child)
|
89
|
-
FakeWeb.register_uri(:get, %r|http://test\.local/#{parent.class.name.to_s.downcase.pluralize}/#{parent.id}/#{child.class.name.downcase.pluralize}/#{child.id}|, :body => { child.class.name.downcase.to_sym => child.to_hash }.to_json, :content_type => 'application/json')
|
90
|
-
yield
|
91
|
-
FakeWeb.clean_registry
|
92
|
-
end
|
93
|
-
|
94
|
-
def stub_conditional_all_response(query, *objects)
|
95
|
-
#json = JSON.generate(objects.inject([]) { |acc,o| acc << })
|
96
|
-
json = objects.inject([]) { |acc, o| acc << o.as_json(:root => o.class.model_name.element, :methods => [:id]) }.to_json
|
97
|
-
FakeWeb.register_uri(:get, %r|http://test.local/dummies\?.*|, :body => json, :content_type => 'application/json')
|
98
|
-
yield
|
99
|
-
FakeWeb.clean_registry
|
100
|
-
end
|
101
|
-
|
102
|
-
def stub_conditional_nested_all_response(parent,query, *children)
|
103
|
-
json = children.inject([]) { |acc, o| acc << o.as_json(:root => o.class.model_name.element, :methods => [:id]) }.to_json
|
104
|
-
FakeWeb.register_uri(:get, %r|http://test.local/#{parent.class.name.to_s.downcase.pluralize}/#{parent.id}/#{children.first.class.name.downcase.pluralize}\?.*|, :body => json, :content_type => 'application/json')
|
105
|
-
yield
|
106
|
-
FakeWeb.clean_registry
|
107
|
-
end
|
108
|
-
|
109
|
-
def stub_conditional_single_response(object, query)
|
110
|
-
#json = JSON.generate(objects.inject([]) { |acc,o| acc << })
|
111
|
-
FakeWeb.register_uri(:get, %r|http://test.local/dummies/\d{1,2}\?.+|, :body => object.to_json, :content_type => 'application/json')
|
112
|
-
yield
|
113
|
-
FakeWeb.clean_registry
|
114
|
-
end
|
115
|
-
|
116
|
-
def stub_conditional_nested_single_response(parent,child, query)
|
117
|
-
FakeWeb.register_uri(:get, %r|http://test.local/#{parent.class.name.to_s.downcase.pluralize}/#{parent.id}/#{child.class.name.downcase.pluralize}/\d{1,2}\?.*|, :body => child.to_json, :content_type => 'application/json')
|
118
|
-
yield
|
119
|
-
FakeWeb.clean_registry
|
120
|
-
end
|