resource_this 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.md +200 -0
- data/Rakefile +25 -0
- data/generators/resource_this/USAGE +24 -0
- data/generators/resource_this/resource_this_generator.rb +72 -0
- data/generators/resource_this/templates/controller.rb +3 -0
- data/generators/resource_this/templates/functional_test.rb +59 -0
- data/generators/resource_this/templates/helper.rb +2 -0
- data/init.rb +1 -0
- data/lib/resource_this.rb +208 -0
- data/resource_this.gemspec +25 -0
- data/test/resource_this_nesting_test.rb +134 -0
- data/test/resource_this_sorting_test.rb +51 -0
- data/test/resource_this_test.rb +96 -0
- data/test/resource_this_url_prefix_test.rb +39 -0
- data/test/test_helper.rb +81 -0
- metadata +129 -0
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
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
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,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
|
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
|
data/test/test_helper.rb
ADDED
@@ -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
|