make_resourceful 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/Rakefile +31 -0
  2. data/Readme.rdoc +229 -0
  3. data/VERSION +1 -0
  4. data/lib/make_resourceful.rb +11 -0
  5. data/lib/resourceful/base.rb +63 -0
  6. data/lib/resourceful/builder.rb +405 -0
  7. data/lib/resourceful/default/accessors.rb +418 -0
  8. data/lib/resourceful/default/actions.rb +101 -0
  9. data/lib/resourceful/default/callbacks.rb +51 -0
  10. data/lib/resourceful/default/responses.rb +118 -0
  11. data/lib/resourceful/default/urls.rb +136 -0
  12. data/lib/resourceful/generators/resourceful_scaffold/resourceful_scaffold_generator.rb +87 -0
  13. data/lib/resourceful/generators/resourceful_scaffold/templates/controller.rb +5 -0
  14. data/lib/resourceful/generators/resourceful_scaffold/templates/fixtures.yml +10 -0
  15. data/lib/resourceful/generators/resourceful_scaffold/templates/functional_test.rb +50 -0
  16. data/lib/resourceful/generators/resourceful_scaffold/templates/helper.rb +2 -0
  17. data/lib/resourceful/generators/resourceful_scaffold/templates/migration.rb +13 -0
  18. data/lib/resourceful/generators/resourceful_scaffold/templates/model.rb +2 -0
  19. data/lib/resourceful/generators/resourceful_scaffold/templates/unit_test.rb +7 -0
  20. data/lib/resourceful/generators/resourceful_scaffold/templates/view__form.haml +5 -0
  21. data/lib/resourceful/generators/resourceful_scaffold/templates/view_edit.haml +11 -0
  22. data/lib/resourceful/generators/resourceful_scaffold/templates/view_index.haml +5 -0
  23. data/lib/resourceful/generators/resourceful_scaffold/templates/view_new.haml +9 -0
  24. data/lib/resourceful/generators/resourceful_scaffold/templates/view_partial.haml +12 -0
  25. data/lib/resourceful/generators/resourceful_scaffold/templates/view_show.haml +14 -0
  26. data/lib/resourceful/maker.rb +92 -0
  27. data/lib/resourceful/response.rb +33 -0
  28. data/lib/resourceful/serialize.rb +185 -0
  29. data/spec/accessors_spec.rb +474 -0
  30. data/spec/actions_spec.rb +310 -0
  31. data/spec/base_spec.rb +12 -0
  32. data/spec/builder_spec.rb +332 -0
  33. data/spec/callbacks_spec.rb +71 -0
  34. data/spec/integration_spec.rb +394 -0
  35. data/spec/maker_spec.rb +91 -0
  36. data/spec/response_spec.rb +37 -0
  37. data/spec/responses_spec.rb +314 -0
  38. data/spec/serialize_spec.rb +133 -0
  39. data/spec/urls_spec.rb +282 -0
  40. 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