make_resourceful 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +31 -0
- data/Readme.rdoc +229 -0
- data/VERSION +1 -0
- data/lib/make_resourceful.rb +11 -0
- data/lib/resourceful/base.rb +63 -0
- data/lib/resourceful/builder.rb +405 -0
- data/lib/resourceful/default/accessors.rb +418 -0
- data/lib/resourceful/default/actions.rb +101 -0
- data/lib/resourceful/default/callbacks.rb +51 -0
- data/lib/resourceful/default/responses.rb +118 -0
- data/lib/resourceful/default/urls.rb +136 -0
- data/lib/resourceful/generators/resourceful_scaffold/resourceful_scaffold_generator.rb +87 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/controller.rb +5 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/fixtures.yml +10 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/functional_test.rb +50 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/helper.rb +2 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/migration.rb +13 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/model.rb +2 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/unit_test.rb +7 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/view__form.haml +5 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/view_edit.haml +11 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/view_index.haml +5 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/view_new.haml +9 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/view_partial.haml +12 -0
- data/lib/resourceful/generators/resourceful_scaffold/templates/view_show.haml +14 -0
- data/lib/resourceful/maker.rb +92 -0
- data/lib/resourceful/response.rb +33 -0
- data/lib/resourceful/serialize.rb +185 -0
- data/spec/accessors_spec.rb +474 -0
- data/spec/actions_spec.rb +310 -0
- data/spec/base_spec.rb +12 -0
- data/spec/builder_spec.rb +332 -0
- data/spec/callbacks_spec.rb +71 -0
- data/spec/integration_spec.rb +394 -0
- data/spec/maker_spec.rb +91 -0
- data/spec/response_spec.rb +37 -0
- data/spec/responses_spec.rb +314 -0
- data/spec/serialize_spec.rb +133 -0
- data/spec/urls_spec.rb +282 -0
- metadata +97 -0
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'spec/rake/spectask'
|
4
|
+
|
5
|
+
desc 'Default: run specs.'
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
spec_files = Rake::FileList["spec/**/*_spec.rb"]
|
9
|
+
|
10
|
+
desc "Run specs"
|
11
|
+
Spec::Rake::SpecTask.new do |t|
|
12
|
+
t.spec_files = spec_files
|
13
|
+
t.spec_opts = ["-c"]
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Generate code coverage"
|
17
|
+
Spec::Rake::SpecTask.new(:coverage) do |t|
|
18
|
+
t.spec_files = spec_files
|
19
|
+
t.rcov = true
|
20
|
+
t.rcov_opts = ['--exclude', 'spec,/var/lib/gems']
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'Generate documentation for the make_resourceful plugin.'
|
24
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
25
|
+
rdoc.rdoc_dir = 'rdoc'
|
26
|
+
rdoc.title = 'make_resourceful'
|
27
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
28
|
+
rdoc.main = 'README'
|
29
|
+
rdoc.rdoc_files.include(FileList.new('*').exclude(/[^A-Z0-9]/))
|
30
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
31
|
+
end
|
data/Readme.rdoc
ADDED
@@ -0,0 +1,229 @@
|
|
1
|
+
= make_resourceful
|
2
|
+
===== Take back control of your Controllers. Make them awesome. Make them sleek. Make them resourceful.
|
3
|
+
|
4
|
+
REST is a fine pattern for designing controllers,
|
5
|
+
but it can be pretty repetitive.
|
6
|
+
Who wants to write out the same actions and copy the same model lookup logic
|
7
|
+
all over their application?
|
8
|
+
|
9
|
+
make_resourceful handles all that for you.
|
10
|
+
It sets up all your RESTful actions and responses with next to no code.
|
11
|
+
Everything has full, sensible default functionality.
|
12
|
+
|
13
|
+
Of course, no controller _only_ uses the defaults.
|
14
|
+
So make_resourceful can be massively customized,
|
15
|
+
while still keeping your controllers trim and readable.
|
16
|
+
|
17
|
+
== Get it!
|
18
|
+
|
19
|
+
Rails 3.0+
|
20
|
+
|
21
|
+
gem "make_resourceful" #ZOMG, SO EASY
|
22
|
+
|
23
|
+
Git
|
24
|
+
|
25
|
+
$ git clone git://github.com/hcatlin/make_resourceful.git
|
26
|
+
|
27
|
+
== Use it!
|
28
|
+
|
29
|
+
If you want to try make_resourceful on one of your current controllers,
|
30
|
+
just replace the mess of repetition with this:
|
31
|
+
|
32
|
+
class FooController < ApplicationController
|
33
|
+
make_resourceful do
|
34
|
+
actions :all
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Those three lines will replace the entire default controller
|
39
|
+
that comes out of the scaffold_resource generator.
|
40
|
+
|
41
|
+
=== Really?
|
42
|
+
|
43
|
+
Yes.
|
44
|
+
|
45
|
+
=== Can I do nested resources?
|
46
|
+
|
47
|
+
make_resourceful do
|
48
|
+
actions :all
|
49
|
+
belongs_to :post
|
50
|
+
end
|
51
|
+
|
52
|
+
=== What if I want to use fancy permalinks?
|
53
|
+
|
54
|
+
def current_object
|
55
|
+
@current_object ||= current_model.find_by_permalink(params[:id])
|
56
|
+
end
|
57
|
+
|
58
|
+
=== What about paging?
|
59
|
+
|
60
|
+
def current_objects
|
61
|
+
@current_objects ||= current_model.find(:all,
|
62
|
+
:order => "created_at DESC", :page => {:current => params[:page], :size => 10 } )
|
63
|
+
end
|
64
|
+
|
65
|
+
=== What if I want to do something in the middle of an action?
|
66
|
+
|
67
|
+
before :show, :index do
|
68
|
+
@page_title = "Awesome!"
|
69
|
+
end
|
70
|
+
|
71
|
+
after :create_fails do
|
72
|
+
@page_title = "Not So Awesome!"
|
73
|
+
end
|
74
|
+
|
75
|
+
=== What about all of my awesome respond_to blocks for my XML APIs and RJS responses?
|
76
|
+
|
77
|
+
response_for :show do |format|
|
78
|
+
format.html
|
79
|
+
format.js
|
80
|
+
format.xml
|
81
|
+
end
|
82
|
+
|
83
|
+
response_for :update_fails do |format|
|
84
|
+
format.html { render :action => 'edit' }
|
85
|
+
format.json { render :json => false.to_json, :status => 422 }
|
86
|
+
end
|
87
|
+
|
88
|
+
=== So I guess I have to write responses for all my actions?
|
89
|
+
|
90
|
+
Nope! make_resourceful makes them do the right thing by default.
|
91
|
+
You only need to customize them if you want to do something special.
|
92
|
+
|
93
|
+
=== Seriously?!
|
94
|
+
|
95
|
+
Yes!
|
96
|
+
|
97
|
+
== Grok it!
|
98
|
+
|
99
|
+
=== +make_resourceful+ the Method
|
100
|
+
|
101
|
+
The +make_resourceful+ block is where most of the action happens.
|
102
|
+
Here you specify which actions you want to auto-generate,
|
103
|
+
what code you want to run for given callbacks,
|
104
|
+
and so forth.
|
105
|
+
|
106
|
+
You also use the block to declare various bits of information about your controller.
|
107
|
+
For instance, if the controller is nested, you'd call +belongs_to+.
|
108
|
+
If you wanted to expose your models as some sort of text format,
|
109
|
+
you'd call +publish+.
|
110
|
+
|
111
|
+
Check out the documentation of Resourceful::Builder
|
112
|
+
for more information on the methods you can call here.
|
113
|
+
|
114
|
+
=== Helper Methods
|
115
|
+
|
116
|
+
make_resourceful provides lots of useful methods
|
117
|
+
that can be used in your callbacks and in your views.
|
118
|
+
They range from accessing the records you're looking up
|
119
|
+
to easily generating URLs for a record
|
120
|
+
to getting information about the action itself.
|
121
|
+
|
122
|
+
Two of the most useful methods are +current_object+ and +current_objects+
|
123
|
+
(note the subtle plurality difference).
|
124
|
+
+current_objects+ only works for +index+,
|
125
|
+
and returns all the records in the current model.
|
126
|
+
+current_object+ works for all actions other than +index+,
|
127
|
+
and returns the record that's currently being dealt with.
|
128
|
+
|
129
|
+
The full documentation of the helper methods
|
130
|
+
is in Resourceful::Default::Accessors and Resourceful::Default::URLs.
|
131
|
+
|
132
|
+
=== Nested Resources
|
133
|
+
|
134
|
+
make_resourceful supports easy management of nested resources.
|
135
|
+
This is set up with the Resourceful::Builder#belongs_to declaration.
|
136
|
+
Pass in the name of the parent model,
|
137
|
+
|
138
|
+
belongs_to :user
|
139
|
+
|
140
|
+
and everything will be taken care of.
|
141
|
+
When +index+ is run for GET /users/12/albums,
|
142
|
+
parent_object
|
143
|
+
will get <tt>User.find(params[:user_id])</tt>,
|
144
|
+
and current_objects
|
145
|
+
will get <tt>parent_object.albums</tt>.
|
146
|
+
When +create+ is run for POST /users/12/albums,
|
147
|
+
the newly created Album will automatically belong to the user
|
148
|
+
with id 12.
|
149
|
+
|
150
|
+
The normal non-scoped actions still work, too.
|
151
|
+
GET /albums/15 runs just fine.
|
152
|
+
make_resourceful knows that since there's no <tt>params[:user_id]</tt>,
|
153
|
+
you just want to deal with the album.
|
154
|
+
|
155
|
+
You can even have a single resource nested under several different resources.
|
156
|
+
Just pass multiple parent names to the Resourceful::Builder#belongs_to, like
|
157
|
+
|
158
|
+
belongs_to :user, :artist
|
159
|
+
|
160
|
+
Then /users/15/albums and /artists/7/albums will both work.
|
161
|
+
|
162
|
+
This does, however, mean that make_resourceful only supports one level of nesting.
|
163
|
+
There's no automatic handling of /users/15/collections/437/albums.
|
164
|
+
However, this is really the best way to organize most resources anyway;
|
165
|
+
see this {article}[http://weblog.jamisbuck.org/2007/2/5/nesting-resources].
|
166
|
+
|
167
|
+
If you really need a deeply nested controller,
|
168
|
+
it should be easy enough to set up on your own.
|
169
|
+
Just override current_model.
|
170
|
+
See the next section for more details.
|
171
|
+
|
172
|
+
=== Overriding Methods
|
173
|
+
|
174
|
+
Not only are helper methods useful to the developer to use,
|
175
|
+
they're used internally by the actions created by make_resourceful.
|
176
|
+
Thus one of the main ways make_resourceful can be customized
|
177
|
+
is by overriding accessors.
|
178
|
+
|
179
|
+
For instance, if you want to only look up the 10 most recent records for +index+,
|
180
|
+
you're override +current_objects+.
|
181
|
+
If you wanted to use a different model than that suggested by the name of the controller,
|
182
|
+
you'd override +current_model+.
|
183
|
+
|
184
|
+
When you're overriding methods that do SQL lookups, though, be a little cautious.
|
185
|
+
By default, these methods cache their values in instance variables
|
186
|
+
so that multiple SQL queries aren't run on multiple calls.
|
187
|
+
When overriding them, it's wise for you to do the same.
|
188
|
+
For instance,
|
189
|
+
|
190
|
+
def current_object
|
191
|
+
@current_object ||= current_model.find_by_name(params[:name])
|
192
|
+
end
|
193
|
+
|
194
|
+
=== For More Information...
|
195
|
+
|
196
|
+
Haven't found all the information you need in the RDoc?
|
197
|
+
Still a little confused about something?
|
198
|
+
Don't despair, there are still more resources available!
|
199
|
+
|
200
|
+
* Read the source code!
|
201
|
+
It's very straightforward,
|
202
|
+
and make_resourceful is built to encourage overriding methods
|
203
|
+
and hacking the source.
|
204
|
+
* Nathan Weizenbaum has some good blog posts about make_resourceful.
|
205
|
+
They may be a little outdated, but they should still be useful and explanatory.
|
206
|
+
* On nesting and associations: {here}[http://nex-3.com/posts/55-nesting-and-make_resourceful].
|
207
|
+
* An overview of make_resourceful 0.2.0 and 0.2.2: {here}[http://localhost:3000/posts/54-make_resourceful-0-2-0].
|
208
|
+
* On Resourceful::Builder#publish
|
209
|
+
and Resourceful::Serialize:
|
210
|
+
{here}[http://nex-3.com/posts/35-make_resourceful-the-basics-of-publish] and
|
211
|
+
{here}[http://nex-3.com/posts/36-make_resourceful-publish-extras].
|
212
|
+
* There's an excellent, active Google Group http://groups.google.com/group/make_resourceful
|
213
|
+
where people will be happy to answer your questions.
|
214
|
+
|
215
|
+
---
|
216
|
+
|
217
|
+
Copyright 2007-2010 Hampton Catlin and Nathan Weizenbaum.
|
218
|
+
Contributions by:
|
219
|
+
|
220
|
+
* Russell Norris
|
221
|
+
* Jonathan Linowes
|
222
|
+
* Cristi Balan
|
223
|
+
* Mike Ferrier
|
224
|
+
* James Golick
|
225
|
+
* Don Petersen
|
226
|
+
* Alex Ross
|
227
|
+
* Tom Stuart
|
228
|
+
* Glenn Powell
|
229
|
+
* Johannes Jörg Schmidt
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0
|
@@ -0,0 +1,11 @@
|
|
1
|
+
|
2
|
+
class MakeResourcefulTie < Rails::Railtie
|
3
|
+
initializer "my_railtie.configure_rails_initialization" do
|
4
|
+
require_relative 'resourceful/maker'
|
5
|
+
ActionController::Base.extend Resourceful::Maker
|
6
|
+
end
|
7
|
+
|
8
|
+
generators do
|
9
|
+
#require_relative 'resourceful/generators/resourceful_scaffold/resourceful_scaffold_generator'
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# The module containing all the code for make_resourceful.
|
2
|
+
#
|
3
|
+
# For methods available in the +make_resourceful+ block,
|
4
|
+
# see Resourceful::Builder.
|
5
|
+
#
|
6
|
+
# For helper methods and methods you can override
|
7
|
+
# to customize the behavior of your actions,
|
8
|
+
# see Resourceful::Default::Accessors
|
9
|
+
# and Resourceful::Default::URLs.
|
10
|
+
module Resourceful
|
11
|
+
# We want to define some stuff before we load other modules
|
12
|
+
|
13
|
+
# The default actions generated by make_resourceful.
|
14
|
+
ACTIONS = [:index, :show, :edit, :update, :create, :new, :destroy]
|
15
|
+
|
16
|
+
# The actions that modify the database.
|
17
|
+
MODIFYING_ACTIONS = [:update, :create, :destroy]
|
18
|
+
|
19
|
+
# The actions that act on multiple records.
|
20
|
+
PLURAL_ACTIONS = [:index]
|
21
|
+
|
22
|
+
# The actions that act on just one record.
|
23
|
+
SINGULAR_ACTIONS = ACTIONS - PLURAL_ACTIONS
|
24
|
+
|
25
|
+
# The actions that act on just one record.
|
26
|
+
SINGULAR_PRELOADED_ACTIONS = SINGULAR_ACTIONS - [:new, :create]
|
27
|
+
end
|
28
|
+
|
29
|
+
require 'resourceful/default/accessors'
|
30
|
+
require 'resourceful/default/responses'
|
31
|
+
require 'resourceful/default/callbacks'
|
32
|
+
require 'resourceful/default/urls'
|
33
|
+
|
34
|
+
# All modules included by this module
|
35
|
+
# are made available to the controller as accessors.
|
36
|
+
module Resourceful::Base
|
37
|
+
@@made_resourceful_callbacks = []
|
38
|
+
|
39
|
+
# This method is meant to be called by included classes.
|
40
|
+
# It takes a block of the same form as that given to Maker#make_resourceful.
|
41
|
+
# The Maker will then run that block
|
42
|
+
# along with the blocks given by the individual controllers.
|
43
|
+
def self.made_resourceful(&block)
|
44
|
+
if block
|
45
|
+
@@made_resourceful_callbacks << block
|
46
|
+
else
|
47
|
+
@@made_resourceful_callbacks
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
include Resourceful::Default::Accessors
|
52
|
+
include Resourceful::Default::Responses
|
53
|
+
include Resourceful::Default::Callbacks
|
54
|
+
include Resourceful::Default::URLs
|
55
|
+
|
56
|
+
# FIXME HACK
|
57
|
+
# making methods assigned to controller private
|
58
|
+
# prevents access from dispatcher.
|
59
|
+
private *Resourceful::Default::Accessors.public_instance_methods
|
60
|
+
private *Resourceful::Default::Responses.public_instance_methods
|
61
|
+
private *Resourceful::Default::Callbacks.public_instance_methods
|
62
|
+
private *Resourceful::Default::URLs.public_instance_methods
|
63
|
+
end
|