rc_rails 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/.gitignore +7 -0
  2. data/CHANGELOG +355 -0
  3. data/Gemfile +5 -0
  4. data/Gemfile.lock.development +117 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +71 -0
  7. data/Rakefile +33 -0
  8. data/Todo.txt +1 -0
  9. data/lib/rc_rails.rb +9 -0
  10. data/lib/resources_controller/actions.rb +147 -0
  11. data/lib/resources_controller/active_record/saved.rb +15 -0
  12. data/lib/resources_controller/helper.rb +123 -0
  13. data/lib/resources_controller/include_actions.rb +37 -0
  14. data/lib/resources_controller/named_route_helper.rb +154 -0
  15. data/lib/resources_controller/railtie.rb +14 -0
  16. data/lib/resources_controller/request_path_introspection.rb +83 -0
  17. data/lib/resources_controller/resource_methods.rb +32 -0
  18. data/lib/resources_controller/singleton_actions.rb +21 -0
  19. data/lib/resources_controller/specification.rb +119 -0
  20. data/lib/resources_controller/version.rb +3 -0
  21. data/lib/resources_controller.rb +849 -0
  22. data/resources_controller.gemspec +29 -0
  23. data/spec/app/database.yml +5 -0
  24. data/spec/app/views/accounts/show.html.erb +0 -0
  25. data/spec/app/views/addresses/edit.html.erb +0 -0
  26. data/spec/app/views/addresses/index.html.erb +0 -0
  27. data/spec/app/views/addresses/new.html.erb +0 -0
  28. data/spec/app/views/addresses/show.html.erb +0 -0
  29. data/spec/app/views/admin/forums/create.html.erb +0 -0
  30. data/spec/app/views/admin/forums/destroy.html.erb +0 -0
  31. data/spec/app/views/admin/forums/edit.html.erb +0 -0
  32. data/spec/app/views/admin/forums/index.html.erb +0 -0
  33. data/spec/app/views/admin/forums/new.html.erb +0 -0
  34. data/spec/app/views/admin/forums/show.html.erb +0 -0
  35. data/spec/app/views/admin/forums/update.html.erb +0 -0
  36. data/spec/app/views/comments/edit.html.erb +0 -0
  37. data/spec/app/views/comments/index.html.erb +0 -0
  38. data/spec/app/views/comments/new.html.erb +0 -0
  39. data/spec/app/views/comments/show.html.erb +0 -0
  40. data/spec/app/views/forum_posts/edit.html.erb +0 -0
  41. data/spec/app/views/forum_posts/index.html.erb +0 -0
  42. data/spec/app/views/forum_posts/new.html.erb +0 -0
  43. data/spec/app/views/forum_posts/show.html.erb +0 -0
  44. data/spec/app/views/forums/create.html.erb +0 -0
  45. data/spec/app/views/forums/destroy.html.erb +0 -0
  46. data/spec/app/views/forums/edit.html.erb +0 -0
  47. data/spec/app/views/forums/index.html.erb +0 -0
  48. data/spec/app/views/forums/new.html.erb +0 -0
  49. data/spec/app/views/forums/show.html.erb +0 -0
  50. data/spec/app/views/forums/update.html.erb +0 -0
  51. data/spec/app/views/infos/edit.html.erb +0 -0
  52. data/spec/app/views/infos/show.html.erb +0 -0
  53. data/spec/app/views/interests/index.html.erb +0 -0
  54. data/spec/app/views/interests/show.html.erb +0 -0
  55. data/spec/app/views/owners/edit.html.erb +0 -0
  56. data/spec/app/views/owners/new.html.erb +0 -0
  57. data/spec/app/views/owners/show.html.erb +0 -0
  58. data/spec/app/views/tags/index.html.erb +0 -0
  59. data/spec/app/views/tags/new.html.erb +0 -0
  60. data/spec/app/views/tags/show.html.erb +0 -0
  61. data/spec/app/views/users/edit.html.erb +0 -0
  62. data/spec/app/views/users/index.html.erb +0 -0
  63. data/spec/app/views/users/show.html.erb +0 -0
  64. data/spec/app.rb +315 -0
  65. data/spec/controllers/accounts_controller_spec.rb +77 -0
  66. data/spec/controllers/addresses_controller_spec.rb +346 -0
  67. data/spec/controllers/admin_forums_controller_spec.rb +638 -0
  68. data/spec/controllers/comments_controller_spec.rb +380 -0
  69. data/spec/controllers/comments_controller_with_models_spec.rb +202 -0
  70. data/spec/controllers/forum_posts_controller_spec.rb +426 -0
  71. data/spec/controllers/forums_controller_spec.rb +694 -0
  72. data/spec/controllers/infos_controller_spec.rb +71 -0
  73. data/spec/controllers/interests_controller_via_forum_spec.rb +80 -0
  74. data/spec/controllers/interests_controller_via_user_spec.rb +114 -0
  75. data/spec/controllers/owners_controller_spec.rb +277 -0
  76. data/spec/controllers/resource_saved_spec.rb +47 -0
  77. data/spec/controllers/resource_service_in_forums_controller_spec.rb +37 -0
  78. data/spec/controllers/resource_service_in_infos_controller_spec.rb +36 -0
  79. data/spec/controllers/resource_service_in_interests_controller_via_forum_spec.rb +51 -0
  80. data/spec/controllers/tags_controller_spec.rb +83 -0
  81. data/spec/controllers/tags_controller_via_account_info_spec.rb +131 -0
  82. data/spec/controllers/tags_controller_via_forum_post_comment_spec.rb +144 -0
  83. data/spec/controllers/tags_controller_via_forum_post_spec.rb +133 -0
  84. data/spec/controllers/tags_controller_via_forum_spec.rb +173 -0
  85. data/spec/controllers/tags_controller_via_user_address_spec.rb +130 -0
  86. data/spec/controllers/users_controller_spec.rb +248 -0
  87. data/spec/lib/action_view_helper_spec.rb +143 -0
  88. data/spec/lib/bug_0001_spec.rb +22 -0
  89. data/spec/lib/include_actions_spec.rb +35 -0
  90. data/spec/lib/load_enclosing_resources_spec.rb +245 -0
  91. data/spec/lib/request_path_introspection_spec.rb +130 -0
  92. data/spec/lib/resource_methods_spec.rb +204 -0
  93. data/spec/lib/resources_controller_spec.rb +57 -0
  94. data/spec/models/comment_saved_spec.rb +24 -0
  95. data/spec/rspec_generator_task.rb +105 -0
  96. data/spec/spec_helper.rb +17 -0
  97. data/spec/verify_rcov.rb +52 -0
  98. metadata +193 -0
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
4
+ require 'resources_controller/version'
5
+ version = ResourcesController::VERSION
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "rc_rails"
9
+ s.version = version
10
+ s.platform = Gem::Platform::RUBY
11
+ s.authors = ["Ian White"]
12
+ s.email = "ian.w.white@gmail.com"
13
+ s.homepage = "http://github.com/ianwhite/resources_controller"
14
+ s.summary = "resources_controller-#{version}"
15
+ s.description = "rc makes RESTful controllers fun"
16
+
17
+ s.rubygems_version = "1.3.7"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
21
+ s.extra_rdoc_files = [ "README.rdoc" ]
22
+ s.rdoc_options = ["--charset=UTF-8"]
23
+ s.require_path = "lib"
24
+
25
+ s.add_runtime_dependency "rails", '>= 3.1.0'
26
+ s.add_development_dependency "rspec", '>= 2.8.0'
27
+ s.add_development_dependency "rspec-rails", '>= 2.8.0'
28
+ s.add_development_dependency 'sqlite3'
29
+ end
@@ -0,0 +1,5 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: tmp/test.sqlite3
4
+ pool: 5
5
+ timeout: 5000
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
data/spec/app.rb ADDED
@@ -0,0 +1,315 @@
1
+ # Testing app setup
2
+
3
+ module ResourcesControllerTest
4
+ class Application < Rails::Application
5
+ config.active_support.deprecation = :stderr
6
+ paths['config/database'] = File.expand_path('../app/database.yml', __FILE__)
7
+ paths['log'] = File.expand_path('../../../tmp/log', __FILE__)
8
+ end
9
+ end
10
+
11
+ ResourcesControllerTest::Application.initialize!
12
+
13
+ ##########
14
+ # Routing
15
+ ##########
16
+
17
+ Rails.application
18
+ Rails.application.routes.clear!
19
+ Rails.application.routes.draw do
20
+ # this tests :resource_path (or :erp), for named routes that map to resources
21
+ root :controller => 'forums', :action => 'index', :resource_path => '/forums'
22
+ match 'create_forum', :controller => 'forums', :action => 'create', :resource_path => '/forums', :resource_method => :post
23
+
24
+ namespace :admin do
25
+ resources :forums do
26
+ resources :interests
27
+ end
28
+ namespace :superduper do
29
+ resources :forums
30
+ end
31
+ end
32
+
33
+ resources :users do
34
+ resources :posts, :controller => 'user_posts'
35
+ resources :comments, :controller => 'user_comments'
36
+ resources :addresses do
37
+ resources :tags
38
+ end
39
+ end
40
+
41
+ resources :forums do
42
+ resources :interests
43
+ resources :posts, :controller => 'forum_posts' do
44
+ resources :comments do
45
+ resources :tags
46
+ end
47
+ resources :tags
48
+ end
49
+ resource :owner do
50
+ resources :posts do
51
+ resources :tags
52
+ end
53
+ end
54
+ resources :tags
55
+ end
56
+
57
+ resource :account do
58
+ resources :posts
59
+ resource :info do
60
+ resources :tags
61
+ end
62
+ end
63
+
64
+ resources :tags
65
+
66
+ with_options :path_prefix => ":tag_id", :name_prefix => "tag_" do
67
+ resources :forums
68
+ end
69
+
70
+ # the following routes are for testing errors
71
+ resources :posts, :controller => 'forum_posts'
72
+ resources :foos do
73
+ resources :bars, :controller => 'forum_posts'
74
+ end
75
+
76
+ match ':controller/:action/:id(.:format)' # naming this so we can test missing segment errors
77
+ end
78
+
79
+
80
+ ##################
81
+ # Database schema
82
+ ##################
83
+
84
+ ActiveRecord::Migration.suppress_messages do
85
+ ActiveRecord::Schema.define(:version => 0) do
86
+ create_table :users, :force => true do |t|
87
+ t.string :login
88
+ end
89
+
90
+ create_table :infos, :force => true do |t|
91
+ t.column "user_id", :integer
92
+ end
93
+
94
+ create_table :addresses, :force => true do |t|
95
+ t.column "user_id", :integer
96
+ end
97
+
98
+ create_table :forums, :force => true do |t|
99
+ t.column "owner_id", :integer
100
+ end
101
+
102
+ create_table :posts, :force => true do |t|
103
+ t.column "forum_id", :integer
104
+ t.column "user_id", :integer
105
+ end
106
+
107
+ create_table :comments, :force => true do |t|
108
+ t.column "post_id", :integer
109
+ t.column "user_id", :integer
110
+ end
111
+
112
+ create_table :interests, :force => true do |t|
113
+ t.column "interested_in_id", :integer
114
+ t.column "interested_in_type", :string
115
+ end
116
+
117
+ create_table :tags, :force => true do |t|
118
+ t.column "taggable_id", :integer
119
+ t.column "taggable_type", :string
120
+ end
121
+ end
122
+ end
123
+
124
+
125
+ #########
126
+ # Models
127
+ #########
128
+
129
+ class Interest < ActiveRecord::Base
130
+ belongs_to :interested_in, :polymorphic => true
131
+ end
132
+
133
+ class Tag < ActiveRecord::Base
134
+ belongs_to :taggable, :polymorphic => true
135
+ end
136
+
137
+ class User < ActiveRecord::Base
138
+ has_many :posts
139
+ has_many :comments
140
+ has_many :interests, :as => :interested_in
141
+ has_many :addresses
142
+ has_one :info
143
+
144
+ def to_param
145
+ login
146
+ end
147
+ end
148
+
149
+ class Info < ActiveRecord::Base
150
+ belongs_to :user
151
+ has_many :tags, :as => :taggable
152
+ end
153
+
154
+ class Address < ActiveRecord::Base
155
+ belongs_to :user
156
+ has_many :tags, :as => :taggable
157
+ end
158
+
159
+ class Forum < ActiveRecord::Base
160
+ has_many :posts
161
+ has_many :tags, :as => :taggable
162
+ has_many :interests, :as => :interested_in
163
+ has_many :users, :through => :posts
164
+ belongs_to :owner, :class_name => "User"
165
+ end
166
+
167
+ class Post < ActiveRecord::Base
168
+ belongs_to :forum
169
+ belongs_to :user
170
+ has_many :comments
171
+ has_many :tags, :as => :taggable
172
+ end
173
+
174
+ class Comment < ActiveRecord::Base
175
+ validates_presence_of :user, :post
176
+
177
+ belongs_to :user
178
+ belongs_to :post
179
+ has_many :tags, :as => :taggable
180
+ end
181
+
182
+ ##############
183
+ # Controllers
184
+ ##############
185
+
186
+ class ApplicationController < ActionController::Base
187
+ map_enclosing_resource :account, :class => User, :singleton => true, :find => :current_user
188
+
189
+ map_enclosing_resource :user do
190
+ User.find_by_login(params[:user_id])
191
+ end
192
+
193
+ protected
194
+ def current_user
195
+ @current_user
196
+ end
197
+ end
198
+
199
+ module Admin
200
+ class ForumsController < ApplicationController
201
+ resources_controller_for :forums
202
+ end
203
+
204
+ class InterestsController < ApplicationController
205
+ resources_controller_for :interests
206
+ end
207
+
208
+ module NotANamespace
209
+ class ForumsController < ApplicationController
210
+ resources_controller_for :forums
211
+ end
212
+ end
213
+
214
+ module Superduper
215
+ class ForumsController < ApplicationController
216
+ resources_controller_for :forums
217
+ end
218
+ end
219
+ end
220
+
221
+ class AccountsController < ApplicationController
222
+ resources_controller_for :account, :singleton => true, :source => :user, :find => :current_user
223
+ end
224
+
225
+ class InfosController < ApplicationController
226
+ resources_controller_for :info, :singleton => true, :only => [:show, :edit, :update]
227
+ end
228
+
229
+ class TagsController < ApplicationController
230
+ resources_controller_for :tags
231
+ end
232
+
233
+ class UsersController < ApplicationController
234
+ resources_controller_for :users, :except => [:new, :create, :destroy]
235
+
236
+ protected
237
+ def find_resource(id = params[:id])
238
+ resource_service.find_by_login(id)
239
+ end
240
+ end
241
+
242
+ class ForumsController < ApplicationController
243
+ resources_controller_for :forums
244
+ end
245
+
246
+ class OwnersController < ApplicationController
247
+ resources_controller_for :owner, :singleton => true, :class => User, :in => :forum
248
+ end
249
+
250
+ class PostsAbstractController < ApplicationController
251
+ include ResourcesController::ResourceMethods
252
+ attr_accessor :filter_trace
253
+
254
+ # for testing filter load order
255
+ before_filter {|controller| controller.filter_trace ||= []; controller.filter_trace << :abstract}
256
+
257
+ protected
258
+ # redefine find_resources
259
+ def find_resources
260
+ resource_service.find :all, :order => 'id DESC'
261
+ end
262
+ end
263
+
264
+ class PostsController < PostsAbstractController
265
+ # for testing filter load order
266
+ before_filter {|controller| controller.filter_trace ||= []; controller.filter_trace << :posts}
267
+
268
+ # example of providing options to resources_controller_for
269
+ resources_controller_for :posts, :class => Post, :route => 'posts'
270
+
271
+ def load_enclosing_resources_with_trace(*args)
272
+ self.filter_trace ||= []; self.filter_trace << :load_enclosing
273
+ load_enclosing_resources_without_trace(*args)
274
+ end
275
+ alias_method_chain :load_enclosing_resources, :trace
276
+ end
277
+
278
+ class UserPostsController < PostsController
279
+ # for testing filter load order
280
+ before_filter {|controller| controller.filter_trace ||= []; controller.filter_trace << :user_posts}
281
+
282
+ # example of providing options to nested in
283
+ nested_in :user, :class => User, :key => 'user_id', :name_prefix => 'user_'
284
+ end
285
+
286
+ class AddressesController < ApplicationController
287
+ resources_controller_for :addresses
288
+ end
289
+
290
+ class ForumPostsController < PostsController
291
+ # for testing filter load order
292
+ before_filter {|controller| controller.filter_trace ||= []; controller.filter_trace << :forum_posts}
293
+
294
+ # test override resources_controller_for use
295
+ resources_controller_for :posts
296
+
297
+ # example of providing a custom finder for the nesting resource
298
+ # also example of :as option, which allows you to assign an alias
299
+ # for an enclosing resource
300
+ nested_in :forum, :as => :other_name_for_forum do
301
+ Forum.find(params[:forum_id])
302
+ end
303
+ end
304
+
305
+ class CommentsController < ApplicationController
306
+ resources_controller_for :comments, :in => [:forum, :post], :load_enclosing => false
307
+ end
308
+
309
+ class InterestsController < ApplicationController
310
+ resources_controller_for :interests
311
+ nested_in :interested_in, :polymorphic => true
312
+
313
+ # the above two lines are the same as:
314
+ # resources_controller_for :interests, :in => '?interested_in'
315
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ module AccountsControllerSpecHelper
4
+ def setup_mocks
5
+ @current_user = mock('user')
6
+ @current_user.stub!(:id).and_return('1')
7
+ User.stub!(:find).and_return(@current_user)
8
+ @controller.instance_variable_set('@current_user', @current_user)
9
+ end
10
+ end
11
+
12
+ describe AccountsController do
13
+ describe "Routing shortcuts for Account should map" do
14
+ include AccountsControllerSpecHelper
15
+
16
+ before(:each) do
17
+ setup_mocks
18
+ get :show
19
+ end
20
+
21
+ it "resource_path to /account" do
22
+ controller.resource_path.should == '/account'
23
+ end
24
+
25
+ it "resource_info_tags_path to /account/info/tags" do
26
+ controller.resource_info_tags_path.should == "/account/info/tags"
27
+ end
28
+ end
29
+
30
+ describe AccountsController, " requesting garbage url" do
31
+ it "should raise ResourcesController::Specification::NoClassFoundError" do
32
+ lambda { get :show, :resource_path => "/crayzeee" }.should raise_error(ResourcesController::Specification::NoClassFoundError)
33
+ end
34
+ end
35
+
36
+ describe AccountsController, "#resource_service" do
37
+ include AccountsControllerSpecHelper
38
+
39
+ before(:each) do
40
+ setup_mocks
41
+ get :show
42
+ @resource_service = controller.send :resource_service
43
+ end
44
+
45
+ it ".new should call :new on User" do
46
+ User.should_receive(:new).with(:args => 'args')
47
+ @resource_service.new :args => 'args'
48
+ end
49
+
50
+ it ".find should call :current_user" do
51
+ @controller.should_receive(:current_user).once.and_return(@current_user)
52
+ @resource_service.find
53
+ end
54
+
55
+ it ".find should call whatever is in resource_specification @find" do
56
+ @controller.should_receive(:lambda_called).once.and_return(@current_user)
57
+ resource_specification = @controller.send(:resource_specification)
58
+ resource_specification.stub(:find).and_return(lambda { lambda_called })
59
+ @resource_service.find
60
+ end
61
+
62
+ it ".find should raise CantFindSingleton when no custom finder (and no enclosing resource)" do
63
+ @controller.send(:resource_specification).stub!(:find).and_return nil
64
+ lambda{ @resource_service.find }.should raise_error(ResourcesController::CantFindSingleton)
65
+ end
66
+
67
+ it ".foo should call foo on User" do
68
+ User.should_receive(:foo).once
69
+ @resource_service.foo
70
+ end
71
+
72
+ it ".respond_to?(:foo) should call respond_to?(:foo) on User" do
73
+ User.stub!(:foo)
74
+ @resource_service.respond_to?(:foo).should be_true
75
+ end
76
+ end
77
+ end