resource_this 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3d1ca98d91b7f77a27fd92f24d30117981c181d9
4
+ data.tar.gz: cb660dc5474ca506caa49a54c381ac8b44816450
5
+ SHA512:
6
+ metadata.gz: b59545fc746ce5d24ebdfd6b26d3dd6ef950ab0715ee6bfc63ea85eadc0a3cbebd5c622094e98865b06883364594ad5d98f627800e5fa844d28119d9e2e38a9c
7
+ data.tar.gz: c6f07405700cb3f79e0dc2fe1e3842508120d3e21a3438c9ef9ab3f2fcc0d40ad845817650c47577ba151e237937c9dda664e232fb1080255e29003f6663387b
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ doc/
2
+ pkg/
3
+ Gemfile.lock
4
+ *.gemfile.lock
5
+ coverage
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # 1.0.0
2
+
3
+ * Gem-ification work
4
+ * Revert returning true { ... }, since it no longer exists in Rails 3.2
5
+
6
+ # Pre 1.0.0
7
+
8
+ * Added resource_this generator
9
+ * Add support for :path_prefix options on resource_this. Useful for admin namespaced controllers
10
+ * wrap some before_filters in returning true { ... } do
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ar_protobuf_store.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2004-2007 Jesse Newland
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.md ADDED
@@ -0,0 +1,200 @@
1
+ resouce_this
2
+ ===========
3
+
4
+ Not scaffolding. Resourcing. Creates extremely customizable resource controllers with one line of code.
5
+
6
+
7
+ ```ruby
8
+ class PostsController < ActionController::Base
9
+ resource_this
10
+ end
11
+ ```
12
+
13
+ ...will generate the following code:
14
+
15
+ ```ruby
16
+ class PostsController < ActionController::Base
17
+ before_filter :load_post, :only => [ :show, :edit, :update, :destroy ]
18
+ before_filter :load_posts, :only => [ :index ]
19
+ before_filter :new_post, :only => [ :new ]
20
+ before_filter :create_post, :only => [ :create ]
21
+ before_filter :update_post, :only => [ :update ]
22
+ before_filter :destroy_post, :only => [ :destroy ]
23
+
24
+ protected
25
+ def load_post
26
+ @post = Post.find(params[:id])
27
+ end
28
+
29
+ def new_post
30
+ @post = Post.new
31
+ end
32
+
33
+ def create_post
34
+ @post = Post.new(params[:post])
35
+ @created = @post.save
36
+ return true
37
+ end
38
+
39
+ def update_post
40
+ @updated = @post.update_attributes(params[:post])
41
+ return true
42
+ end
43
+
44
+ def destroy_post
45
+ @post = @post.destroy
46
+ end
47
+
48
+ def load_posts
49
+ @posts = Post.find(:all)
50
+ end
51
+
52
+ public
53
+ def index
54
+ respond_to do |format|
55
+ format.html
56
+ format.xml { render :xml => @posts }
57
+ format.js
58
+ end
59
+ end
60
+
61
+ def show
62
+ respond_to do |format|
63
+ format.html
64
+ format.xml { render :xml => @post }
65
+ format.js
66
+ end
67
+ end
68
+
69
+ def new
70
+ respond_to do |format|
71
+ format.html { render :action => :edit }
72
+ format.xml { render :xml => @post }
73
+ format.js
74
+ end
75
+ end
76
+
77
+ def create
78
+ respond_to do |format|
79
+ if @created
80
+ flash[:notice] = 'Post was successfully created.'
81
+ format.html { redirect_to @post }
82
+ format.xml { render :xml => @post, :status => :created, :location => @post }
83
+ format.js
84
+ else
85
+ format.html { render :action => :new }
86
+ format.xml { render :xml => @post.errors, :status => :unprocessable_entity }
87
+ format.js
88
+ end
89
+ end
90
+ end
91
+
92
+ def edit
93
+ respond_to do |format|
94
+ format.html
95
+ format.js
96
+ end
97
+ end
98
+
99
+ def update
100
+ respond_to do |format|
101
+ if @updated
102
+ flash[:notice] = 'Post was successfully updated.'
103
+ format.html { redirect_to @post }
104
+ format.xml { head :ok }
105
+ format.js
106
+ else
107
+ format.html { render :action => :edit }
108
+ format.xml { render :xml => @post.errors, :status => :unprocessable_entity }
109
+ format.js
110
+ end
111
+ end
112
+ end
113
+
114
+ def destroy
115
+ respond_to do |format|
116
+ format.html { redirect_to :action => posts_url }
117
+ format.xml { head :ok }
118
+ format.js
119
+ end
120
+ end
121
+ end
122
+ ```
123
+
124
+ Nested Resources
125
+ ===========
126
+
127
+ ```ruby
128
+ class CommentsController < ActionController::Base
129
+ resource_this :nested => [:posts]
130
+ end
131
+ ```
132
+
133
+ This generates a very similar controller to the one above with adjusted redirects and one additional before_filter / loader method pair to grab the parent resource. In this case:
134
+
135
+ ```ruby
136
+ before_filter :load_post
137
+
138
+ def load_post
139
+ @post = Post.find(params[:post_id])
140
+ end
141
+ ```
142
+
143
+ Sorting, etc
144
+ ===========
145
+
146
+ ```ruby
147
+ class CommentsController < ActionController::Base
148
+ resource_this :finder_options => {:order => 'created_on'}
149
+ end
150
+ ```
151
+
152
+ ...or, for lazily evaluated sorting options:
153
+
154
+ ```ruby
155
+ class CommentsController < ActionController::Base
156
+ resource_this :finder_options => Proc.new { finder_options }
157
+
158
+ protected
159
+
160
+ def finder_options
161
+ order = case params[:sort]
162
+ when 'date_reverse' then 'created_on desc'
163
+ else 'created_on'
164
+ end
165
+ {:order => order, :limit => params[:limit] || 10 }
166
+ end
167
+
168
+ end
169
+ ```
170
+
171
+ will_paginate
172
+ ===========
173
+
174
+ will_paginate support is baked right in:
175
+
176
+ ```ruby
177
+ class CommentsController < ActionController::Base
178
+ resource_this :will_paginate => true
179
+ end
180
+ ```
181
+
182
+ This works with the :finder_options option as well
183
+
184
+ Opinionated Software
185
+ ===========
186
+
187
+ The separation of logic - DB operations in before_filters, rendering in the standard resource controller methods - makes this approach ridiculously easy to customize. Need to load an additional object for the :show action? Slap another before_filter on it. Need to change the path that the :update action redirects to? Override the :update action with your new rendering behavior.
188
+
189
+ Generator
190
+ ===========
191
+
192
+ A resource_this generator is included - does the same thing as the 'resource' generator but adds 'resource_this' to the generated controller.
193
+
194
+ Questions? Comments? Flames? Patches?
195
+ ===========
196
+ jnewland@gmail.com
197
+
198
+ Copyright
199
+ ===========
200
+ Copyright (c) 2007 Jesse Newland, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ require "rubygems"
4
+ require "rake"
5
+ require "rake/testtask"
6
+
7
+ desc "Default: run unit tests."
8
+ task :default => :test
9
+
10
+ desc "Test the resource_this plugin."
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs << "lib"
13
+ t.pattern = "test/**/*_test.rb"
14
+ t.verbose = true
15
+ end
16
+
17
+ begin
18
+ gem 'rubygems-tasks', '~> 0.2'
19
+ require 'rubygems/tasks'
20
+
21
+ Gem::Tasks.new
22
+ rescue LoadError => e
23
+ warn e.message
24
+ warn "Run `gem install rubygems-tasks` to install Gem::Tasks."
25
+ end
@@ -0,0 +1,24 @@
1
+ Description:
2
+ Stubs out a new resource including an empty model and controller suitable
3
+ for a restful, resource-oriented application. Pass the singular model name,
4
+ either CamelCased or under_scored, as the first argument, and an optional
5
+ list of attribute pairs.
6
+
7
+ Attribute pairs are column_name:sql_type arguments specifying the
8
+ model's attributes. Timestamps are added by default, so you don't have to
9
+ specify them by hand as 'created_at:datetime updated_at:datetime'.
10
+
11
+ You don't have to think up every attribute up front, but it helps to
12
+ sketch out a few so you can start working with the resource immediately.
13
+
14
+ This creates a model, controller, tests and fixtures for both, and the
15
+ corresponding map.resources declaration in config/routes.rb
16
+
17
+ This generates a DRY resource controller using resource_this:
18
+
19
+ http://jnewland.com/svn/public/ruby/rails/plugins/resource_this/README
20
+
21
+ Examples:
22
+ `./script/generate resource_this post` # no attributes
23
+ `./script/generate resource_this post title:string body:text published:boolean`
24
+ `./script/generate resource_this purchase order_id:integer amount:decimal`
@@ -0,0 +1,72 @@
1
+ class ResourceThisGenerator < Rails::Generator::NamedBase
2
+ default_options :skip_migration => false
3
+
4
+ attr_reader :controller_name,
5
+ :controller_class_path,
6
+ :controller_file_path,
7
+ :controller_class_nesting,
8
+ :controller_class_nesting_depth,
9
+ :controller_class_name,
10
+ :controller_singular_name,
11
+ :controller_plural_name
12
+ alias_method :controller_file_name, :controller_singular_name
13
+ alias_method :controller_table_name, :controller_plural_name
14
+
15
+ def initialize(runtime_args, runtime_options = {})
16
+ super
17
+
18
+ @controller_name = @name.pluralize
19
+
20
+ base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name)
21
+ @controller_class_name_without_nesting, @controller_singular_name, @controller_plural_name = inflect_names(base_name)
22
+
23
+ if @controller_class_nesting.empty?
24
+ @controller_class_name = @controller_class_name_without_nesting
25
+ else
26
+ @controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}"
27
+ end
28
+ end
29
+
30
+ def manifest
31
+ record do |m|
32
+ # Check for class naming collisions.
33
+ m.class_collisions(controller_class_path, "#{controller_class_name}Controller", "#{controller_class_name}Helper")
34
+ m.class_collisions(class_path, "#{class_name}")
35
+
36
+ # Controller, helper, views, and test directories.
37
+ m.directory(File.join('app/models', class_path))
38
+ m.directory(File.join('app/controllers', controller_class_path))
39
+ m.directory(File.join('app/helpers', controller_class_path))
40
+ m.directory(File.join('app/views', controller_class_path, controller_file_name))
41
+ m.directory(File.join('test/functional', controller_class_path))
42
+ m.directory(File.join('test/unit', class_path))
43
+
44
+ m.dependency 'model', [singular_name] + @args, :collision => :skip
45
+
46
+ m.template(
47
+ 'controller.rb', File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb")
48
+ )
49
+
50
+ m.template('functional_test.rb', File.join('test/functional', controller_class_path, "#{controller_file_name}_controller_test.rb"))
51
+ m.template('helper.rb', File.join('app/helpers', controller_class_path, "#{controller_file_name}_helper.rb"))
52
+
53
+ m.route_resources controller_file_name
54
+ end
55
+ end
56
+
57
+ protected
58
+ def banner
59
+ "Usage: #{$0} resource_this ModelName [field:type, field:type]"
60
+ end
61
+
62
+ def add_options!(opt)
63
+ opt.separator ''
64
+ opt.separator 'Options:'
65
+ opt.on("--skip-migration",
66
+ "Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
67
+ end
68
+
69
+ def model_name
70
+ class_name.demodulize
71
+ end
72
+ end
@@ -0,0 +1,3 @@
1
+ class <%= controller_class_name %>Controller < ApplicationController
2
+ resource_this
3
+ end
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) + '<%= '/..' * controller_class_nesting_depth %>/../test_helper'
2
+ require '<%= controller_file_path %>_controller'
3
+
4
+ # Re-raise errors caught by the controller.
5
+ class <%= controller_class_name %>Controller; def rescue_action(e) raise e end; end
6
+
7
+ class <%= controller_class_name %>ControllerTest < Test::Unit::TestCase
8
+ fixtures :<%= table_name %>
9
+
10
+ def setup
11
+ @controller = <%= controller_class_name %>Controller.new
12
+ @request = ActionController::TestRequest.new
13
+ @response = ActionController::TestResponse.new
14
+ end
15
+
16
+ def test_should_get_index
17
+ get :index
18
+ assert_response :success
19
+ assert assigns(:<%= table_name %>)
20
+ end
21
+
22
+ def test_should_get_new
23
+ @request.accept = 'application/xml'
24
+ get :new
25
+ assert_response :success
26
+ end
27
+
28
+ def test_should_create_<%= file_name %>
29
+ assert_difference('<%= class_name %>.count') do
30
+ post :create, :<%= file_name %> => { }
31
+ end
32
+
33
+ assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>))
34
+ end
35
+
36
+ def test_should_show_<%= file_name %>
37
+ @request.accept = 'application/xml'
38
+ get :show, :id => 1
39
+ assert_response :success
40
+ end
41
+
42
+ def test_should_get_edit
43
+ #TODO: replace this with a real test once views are in place
44
+ assert true
45
+ end
46
+
47
+ def test_should_update_<%= file_name %>
48
+ put :update, :id => 1, :<%= file_name %> => { }
49
+ assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>))
50
+ end
51
+
52
+ def test_should_destroy_<%= file_name %>
53
+ assert_difference('<%= class_name %>.count', -1) do
54
+ delete :destroy, :id => 1
55
+ end
56
+
57
+ assert_redirected_to <%= table_name %>_path
58
+ end
59
+ end
@@ -0,0 +1,2 @@
1
+ module <%= controller_class_name %>Helper
2
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ ActionController::Base.send :include, ResourceThis
@@ -0,0 +1,208 @@
1
+ module ResourceThis # :nodoc:
2
+ def self.included(base)
3
+ base.extend(ClassMethods)
4
+ end
5
+
6
+ module ClassMethods
7
+ def resource_this(options = {})
8
+ options.assert_valid_keys(:class_name, :will_paginate, :finder_options, :nested, :path_prefix)
9
+
10
+ singular_name = controller_name.singularize
11
+ singular_name = options[:class_name].downcase.singularize unless options[:class_name].nil?
12
+ class_name = options[:class_name] || singular_name.camelize
13
+ plural_name = singular_name.pluralize
14
+ will_paginate_index = options[:will_paginate] || false
15
+ resource_url = "#{singular_name}_url(@#{singular_name})"
16
+ collection_url = "#{plural_name}_url"
17
+ resource_url = options[:path_prefix] + resource_url unless options[:path_prefix].nil?
18
+ collection_url = options[:path_prefix] + collection_url unless options[:path_prefix].nil?
19
+
20
+ class_attribute :resource_this_finder_options
21
+ self.resource_this_finder_options = options[:finder_options] || {}
22
+
23
+ unless options[:nested].nil?
24
+ nested = options[:nested].to_s.singularize
25
+ nested_class = nested.camelize
26
+ nested_resource_url = "#{nested}_#{singular_name}_url(" + [nested, singular_name].map { |route| "@#{route}"}.join(', ') + ')'
27
+ nested_collection_url = "#{nested}_#{plural_name}_url(@#{nested})"
28
+ nested_resource_url = options[:path_prefix] + nested_resource_url unless options[:path_prefix].nil?
29
+ nested_collection_url = options[:path_prefix] + nested_collection_url unless options[:path_prefix].nil?
30
+ module_eval <<-"end_eval", __FILE__, __LINE__
31
+ before_filter :load_#{nested}
32
+ end_eval
33
+ end
34
+
35
+ #standard before_filters
36
+ module_eval <<-"end_eval", __FILE__, __LINE__
37
+ before_filter :load_#{singular_name}, :only => [ :show, :edit, :update, :destroy ]
38
+ before_filter :load_#{plural_name}, :only => [ :index ]
39
+ before_filter :new_#{singular_name}, :only => [ :new ]
40
+ before_filter :create_#{singular_name}, :only => [ :create ]
41
+ before_filter :update_#{singular_name}, :only => [ :update ]
42
+ before_filter :destroy_#{singular_name}, :only => [ :destroy ]
43
+
44
+ protected
45
+
46
+ def finder_options
47
+ resource_this_finder_options.class == Proc ? resource_this_finder_options.call : {}
48
+ end
49
+
50
+ end_eval
51
+
52
+ if options[:nested].nil?
53
+ module_eval <<-"end_eval", __FILE__, __LINE__
54
+ def finder_base
55
+ #{class_name}
56
+ end
57
+
58
+ def collection
59
+ #{class_name}.find(:all, finder_options)
60
+ end
61
+
62
+ def collection_url
63
+ #{collection_url}
64
+ end
65
+
66
+ def resource_url
67
+ #{resource_url}
68
+ end
69
+ end_eval
70
+ else
71
+ module_eval <<-"end_eval", __FILE__, __LINE__
72
+ def load_#{nested}
73
+ @#{nested} = #{nested_class}.find(params[:#{nested}_id]) rescue nil
74
+ end
75
+
76
+ def finder_base
77
+ @#{nested}.nil? ? #{class_name} : @#{nested}.#{plural_name}
78
+ end
79
+
80
+ def collection
81
+ @#{nested}.nil? ? #{class_name}.find(:all, finder_options) : @#{nested}.#{plural_name}.find(:all, finder_options)
82
+ end
83
+
84
+ def collection_url
85
+ @#{nested}.nil? ? #{collection_url} : #{nested_collection_url}
86
+ end
87
+
88
+ def resource_url
89
+ @#{nested}.nil? ? #{resource_url} : #{nested_resource_url}
90
+ end
91
+ end_eval
92
+ end
93
+
94
+ module_eval <<-"end_eval", __FILE__, __LINE__
95
+ def load_#{singular_name}
96
+ @#{singular_name} = finder_base.find(params[:id])
97
+ end
98
+
99
+ def new_#{singular_name}
100
+ @#{singular_name} = finder_base.new
101
+ end
102
+
103
+ def create_#{singular_name}
104
+ @#{singular_name} = finder_base.new(params[:#{singular_name}])
105
+ @created = @#{singular_name}.save
106
+ return true
107
+ end
108
+
109
+ def update_#{singular_name}
110
+ @updated = @#{singular_name}.update_attributes(params[:#{singular_name}])
111
+ return true
112
+ end
113
+
114
+ def destroy_#{singular_name}
115
+ @#{singular_name} = @#{singular_name}.destroy
116
+ end
117
+ end_eval
118
+
119
+ if will_paginate_index
120
+ module_eval <<-"end_eval", __FILE__, __LINE__
121
+ def load_#{plural_name}
122
+ @#{plural_name} = finder_base.paginate(finder_options.merge(:page => params[:page]))
123
+ end
124
+ end_eval
125
+ else
126
+ module_eval <<-"end_eval", __FILE__, __LINE__
127
+ def load_#{plural_name}
128
+ @#{plural_name} = collection
129
+ end
130
+ end_eval
131
+ end
132
+
133
+ module_eval <<-"end_eval", __FILE__, __LINE__
134
+ public
135
+ def index
136
+ respond_to do |format|
137
+ format.html
138
+ format.xml { render :xml => @#{plural_name} }
139
+ format.js
140
+ end
141
+ end
142
+
143
+ def show
144
+ respond_to do |format|
145
+ format.html
146
+ format.xml { render :xml => @#{singular_name} }
147
+ format.js
148
+ end
149
+ end
150
+
151
+ def new
152
+ respond_to do |format|
153
+ format.html { render :action => :edit }
154
+ format.xml { render :xml => @#{singular_name} }
155
+ format.js
156
+ end
157
+ end
158
+
159
+ def create
160
+ respond_to do |format|
161
+ if @created
162
+ flash[:notice] = '#{class_name} was successfully created.'
163
+ format.html { redirect_to(resource_url) }
164
+ format.xml { render :xml => @#{singular_name}, :status => :created, :location => resource_url }
165
+ format.js
166
+ else
167
+ format.html { render :action => :edit }
168
+ format.xml { render :xml => @#{singular_name}.errors, :status => :unprocessable_entity }
169
+ format.js
170
+ end
171
+ end
172
+ end
173
+
174
+ def edit
175
+ respond_to do |format|
176
+ format.html
177
+ format.js
178
+ end
179
+ end
180
+
181
+ def update
182
+ respond_to do |format|
183
+ if @updated
184
+ flash[:notice] = '#{class_name} was successfully updated.'
185
+ format.html { redirect_to(resource_url) }
186
+ format.xml { head :ok }
187
+ format.js
188
+ else
189
+ format.html { render :action => :edit }
190
+ format.xml { render :xml => @#{singular_name}.errors, :status => :unprocessable_entity }
191
+ format.js
192
+ end
193
+ end
194
+ end
195
+
196
+ def destroy
197
+ respond_to do |format|
198
+ format.html { redirect_to(collection_url) }
199
+ format.xml { head :ok }
200
+ format.js
201
+ end
202
+ end
203
+ end_eval
204
+ end
205
+ end
206
+ end
207
+
208
+ ActionController::Base.send :include, ResourceThis
@@ -0,0 +1,25 @@
1
+ spec = Gem::Specification.new do |s|
2
+ s.name = 'resource_this'
3
+ s.version = '1.0.0'
4
+ s.summary = "Not scaffolding. Resourcing. Creates extremely customizable resource controllers with one line of code."
5
+ s.description = %{Not scaffolding. Resourcing. Creates extremely customizable resource controllers with one line of code.
6
+
7
+ class PostsController < ActionController::Base
8
+ resource_this
9
+ end}
10
+ s.authors = ["Hsiu-Fan Wang", "Jesse Newland"]
11
+ s.email = "hfwang@porkbuns.net"
12
+ s.homepage = "https://github.com/hfwang/resource_this"
13
+
14
+ s.files = `git ls-files`.split($/)
15
+ s.executables = s.files.grep(%r{^bin/}).map { |f| File.basename(f) }
16
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
17
+ s.require_paths = ["lib"]
18
+
19
+
20
+ s.add_runtime_dependency "rails", "~> 3.2"
21
+
22
+ s.add_development_dependency "rspec", "~> 2.4"
23
+ s.add_development_dependency "rubygems-tasks", "~> 0.2"
24
+ s.add_development_dependency "yard", "~> 0.8"
25
+ end
@@ -0,0 +1,134 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class ResourceThisNestingTest < Test::Unit::TestCase
4
+ def setup
5
+ @controller = CommentsController.new
6
+ @request = ActionController::TestRequest.new
7
+ @request.accept = 'application/xml'
8
+ @response = ActionController::TestResponse.new
9
+ @first = Post.create(:title => "test", :body => "test")
10
+ @second = Post.create(:title => "test2", :body => "test2")
11
+ @first_comment = Comment.create(:post => @first, :body => "test")
12
+ @second_comment = Comment.create(:post => @second, :body => "test")
13
+ ActionController::Routing::Routes.draw do |map|
14
+ map.resources :posts do |post|
15
+ post.resources :comments
16
+ end
17
+ map.resources :comments
18
+ end
19
+ end
20
+
21
+ def teardown
22
+ Post.find(:all).each { |post| post.destroy }
23
+ Comment.find(:all).each { |comment| comment.destroy }
24
+ end
25
+
26
+ def test_should_get_index
27
+ get :index, :post_id => @first.id
28
+ assert_response :success
29
+ assert_equal @first.comments, assigns(:comments)
30
+ assert_equal @first, assigns(:post)
31
+ end
32
+
33
+ def test_should_get_index_without_post
34
+ get :index
35
+ assert_response :success
36
+ assert assigns(:post).nil?
37
+ assert_equal Comment.find(:all), assigns(:comments)
38
+ end
39
+
40
+ def test_should_get_new
41
+ get :new, :post_id => @first.id
42
+ assert_response :success
43
+ assert assigns(:comment)
44
+ assert assigns(:post)
45
+ end
46
+
47
+ def test_should_get_new_without_post
48
+ get :new
49
+ assert_response :success
50
+ assert assigns(:post).nil?
51
+ assert assigns(:comment)
52
+ end
53
+
54
+ def test_should_create_comment
55
+ assert_difference('Comment.count') do
56
+ post :create, :post_id => @first.id, :comment => { :body => "test" }
57
+ end
58
+ assert_response :created
59
+ assert assigns(:comment)
60
+ assert assigns(:post)
61
+ end
62
+
63
+ def test_should_create_comment_html
64
+ @request.accept = 'text/html'
65
+ assert_difference('Comment.count') do
66
+ post :create, :post_id => @first.id, :comment => { :body => "test" }
67
+ end
68
+ assert_redirected_to "posts/#{assigns(:post).id}/comments/#{assigns(:comment).id}"
69
+ end
70
+
71
+ def test_should_create_comment_html_without_post
72
+ @request.accept = 'text/html'
73
+ assert_difference('Comment.count') do
74
+ post :create, :comment => { :body => "test" }
75
+ end
76
+ assert_redirected_to "/comments/#{assigns(:comment).id}"
77
+ end
78
+
79
+ def test_should_show_comment
80
+ get :show, :post_id => @first.id, :id => @first_comment.id
81
+ assert_response :success
82
+ assert assigns(:comment)
83
+ assert assigns(:post)
84
+ end
85
+
86
+ def test_should_show_comment_without_post
87
+ get :show, :id => @first_comment.id
88
+ assert_response :success
89
+ assert_equal Comment.find(@first_comment.id), assigns(:comment)
90
+ assert assigns(:post).nil?
91
+ end
92
+
93
+ def test_should_update_comment
94
+ put :update, :post_id => @first.id, :id => @first_comment.id, :comment => { :post => @first, :body => "test" }
95
+ assert_response :success
96
+ assert assigns(:comment)
97
+ assert assigns(:post)
98
+ end
99
+
100
+ def test_should_update_comment_html
101
+ @request.accept = 'text/html'
102
+ put :update, :post_id => @first.id, :id => @first_comment.id, :comment => { :post => @first, :body => "test" }
103
+ assert_redirected_to "posts/#{assigns(:post).id}/comments/#{assigns(:comment).id}"
104
+ end
105
+
106
+ def test_should_update_comment_html_without_post
107
+ @request.accept = 'text/html'
108
+ put :update, :id => @first_comment.id, :comment => { :post => @first, :body => "test2" }
109
+ assert_redirected_to "/comments/#{assigns(:comment).id}"
110
+ end
111
+
112
+ def test_should_destroy_comment
113
+ assert_difference('Comment.count', -1) do
114
+ delete :destroy, :post_id => @first.id, :id => @first_comment.id
115
+ end
116
+ assert_response :success
117
+ end
118
+
119
+ def test_should_destroy_html
120
+ @request.accept = 'text/html'
121
+ assert_difference('Comment.count', -1) do
122
+ delete :destroy, :post_id => @first.id, :id => @first_comment.id
123
+ end
124
+ assert_redirected_to "posts/#{assigns(:post).id}/comments"
125
+ end
126
+
127
+ def test_should_destroy_html_without_post
128
+ @request.accept = 'text/html'
129
+ assert_difference('Comment.count', -1) do
130
+ delete :destroy, :id => @first_comment.id
131
+ end
132
+ assert_redirected_to "/comments"
133
+ end
134
+ end
@@ -0,0 +1,51 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class ResourceThisSortingTest < Test::Unit::TestCase
4
+ def setup
5
+ @controller = WidgetsController.new
6
+ @request = ActionController::TestRequest.new
7
+ @request.accept = 'application/xml'
8
+ @response = ActionController::TestResponse.new
9
+ @a = Widget.create(:title => "aaa", :body => "zzz")
10
+ @z = Widget.create(:title => "zzz", :body => "aaa")
11
+ 100.times do
12
+ Widget.create(:title => "foo", :body => "bar")
13
+ end
14
+ ActionController::Routing::Routes.draw do |map|
15
+ map.resources :widgets
16
+ end
17
+ end
18
+
19
+ def teardown
20
+ Widget.find(:all).each { |w| w.destroy }
21
+ end
22
+
23
+ def test_should_get_index
24
+ get :index
25
+ assert_response :success
26
+ assert assigns(:widgets)
27
+ assert_equal @a, assigns(:widgets).first
28
+ end
29
+
30
+ def test_should_get_index_sorted_with_inline_proc
31
+ @controller.resource_this_finder_options = Proc.new { { :order => 'body' } }
32
+ get :index
33
+ assert_response :success
34
+ assert assigns(:widgets)
35
+ assert_equal @z, assigns(:widgets).first
36
+ end
37
+
38
+ def test_should_get_index_sorted_with_proc
39
+ @controller.resource_this_finder_options = Proc.new { finder_options }
40
+ get :index
41
+ assert_response :success
42
+ assert assigns(:widgets)
43
+ assert_equal 2, assigns(:widgets).size
44
+ assert_equal @z, assigns(:widgets).first
45
+ end
46
+
47
+ def finder_options
48
+ {:order => 'body', :limit => 2}
49
+ end
50
+
51
+ end
@@ -0,0 +1,96 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class ResourceThisTest < Test::Unit::TestCase
4
+ def setup
5
+ @controller = PostsController.new
6
+ @request = ActionController::TestRequest.new
7
+ @request.accept = 'application/xml'
8
+ @response = ActionController::TestResponse.new
9
+ @first = Post.create(:title => "test", :body => "test")
10
+ ActionController::Routing::Routes.draw do |map|
11
+ map.resources :posts
12
+ end
13
+ end
14
+
15
+ def teardown
16
+ Post.find(:all).each { |post| post.destroy }
17
+ end
18
+
19
+ def test_should_get_index
20
+ get :index
21
+ assert_response :success
22
+ assert assigns(:posts)
23
+ end
24
+
25
+ def test_should_get_new
26
+ get :new
27
+ assert_response :success
28
+ assert assigns(:post)
29
+ end
30
+
31
+ def test_should_create_post
32
+ assert_difference('Post.count') do
33
+ post :create, :post => { :title => "test", :body => "test" }
34
+ end
35
+ assert_response :created
36
+ assert assigns(:post)
37
+ end
38
+
39
+ def test_should_handle_invalid_post_on_create
40
+ assert_no_difference('Post.count') do
41
+ post :create, :post => { :title => "1" }
42
+ end
43
+ assert_response :unprocessable_entity
44
+ assert assigns(:post).errors
45
+ assert !assigns(:created)
46
+ end
47
+
48
+
49
+ def test_should_create_post_html
50
+ @request.accept = 'text/html'
51
+ assert_difference('Post.count') do
52
+ post :create, :post => { :title => "test", :body => "test" }
53
+ end
54
+ assert_redirected_to "/posts/#{assigns(:post).id}"
55
+ end
56
+
57
+ def test_should_show_post
58
+ get :show, :id => @first.id
59
+ assert_response :success
60
+ assert assigns(:post)
61
+ end
62
+
63
+ def test_should_update_post
64
+ put :update, :id => @first.id, :post => { :title => "test", :body => "test" }
65
+ assert_response :success
66
+ assert assigns(:post)
67
+ end
68
+
69
+ def test_should_handle_invalid_post_on_update
70
+ post :update, :id => @first.id, :post => { :title => "1" }
71
+ assert_response :unprocessable_entity
72
+ assert assigns(:post).errors
73
+ assert !assigns(:updated)
74
+ end
75
+
76
+ def test_should_update_post_html
77
+ @request.accept = 'text/html'
78
+ put :update, :id => @first.id, :post => { :title => "test", :body => "test" }
79
+ assert_redirected_to "/posts/#{assigns(:post).id}"
80
+ end
81
+
82
+ def test_should_destroy_post
83
+ assert_difference('Post.count', -1) do
84
+ delete :destroy, :id => @first.id
85
+ end
86
+ assert_response :success
87
+ end
88
+
89
+ def test_should_destroy_post_html
90
+ @request.accept = 'text/html'
91
+ assert_difference('Post.count', -1) do
92
+ delete :destroy, :id => @first.id
93
+ end
94
+ assert_redirected_to "/posts"
95
+ end
96
+ end
@@ -0,0 +1,39 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class ResourceThisUrlPrefixTest < Test::Unit::TestCase
4
+ def setup
5
+ @controller = Admin::PostsController.new
6
+ @request = ActionController::TestRequest.new
7
+ @response = ActionController::TestResponse.new
8
+ @first = Post.create(:title => "test", :body => "test")
9
+ ActionController::Routing::Routes.draw do |map|
10
+ map.resources :posts
11
+ map.with_options :path_prefix => 'admin', :name_prefix => 'admin_' do |map|
12
+ map.resources :posts, :controller => 'admin/posts'
13
+ end
14
+ end
15
+ end
16
+
17
+ def teardown
18
+ Post.find(:all).each { |post| post.destroy }
19
+ end
20
+
21
+ def test_should_create_post
22
+ assert_difference('Post.count') do
23
+ post :create, :post => { :title => "test", :body => "test" }
24
+ end
25
+ assert_redirected_to "/admin/posts/#{assigns(:post).id}"
26
+ end
27
+
28
+ def test_should_update_post
29
+ put :update, :id => @first.id, :post => { :title => "test", :body => "test" }
30
+ assert_redirected_to "/admin/posts/#{assigns(:post).id}"
31
+ end
32
+
33
+ def test_should_destroy_post
34
+ assert_difference('Post.count', -1) do
35
+ delete :destroy, :id => @first.id
36
+ end
37
+ assert_redirected_to "/admin/posts"
38
+ end
39
+ end
@@ -0,0 +1,81 @@
1
+ $LOAD_PATH.unshift 'lib/'
2
+
3
+ require 'rubygems'
4
+ require 'multi_rails_init'
5
+ require 'action_controller/test_process'
6
+ require 'test/unit'
7
+ require 'resource_this'
8
+
9
+ begin
10
+ require 'redgreen'
11
+ rescue LoadError
12
+ nil
13
+ end
14
+
15
+ RAILS_ROOT = '.' unless defined? RAILS_ROOT
16
+ RAILS_ENV = 'test' unless defined? RAILS_ENV
17
+
18
+ ActiveRecord::Base.logger = Logger.new(STDOUT) if ENV['DEBUG']
19
+ ActionController::Base.logger = Logger.new(STDOUT) if ENV['DEBUG']
20
+
21
+ ActionController::Base.send :include, ResourceThis
22
+
23
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
24
+
25
+ ActiveRecord::Schema.define(:version => 1) do
26
+ create_table :posts do |t|
27
+ t.column :title, :string
28
+ t.column :body, :text
29
+ t.column :created_at, :datetime
30
+ t.column :updated_at, :datetime
31
+ end
32
+ create_table :comments do |t|
33
+ t.column :body, :text
34
+ t.column :post_id, :integer
35
+ t.column :created_at, :datetime
36
+ t.column :updated_at, :datetime
37
+ end
38
+ create_table :widgets do |t|
39
+ t.column :title, :string
40
+ t.column :body, :text
41
+ t.column :created_at, :datetime
42
+ t.column :updated_at, :datetime
43
+ end
44
+ end
45
+
46
+ class Post < ActiveRecord::Base
47
+ has_many :comments
48
+ validates_length_of :title, :within => 2..100
49
+ def validate
50
+ end
51
+ end
52
+
53
+ class Comment < ActiveRecord::Base
54
+ belongs_to :post
55
+ def validate
56
+ end
57
+ validates_associated :post
58
+ end
59
+
60
+ class Widget < ActiveRecord::Base
61
+ def validate
62
+ end
63
+ end
64
+
65
+ class PostsController < ActionController::Base
66
+ resource_this
67
+ end
68
+
69
+ class WidgetsController < ActionController::Base
70
+ resource_this
71
+ end
72
+
73
+ module Admin; end
74
+
75
+ class Admin::PostsController < ActionController::Base
76
+ resource_this :path_prefix => "admin_"
77
+ end
78
+
79
+ class CommentsController < ActionController::Base
80
+ resource_this :nested => [:posts]
81
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resource_this
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Hsiu-Fan Wang
8
+ - Jesse Newland
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-08-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '3.2'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '3.2'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rspec
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '2.4'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '2.4'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rubygems-tasks
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '0.2'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '0.2'
56
+ - !ruby/object:Gem::Dependency
57
+ name: yard
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '0.8'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '0.8'
70
+ description: |-
71
+ Not scaffolding. Resourcing. Creates extremely customizable resource controllers with one line of code.
72
+
73
+ class PostsController < ActionController::Base
74
+ resource_this
75
+ end
76
+ email: hfwang@porkbuns.net
77
+ executables: []
78
+ extensions: []
79
+ extra_rdoc_files: []
80
+ files:
81
+ - ".gitignore"
82
+ - CHANGELOG.md
83
+ - Gemfile
84
+ - MIT-LICENSE
85
+ - README.md
86
+ - Rakefile
87
+ - generators/resource_this/USAGE
88
+ - generators/resource_this/resource_this_generator.rb
89
+ - generators/resource_this/templates/controller.rb
90
+ - generators/resource_this/templates/functional_test.rb
91
+ - generators/resource_this/templates/helper.rb
92
+ - init.rb
93
+ - lib/resource_this.rb
94
+ - resource_this.gemspec
95
+ - test/resource_this_nesting_test.rb
96
+ - test/resource_this_sorting_test.rb
97
+ - test/resource_this_test.rb
98
+ - test/resource_this_url_prefix_test.rb
99
+ - test/test_helper.rb
100
+ homepage: https://github.com/hfwang/resource_this
101
+ licenses: []
102
+ metadata: {}
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 2.2.2
120
+ signing_key:
121
+ specification_version: 4
122
+ summary: Not scaffolding. Resourcing. Creates extremely customizable resource controllers
123
+ with one line of code.
124
+ test_files:
125
+ - test/resource_this_nesting_test.rb
126
+ - test/resource_this_sorting_test.rb
127
+ - test/resource_this_test.rb
128
+ - test/resource_this_url_prefix_test.rb
129
+ - test/test_helper.rb