restful_controller 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +151 -0
  4. data/Rakefile +44 -0
  5. data/lib/restful/actions.rb +168 -0
  6. data/lib/restful/base.rb +321 -0
  7. data/lib/restful/dummy_responder.rb +11 -0
  8. data/lib/restful/version.rb +7 -0
  9. data/lib/restful.rb +7 -0
  10. data/lib/tasks/resourceful_tasks.rake +4 -0
  11. data/test/actions_definition_test.rb +104 -0
  12. data/test/alternates_controller_test.rb +8 -0
  13. data/test/base_controller_test.rb +8 -0
  14. data/test/blocks_controller_test.rb +28 -0
  15. data/test/custom_notices_controller_test.rb +22 -0
  16. data/test/dummy/README.rdoc +28 -0
  17. data/test/dummy/Rakefile +6 -0
  18. data/test/dummy/app/assets/javascripts/application.js +13 -0
  19. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  20. data/test/dummy/app/controllers/alternates_controller.rb +49 -0
  21. data/test/dummy/app/controllers/application_controller.rb +5 -0
  22. data/test/dummy/app/controllers/base_controller.rb +5 -0
  23. data/test/dummy/app/controllers/blocks_controller.rb +19 -0
  24. data/test/dummy/app/controllers/custom_notices_controller.rb +14 -0
  25. data/test/dummy/app/controllers/documents_controller.rb +11 -0
  26. data/test/dummy/app/controllers/home_controller.rb +5 -0
  27. data/test/dummy/app/helpers/application_helper.rb +2 -0
  28. data/test/dummy/app/models/document.rb +3 -0
  29. data/test/dummy/app/views/base/edit.html.erb +3 -0
  30. data/test/dummy/app/views/base/index.html.erb +3 -0
  31. data/test/dummy/app/views/base/new.html.erb +3 -0
  32. data/test/dummy/app/views/base/show.html.erb +1 -0
  33. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  34. data/test/dummy/bin/bundle +3 -0
  35. data/test/dummy/bin/rails +4 -0
  36. data/test/dummy/bin/rake +4 -0
  37. data/test/dummy/config/application.rb +29 -0
  38. data/test/dummy/config/boot.rb +5 -0
  39. data/test/dummy/config/database.yml +25 -0
  40. data/test/dummy/config/environment.rb +5 -0
  41. data/test/dummy/config/environments/development.rb +29 -0
  42. data/test/dummy/config/environments/production.rb +80 -0
  43. data/test/dummy/config/environments/test.rb +36 -0
  44. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  45. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  46. data/test/dummy/config/initializers/generators.rb +6 -0
  47. data/test/dummy/config/initializers/inflections.rb +16 -0
  48. data/test/dummy/config/initializers/mime_types.rb +5 -0
  49. data/test/dummy/config/initializers/secret_token.rb +12 -0
  50. data/test/dummy/config/initializers/session_store.rb +3 -0
  51. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  52. data/test/dummy/config/locales/en.yml +23 -0
  53. data/test/dummy/config/routes.rb +62 -0
  54. data/test/dummy/config.ru +4 -0
  55. data/test/dummy/db/development.sqlite3 +0 -0
  56. data/test/dummy/db/migrate/20130703024719_create_documents.rb +9 -0
  57. data/test/dummy/db/schema.rb +22 -0
  58. data/test/dummy/db/test.sqlite3 +0 -0
  59. data/test/dummy/log/development.log +11 -0
  60. data/test/dummy/log/test.log +75091 -0
  61. data/test/dummy/public/404.html +58 -0
  62. data/test/dummy/public/422.html +58 -0
  63. data/test/dummy/public/500.html +57 -0
  64. data/test/dummy/public/favicon.ico +0 -0
  65. data/test/dummy/test/fixtures/documents.yml +7 -0
  66. data/test/dummy/test/models/document_test.rb +7 -0
  67. data/test/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  68. data/test/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  69. data/test/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  70. data/test/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  71. data/test/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  72. data/test/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  73. data/test/resourceful_test.rb +8 -0
  74. data/test/support/base_actions.rb +130 -0
  75. data/test/test_helper.rb +39 -0
  76. metadata +268 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 15e4f8de8ab53f6ca410c248e9b84d4ba7afe2c4
4
+ data.tar.gz: 21f2de7e065969b0f56fda318a94bca1aacdb428
5
+ SHA512:
6
+ metadata.gz: fcb5302fa9589c455bb6c4e0ee34e5e7320e041d08746c2abbb377beb8d4fd7f1a03068046feb3758cfb653b22892a9f5a6681cc55301ab9b4dae3cb8ec222a9
7
+ data.tar.gz: ccd5c3dafaab3fb91b0df5da70da7a74aa3b43849b2fddfe28ea65983b86ba86fbff0eeec3af493aae03ced53dc134cfd854e10597b137e5b98b670412653edd
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,151 @@
1
+ {<img src="https://travis-ci.org/mariochavez/restful.png?branch=master" alt="Build Status" />}[https://travis-ci.org/mariochavez/restful]
2
+ = Restful
3
+ Restful helps to keep Controllers DRY, removing repetitive code from basic REST actions.
4
+
5
+ Very basic controllers repeat over and over the same code for REST actions, but if you do TDD - and should be doing it -, the code to test these controllers is also repetitive and boring.
6
+
7
+ Restful helps you to get rid of that repetitive and boring code with a very simple defaults for RESTful controllers.
8
+
9
+ But wait, this is not a new idea, there is already Inherited Resources (https://github.com/josevalim/inherited_resources) gem that allows you to do the same and maybe even more; so why write another library?
10
+
11
+ It's simple, I had the time and I wanted to try it. This library does not cover all the cases that Inherited Resources cover, but it's good enough for so many controllers. Also all the source code is documented and quite simple to follow in case that you want to learn how is it implemented.
12
+
13
+ == Installation
14
+ Resful requires Ruby on Rails 4.0 and Ruby 2.0.
15
+
16
+ To install it, just add the Restful gem to your Gemfile:
17
+
18
+ gem 'restful'
19
+
20
+ Run bundler command and you are all set.
21
+
22
+ == Usage
23
+ Restful module must be included on each controller that you want to become Restful. Also it's need for these controllers to include the respond_to macro, which will especify the format to which our controllers will respond to.
24
+
25
+ Finally the resful macro is need it to setup our controller.
26
+ This macro accepts 3 params:
27
+
28
+ === Params
29
+ * model: A requires parameter which is a symbol of the model name.
30
+ * strong_params: A symbol, a string or a proc for the method that should apply the strong parameters to allow Active Model mass assignments.
31
+ * actions: An array of actions that a controller should implement, if none is passed then all seven REST actions are defined.
32
+
33
+ === Examples
34
+
35
+ Simple:
36
+
37
+ class DocumentsController < ApplicationController
38
+ include restful
39
+ respond_to :html
40
+
41
+ restful model: :document, strong_params: :document_params
42
+ end
43
+
44
+ This definition will create the seven REST actions for Document model,
45
+ this setup a single object instance variable @document and a collection
46
+ variable @documents.
47
+
48
+ It's expected that this controller will provide a method
49
+ document_params which will be used to allow mass assignments.
50
+
51
+ Strong params variation:
52
+
53
+ class DocumentsController < ApplicationController
54
+ include restful
55
+ respond_to :html
56
+
57
+ restful model: :document,
58
+ strong_params: ->(params){ params.require(:document).permit :name }
59
+ end
60
+
61
+ In this example instead of providing a strong params method by string
62
+ or symbol, a proc is passed to do the same job.
63
+
64
+ Listed actions variation:
65
+
66
+ The last parameter *actions* allows you to list in an array the actions
67
+ that you want your controller to have:
68
+
69
+ class DocumentsController < ApplicationController
70
+ include restful
71
+ respond_to :html
72
+
73
+ restful model: :document, strong_params: :document_params,
74
+ actions: [:index, :show]
75
+ end
76
+
77
+ In this case our controller will only respond to those 2 actions. We
78
+ can do it the other way, indicate list of actions that shouldn't be
79
+ defined:
80
+
81
+ class DocumentsController < ApplicationController
82
+ include restful
83
+ respond_to :html
84
+
85
+ restful model: :document, strong_params: :document_params,
86
+ actions: [:all, except: [:destroy, :show]]
87
+ end
88
+
89
+ For this last example all seven REST actions will be defined but :destroy and :show
90
+
91
+ == Actions
92
+
93
+ Used as a template for all Restful controller actions
94
+
95
+ By default an action is created with an alias method with a bang(!).
96
+ If you need to override an action, just redefine it in you controller,
97
+ to call this base action, just call the bang version:
98
+
99
+ def index
100
+ @documents = Document.all
101
+ index!
102
+ end
103
+
104
+ This will allow you to let Restful to continue with the action flow.
105
+
106
+ When overriding an action, just be sure to have inside de action variables
107
+ with the name of the defined model, doing this will allow you to call the
108
+ bang action version:
109
+
110
+ def new
111
+ @document = Document.new name: 'Default name'
112
+ new!
113
+ end
114
+
115
+ For actions like :create and :update a notice or alert can be passed as
116
+ option to be set in flash object:
117
+
118
+ def create
119
+ @document = Document.new secure_params
120
+ create!(notice: 'Hey a new document was created!')
121
+ end
122
+
123
+ Also a block can be passed for the happy path to tell the application to
124
+ where redirect:
125
+
126
+ def update
127
+ @document = Document.find params[:id]
128
+ @document.update_attributes secure_params
129
+
130
+ update!(notice: 'Document has been updated'){ root_path }
131
+ end
132
+
133
+ It's also possible to supply a block for the non-happy path, this means
134
+ proving a dual block for success and failure results from our action:
135
+
136
+ def update
137
+ @document = Document.find params[:id]
138
+ @document = update_attributes secure_params
139
+
140
+ update! do |success, failure|
141
+ success.html { redirect_to root_path }
142
+ failure.html { render :custom }
143
+ end
144
+ end
145
+
146
+ == Bugs and feedback
147
+ Use issues at Github to report bugs or give feedback.
148
+
149
+ For detailed documentation look at http://rdoc.info/github/mariochavez/restful/master/frames
150
+
151
+ Copyright © 2013 Mario Alberto Chavez. This project uses MIT-LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,44 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Restful'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ Bundler::GemHelper.install_tasks
18
+
19
+ require 'rake/testtask'
20
+
21
+ desc 'Run rubocop checks'
22
+ task :rubocop do
23
+ sh 'rubocop lib test'
24
+ end
25
+
26
+ desc 'Run flay checks'
27
+ task :flay do
28
+ sh 'find lib -name \*.rb | xargs flog'
29
+ end
30
+
31
+ desc 'Run flog checks'
32
+ task :flog do
33
+ sh 'flay lib/*.rb'
34
+ end
35
+
36
+ Rake::TestTask.new(:test) do |t|
37
+ t.libs << 'lib'
38
+ t.libs << 'test'
39
+ t.pattern = 'test/**/*_test.rb'
40
+ t.verbose = false
41
+ end
42
+
43
+
44
+ task default: :test
@@ -0,0 +1,168 @@
1
+ module Restful
2
+ ##
3
+ # = Actions
4
+ #
5
+ # Used as a template for all Restful controller actions
6
+ #
7
+ # By default an action is created with an alias method with a bang(!).
8
+ # If you need to override an action, just redefine it in you controller,
9
+ # to call this base action, just call the bang version:
10
+ #
11
+ # def index
12
+ # @documents = Document.all
13
+ # index!
14
+ # end
15
+ #
16
+ # This will allow you to let Restful to continue with the action flow.
17
+ #
18
+ # When overriding an action, just be sure to have inside de action variables
19
+ # with the name of the defined model, doing this will allow you to call the
20
+ # bang action version:
21
+ #
22
+ # def new
23
+ # @document = Document.new name: 'Default name'
24
+ # new!
25
+ # end
26
+ #
27
+ # For actions like :create and :update a notice or alert can be passed as
28
+ # option to be set in flash object:
29
+ #
30
+ # def create
31
+ # @document = Document.new secure_params
32
+ # create!(notice: 'Hey a new document was created!')
33
+ # end
34
+ #
35
+ # Also a block can be passed for the happy path to tell the application to
36
+ # where redirect:
37
+ #
38
+ # def update
39
+ # @document = Document.find params[:id]
40
+ # @document.update_attributes secure_params
41
+ #
42
+ # update!(notice: 'Document has been updated'){ root_path }
43
+ # end
44
+ #
45
+ # It's also possible to supply a block for the non-happy path, this means
46
+ # proving a dual block for success and failure results from our action:
47
+ #
48
+ # def update
49
+ # @document = Document.find params[:id]
50
+ # @document = update_attributes secure_params
51
+ #
52
+ # update! do |success, failure|
53
+ # success.html { redirect_to root_path }
54
+ # failure.html { render :custom }
55
+ # end
56
+ # end
57
+ #
58
+ # Be aware that Restful require that your controllers define to what they
59
+ # respond, it could be :html, :json or anything else, just remember to add
60
+ # the respond_to macro to the top of your controller's definition:
61
+ #
62
+ # class DocumentsController < ApplicationController
63
+ # respond_to :html
64
+ # end
65
+ #
66
+ module Actions
67
+ ##
68
+ # index action, this set a collection of objects to an instance variable
69
+ # which can be accessed from the view using the collection helper method.
70
+ # The instance variable name is a pluralization of the model name defined
71
+ # in the restful macro.
72
+ def index(options = {}, &block)
73
+ respond_with(collection, options, &block)
74
+ end
75
+ alias_method :index!, :index
76
+
77
+ ##
78
+ # new action, creates a new object and sets an instance variable which can
79
+ # be accessed from the view using the resource helper method. The instance
80
+ # variable is named after the model name defined in the restful macro.
81
+ def new(options = {}, &block)
82
+ respond_with(build_resource, options, &block)
83
+ end
84
+ alias_method :new!, :new
85
+
86
+ ##
87
+ # create action, creates a new object off the received params and sets an
88
+ # instance variable if record is saved then a redirect to index action is
89
+ # made.
90
+ #
91
+ # If record fail to be saved, the new form is renderd and the instance
92
+ # variable can be accessed from the view using the resource
93
+ # helper method. The instance variable is named after the model name
94
+ # defined in the restful macro.
95
+ def create(options = {}, &block)
96
+ object = get_resource_ivar || create_resource
97
+
98
+ options[:location] = collection_path if object.errors.empty?
99
+
100
+ respond_with_dual(object, options, &block)
101
+ end
102
+ alias_method :create!, :create
103
+
104
+ ##
105
+ # edit action, finds an object based on the passed id, if no object is
106
+ # found an ActiveRecord::RecordNotFound is raised.
107
+ #
108
+ # If the record is found then an instance variable, based on the model
109
+ # name set in the restful macro.
110
+ #
111
+ # This variable can be accessed in teh form using the resource helper
112
+ # method.
113
+ def edit(options = {}, &block)
114
+ object = get_resource_ivar || find_resource
115
+
116
+ respond_with(object, options, &block)
117
+ end
118
+ alias_method :edit!, :edit
119
+
120
+ ##
121
+ # update action, finds an object based on the passed id, if no object is
122
+ # found an ActiveRecord::RecordNotFound is raised. If the record is found
123
+ # then it's updated from params using ActiveRecord update_attributes method
124
+ # and an instance variable is set with the object, variable name is based
125
+ # on the model name set in the restful macro.
126
+ #
127
+ # If update_attributes fail, then edit form is displayed, and the instance
128
+ # variable can be accessed in teh form using the resource helper method.
129
+ #
130
+ # If update_attributes success, a redirect to the index action is made.
131
+ def update(options = {}, &block)
132
+ object = get_resource_ivar || find_and_update_resource
133
+
134
+ options[:location] = collection_path if object.errors.empty?
135
+
136
+ respond_with_dual(object, options, &block)
137
+ end
138
+ alias_method :update!, :update
139
+
140
+ ##
141
+ # show action, finds an object based on the passed id, if no object is
142
+ # found an ActiveRecord::RecordNotFound is raised. If the record is found
143
+ # then an instance variable is set with the object, variable name is based
144
+ # on the model name set in the restful macro.
145
+ def show(options = {}, &block)
146
+ object = get_resource_ivar || find_resource
147
+
148
+ respond_with(object, options, &block)
149
+ end
150
+ alias_method :show!, :show
151
+
152
+ ##
153
+ # destroy action, finds an object based on the passed id, if no object is
154
+ # found an ActiveRecord::RecordNotFound is raised. If the record is found
155
+ # then it's destroyed and a redirect to the index action is made.
156
+ def destroy(options = {}, &block)
157
+ object = get_resource_ivar || find_resource
158
+
159
+ object.destroy
160
+ options[:location] = collection_path
161
+
162
+ respond_with(object, options, &block)
163
+ end
164
+ alias_method :destroy!, :destroy
165
+
166
+ protected :index!, :new!, :create!, :edit!, :update!, :show!, :destroy!
167
+ end
168
+ end