giraffesoft-classy_resources 0.0.1 → 0.1.0

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