giraffesoft-classy_resources 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Think resource_controller, except for Sinatra.
4
4
 
5
+ = Installation
6
+
7
+ sudo gem install giraffesoft-classy_resources
8
+
5
9
  = Usage
6
10
 
7
11
  require 'rubygems'
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 1
2
+ :patch: 0
3
3
  :major: 0
4
- :minor: 0
4
+ :minor: 1
@@ -11,8 +11,25 @@ module ClassyResources
11
11
  ResourceBuilder.new(self, *options)
12
12
  end
13
13
 
14
- def collection_url_for(resource, format)
15
- "/#{resource}.#{format}"
14
+ def load_collection(resource, parent = nil)
15
+ parent.nil? ? load_shallow_collection(resource) : load_nested_collection(resource, parent)
16
+ end
17
+
18
+ def create_object(resource, object_params, parent = nil)
19
+ parent.nil? ? create_shallow_object(resource, object_params) : create_nested_object(resource, object_params, parent)
20
+ end
21
+
22
+ def load_parent_object(parent)
23
+ load_object(parent, params[parent_id_name(parent)])
24
+ end
25
+
26
+ def parent_id_name(parent)
27
+ :"#{parent.to_s.singularize}_id"
28
+ end
29
+
30
+ def collection_url_for(resource, format, parent = nil)
31
+ parent = parent.nil? ? "" : "/#{parent}/:#{parent_id_name(parent)}"
32
+ [parent, "/#{resource}.#{format}"].join
16
33
  end
17
34
 
18
35
  def object_route_url(resource, format)
@@ -57,16 +74,18 @@ module ClassyResources
57
74
 
58
75
  protected
59
76
  def define_collection_get(resource, format)
60
- get collection_url_for(resource, format) do
77
+ parent = options[:parent]
78
+ get collection_url_for(resource, format, parent) do
61
79
  set_content_type(format)
62
- serialize(load_collection(resource), format)
80
+ serialize(load_collection(resource, parent), format)
63
81
  end
64
82
  end
65
83
 
66
84
  def define_collection_post(resource, format)
67
- post collection_url_for(resource, format) do
85
+ parent = options[:parent]
86
+ post collection_url_for(resource, format, parent) do
68
87
  set_content_type(format)
69
- object = create_object(resource, params[resource.to_s.singularize])
88
+ object = create_object(resource, params[resource.to_s.singularize] || {}, parent)
70
89
  redirect object_url_for(resource, format, object)
71
90
  end
72
91
  end
@@ -74,7 +93,7 @@ module ClassyResources
74
93
  def define_member_get(resource, format)
75
94
  get object_route_url(resource, format) do
76
95
  set_content_type(format)
77
- object = find_object(resource, params[:id])
96
+ object = load_object(resource, params[:id])
78
97
  serialize(object, format)
79
98
  end
80
99
  end
@@ -82,7 +101,7 @@ module ClassyResources
82
101
  def define_member_put(resource, format)
83
102
  put object_route_url(resource, format) do
84
103
  set_content_type(format)
85
- object = find_object(resource, params[:id])
104
+ object = load_object(resource, params[:id])
86
105
  update_object(object, params[resource.to_s.singularize])
87
106
  serialize(object, format)
88
107
  end
@@ -91,7 +110,7 @@ module ClassyResources
91
110
  def define_member_delete(resource, format)
92
111
  delete object_route_url(resource, format) do
93
112
  set_content_type(format)
94
- object = find_object(resource, params[:id])
113
+ object = load_object(resource, params[:id])
95
114
  destroy_object(object)
96
115
  ""
97
116
  end
@@ -1,14 +1,22 @@
1
1
  module ClassyResources
2
2
  module ActiveRecord
3
- def load_collection(resource)
3
+ def load_shallow_collection(resource)
4
4
  class_for(resource).all
5
5
  end
6
6
 
7
- def create_object(resource, params)
7
+ def load_nested_collection(resource, parent)
8
+ load_parent_object(parent).send(resource)
9
+ end
10
+
11
+ def create_shallow_object(resource, params)
8
12
  class_for(resource).create!(params)
9
13
  end
10
14
 
11
- def find_object(resource, id)
15
+ def create_nested_object(resource, params, parent)
16
+ load_parent_object(parent).send(resource).create!(params)
17
+ end
18
+
19
+ def load_object(resource, id)
12
20
  class_for(resource).find(id)
13
21
  end
14
22
 
@@ -1,14 +1,23 @@
1
1
  module ClassyResources
2
2
  module Sequel
3
- def load_collection(resources)
4
- class_for(resources).all
3
+ def load_shallow_collection(resource)
4
+ class_for(resource).all
5
5
  end
6
6
 
7
- def create_object(resource, params)
8
- class_for(resource).create(params)
7
+ def load_nested_collection(resource, parent)
8
+ load_parent_object(parent).send(resource)
9
9
  end
10
10
 
11
- def find_object(resource, id)
11
+ def create_shallow_object(resource, object_params)
12
+ class_for(resource).create(object_params)
13
+ end
14
+
15
+ def create_nested_object(resource, object_params, parent)
16
+ c = create_shallow_object(resource, object_params)
17
+ load_parent_object(parent).send(:"add_#{resource.to_s.singularize}", c)
18
+ end
19
+
20
+ def load_object(resource, id)
12
21
  class_for(resource).find(:id => id)
13
22
  end
14
23
 
@@ -77,4 +77,29 @@ class ActiveRecordTest < Test::Unit::TestCase
77
77
  assert_nil Post.find_by_id(@post)
78
78
  end
79
79
  end
80
+
81
+ context "on GET to /posts/id/comments" do
82
+ setup do
83
+ @post = create_post
84
+ 2.times { @post.comments.create!(hash_for_comment) }
85
+ 2.times { create_comment }
86
+ get "/posts/#{@post.id}/comments.xml"
87
+ end
88
+
89
+ expect { assert_equal 200, @response.status }
90
+ expect { assert_equal "application/xml", @response.content_type }
91
+ expect { assert_equal @post.comments.to_xml, @response.body }
92
+ end
93
+
94
+ context "on POST to /posts/id/comments" do
95
+ setup do
96
+ @post = create_post
97
+ post "/posts/#{@post.id}/comments.xml", :comment => hash_for_comment
98
+ end
99
+
100
+ expect { assert_equal 302, @response.status }
101
+ expect { assert_equal "application/xml", @response.content_type }
102
+ expect { assert_equal "/comments/#{@post.comments.reload.first.id}.xml", @response.location }
103
+ expect { assert_equal 1, @post.comments.reload.count }
104
+ end
80
105
  end
@@ -14,12 +14,26 @@ ActiveRecord::Schema.define(:version => 0) do
14
14
  create_table :posts do |t|
15
15
  t.string :title
16
16
  end
17
+
18
+ create_table :comments do |t|
19
+ t.integer :post_id
20
+ t.string :author
21
+ end
17
22
  end
18
23
 
19
24
  class Post < ActiveRecord::Base
25
+ has_many :comments
26
+ end
27
+
28
+ class Comment < ActiveRecord::Base
29
+ belongs_to :post
20
30
  end
21
31
 
22
32
 
23
33
  define_resource :posts, :collection => [:get, :post],
24
34
  :member => [:get, :put, :delete],
25
35
  :formats => [:xml, :json]
36
+
37
+ define_resource :comments, :collection => [:get, :post],
38
+ :parent => :posts
39
+
@@ -10,10 +10,24 @@ Sequel::Model.db.instance_eval do
10
10
  primary_key :id
11
11
  varchar :name
12
12
  end
13
+
14
+ create_table! :subscriptions do
15
+ primary_key :id
16
+ int :user_id
17
+ varchar :name
18
+ end
13
19
  end
14
20
 
15
21
  class User < Sequel::Model(:users)
22
+ one_to_many :subscriptions
23
+ end
24
+
25
+ class Subscription < Sequel::Model(:subscriptions)
26
+ many_to_one :users
16
27
  end
17
28
 
18
29
  define_resource :users, :collection => [:get, :post],
19
30
  :member => [:put, :delete, :get]
31
+
32
+ define_resource :subscriptions, :collection => [:get, :post],
33
+ :parent => :users
data/test/sequel_test.rb CHANGED
@@ -73,4 +73,38 @@ class SequelTest < Test::Unit::TestCase
73
73
  assert_nil User.find(:id => @user.id)
74
74
  end
75
75
  end
76
+
77
+ context "on GET to /users/id/comments" do
78
+ setup do
79
+ @user = create_user
80
+ 2.times { @user.add_subscription(create_subscription) }
81
+ 2.times { create_subscription }
82
+ get "/users/#{@user.id}/subscriptions.xml"
83
+ end
84
+
85
+ expect { assert_equal 200, @response.status }
86
+ expect { assert_equal "application/xml", @response.content_type }
87
+ expect { assert_equal @user.subscriptions.to_xml, @response.body }
88
+ end
89
+
90
+ context "on POST to /users/id/subscriptions" do
91
+ setup do
92
+ @user = create_user
93
+ post "/users/#{@user.id}/subscriptions.xml", :subscription => hash_for_subscription
94
+ end
95
+
96
+ expect { assert_equal 302, @response.status }
97
+ expect { assert_equal "application/xml", @response.content_type }
98
+ expect { assert_equal "/subscriptions/#{@user.reload.subscriptions.first.id}.xml", @response.location }
99
+ expect { assert_equal 1, @user.reload.subscriptions.length }
100
+ end
101
+
102
+ context "on POST to /users/id/subscriptions with no params" do
103
+ should "not raise" do
104
+ @user = create_user
105
+ assert_nothing_raised {
106
+ post "/users/#{@user.id}/subscriptions.xml", :subscription => {}
107
+ }
108
+ end
109
+ end
76
110
  end
data/test/test_helper.rb CHANGED
@@ -11,9 +11,27 @@ class Test::Unit::TestCase
11
11
  Post.create!({}.merge(opts))
12
12
  end
13
13
 
14
+ def hash_for_comment(opts = {})
15
+ {}.merge(opts)
16
+ end
17
+
18
+ def create_comment(opts = {})
19
+ Comment.create!(hash_for_comment(opts))
20
+ end
21
+
14
22
  def create_user(opts = {})
15
23
  u = User.new({}.merge(opts))
16
24
  u.save
17
25
  u
18
26
  end
27
+
28
+ def hash_for_subscription(opts = {})
29
+ {:name => "emptiness is depressing"}.merge(opts)
30
+ end
31
+
32
+ def create_subscription(opts = {})
33
+ s = Subscription.new(hash_for_subscription(opts))
34
+ s.save
35
+ s
36
+ end
19
37
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: giraffesoft-classy_resources
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Golick
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-27 00:00:00 -08:00
12
+ date: 2009-01-28 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15