dry_crud 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -5
- data/Rakefile +7 -15
- data/VERSION +1 -1
- data/lib/generators/dry_crud/templates/{public → app/assets}/images/actions/add.png +0 -0
- data/lib/generators/dry_crud/templates/{public → app/assets}/images/actions/delete.png +0 -0
- data/lib/generators/dry_crud/templates/{public → app/assets}/images/actions/edit.png +0 -0
- data/lib/generators/dry_crud/templates/{public → app/assets}/images/actions/list.png +0 -0
- data/lib/generators/dry_crud/templates/{public → app/assets}/images/actions/show.png +0 -0
- data/lib/generators/dry_crud/templates/{public → app/assets}/stylesheets/crud.css +0 -0
- data/lib/generators/dry_crud/templates/app/controllers/crud_controller.rb +12 -12
- data/lib/generators/dry_crud/templates/app/controllers/list_controller.rb +3 -5
- data/lib/generators/dry_crud/templates/app/helpers/standard_helper.rb +12 -13
- data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.erb +1 -1
- data/lib/generators/dry_crud/templates/test/crud_test_model.rb +4 -0
- data/lib/generators/dry_crud/templates/test/functional/crud_controller_test_helper.rb +13 -13
- data/test/templates/Gemfile +18 -16
- data/test/templates/app/controllers/cities_controller.rb +2 -2
- data/test/templates/app/views/ajax/ajax.js.erb +1 -0
- metadata +12 -14
- data/lib/generators/dry_crud/templates/app/controllers/render_inheritable.rb +0 -153
- data/lib/generators/dry_crud/templates/test/unit/helpers/render_inheritable_test.rb +0 -153
- data/test/templates/app/views/ajax/ajax.js.rjs +0 -1
data/README.rdoc
CHANGED
@@ -19,7 +19,7 @@ To integrate DRY CRUD into your code, only a few additions are required:
|
|
19
19
|
* For uniform CRUD functionality, just subclass your controllers from +CrudController+.
|
20
20
|
* Overwrite the <tt>:to_s</tt> method of your models for a human-friendly representation in captions.
|
21
21
|
|
22
|
-
Version 1.
|
22
|
+
Version 1.4 and higher are built for Rails 3.1. As of Rails 3.1, views are inheritable as well, so a core functionality of DRY CRUD got into the Rails core itself. For Rails 3.0, use version 1.3.1 or refer to the rails-3.0 branch. If you need a version for Rails 2.3, please get version 0.6.0 of the gem or go to the rails-2.3 branch on Github. DRY CRUD 1.3 is fully compatible with Ruby 1.8.7, Ruby 1.9.2 and JRuby.
|
23
23
|
|
24
24
|
== Overview
|
25
25
|
|
@@ -31,8 +31,6 @@ Enter DRY CRUD.
|
|
31
31
|
The main idea of DRY CRUD is to concentrate basic functionality of your application, like CRUD actions, uniform formatting, forms and tables into specifically extendable units. DRY CRUD generates various foundation classes that you may freely adapt to your application's needs. For each model, you may transparently customize arbitrary parts or just fallback to the general behavior. This applies not only for controllers, but also for view templates and helpers. There is no black box your code depends on. You lay the foundation that fits your application best.
|
32
32
|
</b>
|
33
33
|
|
34
|
-
A core element of DRY CRUD is the +RenderInheritable+ module. This gives you inheritable views and partials. In the default case, a template is searched in the current controller's view folder. If it is not found there, the template with the same name in the view folder of the superclass controller is used. This lookup path might be customized as well. RenderInheritable is also available as a stand-alone gem at http://github.com/codez/render_inheritable.
|
35
|
-
|
36
34
|
DRY CRUD is a Rails generator. All code resides in your application and is open for you to inspect and to extend. You may pick whatever you consider useful or adapt what is not sufficient. Even if you do not require any CRUD functionality, you might find some helpers simplifying your work. There are no runtime dependencies to the dry_crud gem. Having said this, DRY CRUD does not want to provide a maximum of functionality that requires a lot of configuration, but rather a clean and lightweight foundation to build your application's requirements upon. This is why DRY CRUD comes as a generator and not as a Rails plugin.
|
37
35
|
|
38
36
|
DRY CRUD does not depend on any other plugins, but easily allows you to integrate them in order to unify the behavior of your CRUD controllers. You might even use the plugins mentioned above to adapt your generated +CrudController+ base class. All classes come with thorough tests that provide you with a solid foundation for implementing your own adaptions.
|
@@ -219,8 +217,6 @@ All generated files are supposed to provide a reasonable foundation for the CRUD
|
|
219
217
|
|
220
218
|
{controller/list_controller.rb}[http://codez.ch/dry_crud/?q=ListController]:: Abstract controller providing a basic list action. There are two sub-modules that provide search and sort functionality for the table displayed in the list action. A third sub-module remembers the list parameters in order to return to an identical list.
|
221
219
|
|
222
|
-
{controller/render_inheritable.rb}[http://codez.ch/dry_crud/?q=RenderInheritable]:: A controller enhancement that allows one to render inheritable views and partials. If no view file is found for the current controller, the corresponding file is looked up in its superclass hierarchy. Thus, only views or partials that look differently have to be overwritten.
|
223
|
-
|
224
220
|
|
225
221
|
=== Helpers:
|
226
222
|
|
data/Rakefile
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
sdoc = begin
|
6
|
-
require 'sdoc'
|
7
|
-
true
|
8
|
-
rescue Exception
|
9
|
-
false
|
10
|
-
end
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rubygems/package_task'
|
4
|
+
require 'rdoc/task'
|
11
5
|
|
12
6
|
load 'dry_crud.gemspec'
|
13
7
|
|
@@ -49,6 +43,8 @@ namespace :test do
|
|
49
43
|
unless File.exist?(TEST_APP_ROOT)
|
50
44
|
sh "rails new #{TEST_APP_ROOT}"
|
51
45
|
FileUtils.cp(File.join(File.dirname(__FILE__), 'test', 'templates', 'Gemfile'), TEST_APP_ROOT)
|
46
|
+
sh "cd #{TEST_APP_ROOT}; bundle install" # update Gemfile.lock
|
47
|
+
FileUtils.rm_f(File.join(TEST_APP_ROOT, 'test', 'performance', 'browsing_test.rb'))
|
52
48
|
end
|
53
49
|
end
|
54
50
|
|
@@ -96,7 +92,7 @@ task :site => :rdoc do
|
|
96
92
|
end
|
97
93
|
|
98
94
|
# :package task
|
99
|
-
|
95
|
+
Gem::PackageTask.new(DRY_CRUD_GEMSPEC) do |pkg|
|
100
96
|
if Rake.application.top_level_tasks.include?('release')
|
101
97
|
pkg.need_tar_gz = true
|
102
98
|
pkg.need_tar_bz2 = true
|
@@ -107,11 +103,7 @@ end
|
|
107
103
|
# :rdoc task
|
108
104
|
Rake::RDocTask.new do |rdoc|
|
109
105
|
rdoc.title = 'Dry Crud'
|
110
|
-
rdoc.options << '--line-numbers'
|
111
|
-
if sdoc
|
112
|
-
rdoc.options << '--fmt' << 'shtml'
|
113
|
-
rdoc.template = 'direct'
|
114
|
-
end
|
106
|
+
rdoc.options << '--line-numbers'
|
115
107
|
rdoc.rdoc_files.include(*FileList.new('*') do |list|
|
116
108
|
list.exclude(/(^|[^.a-z])[a-z]+/)
|
117
109
|
list.exclude('TODO')
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.4.0
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Abstract controller providing basic CRUD actions.
|
2
2
|
# This implementation mainly follows the one of the Rails scaffolding
|
3
|
-
# controller and responses to HTML and
|
3
|
+
# controller and responses to HTML and JSON requests. Some enhancements were made to ease extendability.
|
4
4
|
# Several protected helper methods are there to be (optionally) overriden by subclasses.
|
5
5
|
# With the help of additional callbacks, it is possible to hook into the action procedures without
|
6
6
|
# overriding the entire method.
|
@@ -31,14 +31,14 @@ class CrudController < ListController
|
|
31
31
|
|
32
32
|
# Show one entry of this model.
|
33
33
|
# GET /entries/1
|
34
|
-
# GET /entries/1.
|
34
|
+
# GET /entries/1.json
|
35
35
|
def show
|
36
36
|
respond_with @entry
|
37
37
|
end
|
38
38
|
|
39
39
|
# Display a form to create a new entry of this model.
|
40
40
|
# GET /entries/new
|
41
|
-
# GET /entries/new.
|
41
|
+
# GET /entries/new.json
|
42
42
|
def new
|
43
43
|
@entry.attributes = params[model_identifier]
|
44
44
|
respond_with @entry
|
@@ -49,7 +49,7 @@ class CrudController < ListController
|
|
49
49
|
# To customize the response, you may overwrite this action and call
|
50
50
|
# super with a block that gets success and format parameters.
|
51
51
|
# POST /entries
|
52
|
-
# POST /entries.
|
52
|
+
# POST /entries.json
|
53
53
|
def create(&block)
|
54
54
|
@entry.attributes = params[model_identifier]
|
55
55
|
created = with_callbacks(:create, :save) { @entry.save }
|
@@ -57,10 +57,10 @@ class CrudController < ListController
|
|
57
57
|
customizable_respond_to(created, block) do |format|
|
58
58
|
if created
|
59
59
|
format.html { redirect_to_show success_notice }
|
60
|
-
format.
|
60
|
+
format.json { render :json => @entry, :status => :created, :location => @entry }
|
61
61
|
else
|
62
62
|
format.html { render_with_callback 'new' }
|
63
|
-
format.
|
63
|
+
format.json { render :json => @entry.errors, :status => :unprocessable_entity }
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -76,7 +76,7 @@ class CrudController < ListController
|
|
76
76
|
# To customize the response, you may overwrite this action and call
|
77
77
|
# super with a block that gets success and format parameters.
|
78
78
|
# PUT /entries/1
|
79
|
-
# PUT /entries/1.
|
79
|
+
# PUT /entries/1.json
|
80
80
|
def update(&block)
|
81
81
|
@entry.attributes = params[model_identifier]
|
82
82
|
updated = with_callbacks(:update, :save) { @entry.save }
|
@@ -84,10 +84,10 @@ class CrudController < ListController
|
|
84
84
|
customizable_respond_to(updated, block) do |format|
|
85
85
|
if updated
|
86
86
|
format.html { redirect_to_show success_notice }
|
87
|
-
format.
|
87
|
+
format.json { head :ok }
|
88
88
|
else
|
89
89
|
format.html { render_with_callback 'edit' }
|
90
|
-
format.
|
90
|
+
format.json { render :json => @entry.errors, :status => :unprocessable_entity }
|
91
91
|
end
|
92
92
|
end
|
93
93
|
end
|
@@ -97,20 +97,20 @@ class CrudController < ListController
|
|
97
97
|
# To customize the response, you may overwrite this action and call
|
98
98
|
# super with a block that gets success and format parameters.
|
99
99
|
# DELETE /entries/1
|
100
|
-
# DELETE /entries/1.
|
100
|
+
# DELETE /entries/1.json
|
101
101
|
def destroy(&block)
|
102
102
|
destroyed = run_callbacks(:destroy) { @entry.destroy }
|
103
103
|
|
104
104
|
customizable_respond_to(destroyed, block) do |format|
|
105
105
|
if destroyed
|
106
106
|
format.html { redirect_to_index success_notice }
|
107
|
-
format.
|
107
|
+
format.json { head :ok }
|
108
108
|
else
|
109
109
|
format.html {
|
110
110
|
flash.alert = @entry.errors.full_messages.join('<br/>')
|
111
111
|
request.env["HTTP_REFERER"].present? ? redirect_to(:back) : redirect_to_show
|
112
112
|
}
|
113
|
-
format.
|
113
|
+
format.json { render :json => @entry.errors, :status => :unprocessable_entity }
|
114
114
|
end
|
115
115
|
end
|
116
116
|
end
|
@@ -6,8 +6,6 @@
|
|
6
6
|
# the user the same list as he left it.
|
7
7
|
class ListController < ApplicationController
|
8
8
|
|
9
|
-
include RenderInheritable
|
10
|
-
|
11
9
|
helper_method :model_class, :models_label
|
12
10
|
|
13
11
|
delegate :model_class, :models_label, :to => 'self.class'
|
@@ -19,7 +17,7 @@ class ListController < ApplicationController
|
|
19
17
|
|
20
18
|
# List all entries of this model.
|
21
19
|
# GET /entries
|
22
|
-
# GET /entries.
|
20
|
+
# GET /entries.json
|
23
21
|
def index
|
24
22
|
@entries = list_entries
|
25
23
|
respond_with @entries
|
@@ -36,7 +34,7 @@ class ListController < ApplicationController
|
|
36
34
|
def respond_with(object)
|
37
35
|
respond_to do |format|
|
38
36
|
format.html { render_with_callback action_name }
|
39
|
-
format.
|
37
|
+
format.json { render :json => object }
|
40
38
|
end
|
41
39
|
end
|
42
40
|
|
@@ -135,7 +133,7 @@ class ListController < ApplicationController
|
|
135
133
|
# Enhance the list entries with an optional sort order.
|
136
134
|
def list_entries_with_sort
|
137
135
|
if params[:sort].present? && sortable?(params[:sort])
|
138
|
-
list_entries_without_sort.
|
136
|
+
list_entries_without_sort.reorder(sort_expression)
|
139
137
|
else
|
140
138
|
list_entries_without_sort
|
141
139
|
end
|
@@ -27,7 +27,7 @@ module StandardHelper
|
|
27
27
|
# If the value is an associated model, renders the label of this object.
|
28
28
|
# Otherwise, calls format_type.
|
29
29
|
def format_attr(obj, attr)
|
30
|
-
format_type_attr_method = :"format_#{obj.class.name.underscore}_#{attr.to_s}"
|
30
|
+
format_type_attr_method = obj.class.respond_to?(:model_name) ? :"format_#{obj.class.model_name.underscore}_#{attr.to_s}" : :"format_#{obj.class.name.underscore}_#{attr.to_s}"
|
31
31
|
format_attr_method = :"format_#{attr.to_s}"
|
32
32
|
if respond_to?(format_type_attr_method)
|
33
33
|
send(format_type_attr_method, obj)
|
@@ -164,9 +164,8 @@ module StandardHelper
|
|
164
164
|
html
|
165
165
|
end
|
166
166
|
|
167
|
-
# Translates the passed key by looking it up over the
|
168
|
-
#
|
169
|
-
# order:
|
167
|
+
# Translates the passed key by looking it up over the controller hierarchy.
|
168
|
+
# The key is searched in the following order:
|
170
169
|
# - {controller}.{current_partial}.{key}
|
171
170
|
# - {controller}.{current_action}.{key}
|
172
171
|
# - {controller}.global.{key}
|
@@ -177,16 +176,16 @@ module StandardHelper
|
|
177
176
|
# - global.{key}
|
178
177
|
def translate_inheritable(key, variables = {})
|
179
178
|
defaults = []
|
180
|
-
|
181
|
-
|
182
|
-
|
179
|
+
partial = @virtual_path ? @virtual_path.gsub(%r{.*/_?}, "") : nil
|
180
|
+
current = controller.class
|
181
|
+
while current < ActionController::Base
|
182
|
+
folder = current.controller_path
|
183
|
+
if folder.present?
|
183
184
|
defaults << :"#{folder}.#{partial}.#{key}" if partial
|
184
185
|
defaults << :"#{folder}.#{action_name}.#{key}"
|
185
186
|
defaults << :"#{folder}.global.#{key}"
|
186
187
|
end
|
187
|
-
|
188
|
-
defaults << :"#{controller_name}.#{action_name}.#{key}"
|
189
|
-
defaults << :"#{controller_name}.global.#{key}"
|
188
|
+
current = current.superclass
|
190
189
|
end
|
191
190
|
defaults << :"global.#{key}"
|
192
191
|
|
@@ -205,9 +204,9 @@ module StandardHelper
|
|
205
204
|
# - global.associations.{key}
|
206
205
|
def translate_association(key, assoc = nil, variables = {})
|
207
206
|
primary = if assoc
|
208
|
-
variables[:default] ||= [:"activerecord.associations.#{assoc.klass.
|
207
|
+
variables[:default] ||= [:"activerecord.associations.#{assoc.klass.model_name.underscore}.#{key}",
|
209
208
|
:"global.associations.#{key}"]
|
210
|
-
:"activerecord.associations.models.#{assoc.active_record.
|
209
|
+
:"activerecord.associations.models.#{assoc.active_record.model_name.underscore}.#{assoc.name}.#{key}"
|
211
210
|
else
|
212
211
|
:"global.associations.#{key}"
|
213
212
|
end
|
@@ -261,7 +260,7 @@ module StandardHelper
|
|
261
260
|
|
262
261
|
# Returns true if no link should be created when formatting the given association.
|
263
262
|
def no_assoc_link?(assoc, val)
|
264
|
-
!respond_to?("#{val.class.
|
263
|
+
!respond_to?("#{val.class.model_name.underscore}_path".to_sym)
|
265
264
|
end
|
266
265
|
|
267
266
|
# Returns the association proxy for the given attribute. The attr parameter
|
@@ -11,11 +11,11 @@ module CrudControllerTestHelper
|
|
11
11
|
assert_present assigns(:entries)
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
get :index, :format => '
|
14
|
+
def test_index_json
|
15
|
+
get :index, :format => 'json'
|
16
16
|
assert_response :success
|
17
17
|
assert_present assigns(:entries)
|
18
|
-
assert @response.body.starts_with?("
|
18
|
+
assert @response.body.starts_with?("[{"), @response.body
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_index_search
|
@@ -54,11 +54,11 @@ module CrudControllerTestHelper
|
|
54
54
|
assert_equal test_entry, assigns(:entry)
|
55
55
|
end
|
56
56
|
|
57
|
-
def
|
58
|
-
get :show, :id => test_entry.id, :format => '
|
57
|
+
def test_show_json
|
58
|
+
get :show, :id => test_entry.id, :format => 'json'
|
59
59
|
assert_response :success
|
60
60
|
assert_equal test_entry, assigns(:entry)
|
61
|
-
assert @response.body.starts_with?("
|
61
|
+
assert @response.body.starts_with?("{")
|
62
62
|
end
|
63
63
|
|
64
64
|
def test_show_with_not_existing_id_raises_RecordNotFound
|
@@ -89,12 +89,12 @@ module CrudControllerTestHelper
|
|
89
89
|
assert_test_attrs_equal
|
90
90
|
end
|
91
91
|
|
92
|
-
def
|
92
|
+
def test_create_json
|
93
93
|
assert_difference("#{model_class.name}.count") do
|
94
|
-
post :create, model_identifier => test_entry_attrs, :format => '
|
94
|
+
post :create, model_identifier => test_entry_attrs, :format => 'json'
|
95
95
|
end
|
96
96
|
assert_response :success
|
97
|
-
assert @response.body.starts_with?("
|
97
|
+
assert @response.body.starts_with?("{")
|
98
98
|
end
|
99
99
|
|
100
100
|
def test_edit
|
@@ -118,9 +118,9 @@ module CrudControllerTestHelper
|
|
118
118
|
assert_redirected_to assigns(:entry)
|
119
119
|
end
|
120
120
|
|
121
|
-
def
|
121
|
+
def test_update_json
|
122
122
|
assert_no_difference("#{model_class.name}.count") do
|
123
|
-
put :update, :id => test_entry.id, model_identifier => test_entry_attrs, :format => '
|
123
|
+
put :update, :id => test_entry.id, model_identifier => test_entry_attrs, :format => 'json'
|
124
124
|
end
|
125
125
|
assert_response :success
|
126
126
|
assert_equal "", @response.body.strip
|
@@ -133,9 +133,9 @@ module CrudControllerTestHelper
|
|
133
133
|
assert_redirected_to_index
|
134
134
|
end
|
135
135
|
|
136
|
-
def
|
136
|
+
def test_destroy_json
|
137
137
|
assert_difference("#{model_class.name}.count", -1) do
|
138
|
-
delete :destroy, :id => test_entry.id, :format => '
|
138
|
+
delete :destroy, :id => test_entry.id, :format => 'json'
|
139
139
|
end
|
140
140
|
assert_response :success
|
141
141
|
assert_equal "", @response.body.strip
|
data/test/templates/Gemfile
CHANGED
@@ -1,34 +1,36 @@
|
|
1
1
|
source 'http://rubygems.org'
|
2
2
|
|
3
|
-
gem 'rails'
|
3
|
+
gem 'rails', '>= 3.1'
|
4
4
|
|
5
5
|
# Bundle edge Rails instead:
|
6
|
-
# gem 'rails',
|
6
|
+
# gem 'rails', :git => 'git://github.com/rails/rails.git'
|
7
7
|
|
8
8
|
gem 'sqlite3', :platforms => :ruby
|
9
9
|
|
10
10
|
gem 'jdbc-sqlite3', '3.6.14.2.056', :platforms => :jruby
|
11
11
|
gem 'activerecord-jdbcsqlite3-adapter', :platforms => :jruby
|
12
12
|
|
13
|
+
gem 'json'
|
14
|
+
|
15
|
+
# Gems used only for assets and not required
|
16
|
+
# in production environments by default.
|
17
|
+
group :assets do
|
18
|
+
gem 'sass-rails', '~> 3.1.5.rc.2'
|
19
|
+
gem 'coffee-rails', '~> 3.1.1'
|
20
|
+
gem 'uglifier', '>= 1.0.3'
|
21
|
+
end
|
22
|
+
|
23
|
+
gem 'jquery-rails'
|
24
|
+
|
25
|
+
# To use ActiveModel has_secure_password
|
26
|
+
# gem 'bcrypt-ruby', '~> 3.0.0'
|
27
|
+
|
13
28
|
# Use unicorn as the web server
|
14
29
|
# gem 'unicorn'
|
15
30
|
|
16
31
|
# Deploy with Capistrano
|
17
32
|
# gem 'capistrano'
|
18
33
|
|
19
|
-
# To use debugger
|
34
|
+
# To use debugger
|
20
35
|
# gem 'ruby-debug'
|
21
36
|
# gem 'ruby-debug19', :require => 'ruby-debug'
|
22
|
-
|
23
|
-
# Bundle the extra gems:
|
24
|
-
# gem 'bj'
|
25
|
-
# gem 'nokogiri'
|
26
|
-
# gem 'sqlite3-ruby', :require => 'sqlite3'
|
27
|
-
# gem 'aws-s3', :require => 'aws/s3'
|
28
|
-
|
29
|
-
# Bundle gems for the local environment. Make sure to
|
30
|
-
# put test-only gems in this group so their generators
|
31
|
-
# and rake tasks are available in development mode:
|
32
|
-
# group :development, :test do
|
33
|
-
# gem 'webrat'
|
34
|
-
# end
|
@@ -0,0 +1 @@
|
|
1
|
+
$('#response').html("<%= escape_javascript(render 'hello') %>");
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry_crud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 1.
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 1.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Pascal Zumkehr
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-12-05 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -47,9 +47,14 @@ extra_rdoc_files:
|
|
47
47
|
- VERSION
|
48
48
|
files:
|
49
49
|
- lib/generators/dry_crud/dry_crud_generator.rb
|
50
|
+
- lib/generators/dry_crud/templates/app/assets/images/actions/add.png
|
51
|
+
- lib/generators/dry_crud/templates/app/assets/images/actions/delete.png
|
52
|
+
- lib/generators/dry_crud/templates/app/assets/images/actions/edit.png
|
53
|
+
- lib/generators/dry_crud/templates/app/assets/images/actions/list.png
|
54
|
+
- lib/generators/dry_crud/templates/app/assets/images/actions/show.png
|
55
|
+
- lib/generators/dry_crud/templates/app/assets/stylesheets/crud.css
|
50
56
|
- lib/generators/dry_crud/templates/app/controllers/crud_controller.rb
|
51
57
|
- lib/generators/dry_crud/templates/app/controllers/list_controller.rb
|
52
|
-
- lib/generators/dry_crud/templates/app/controllers/render_inheritable.rb
|
53
58
|
- lib/generators/dry_crud/templates/app/helpers/crud_helper.rb
|
54
59
|
- lib/generators/dry_crud/templates/app/helpers/list_helper.rb
|
55
60
|
- lib/generators/dry_crud/templates/app/helpers/standard_form_builder.rb
|
@@ -74,12 +79,6 @@ files:
|
|
74
79
|
- lib/generators/dry_crud/templates/app/views/shared/_labeled.html.erb
|
75
80
|
- lib/generators/dry_crud/templates/config/locales/en_crud.yml
|
76
81
|
- lib/generators/dry_crud/templates/INSTALL
|
77
|
-
- lib/generators/dry_crud/templates/public/images/actions/add.png
|
78
|
-
- lib/generators/dry_crud/templates/public/images/actions/delete.png
|
79
|
-
- lib/generators/dry_crud/templates/public/images/actions/edit.png
|
80
|
-
- lib/generators/dry_crud/templates/public/images/actions/list.png
|
81
|
-
- lib/generators/dry_crud/templates/public/images/actions/show.png
|
82
|
-
- lib/generators/dry_crud/templates/public/stylesheets/crud.css
|
83
82
|
- lib/generators/dry_crud/templates/test/crud_test_model.rb
|
84
83
|
- lib/generators/dry_crud/templates/test/custom_assertions.rb
|
85
84
|
- lib/generators/dry_crud/templates/test/functional/crud_controller_test_helper.rb
|
@@ -87,7 +86,6 @@ files:
|
|
87
86
|
- lib/generators/dry_crud/templates/test/unit/custom_assertions_test.rb
|
88
87
|
- lib/generators/dry_crud/templates/test/unit/helpers/crud_helper_test.rb
|
89
88
|
- lib/generators/dry_crud/templates/test/unit/helpers/list_helper_test.rb
|
90
|
-
- lib/generators/dry_crud/templates/test/unit/helpers/render_inheritable_test.rb
|
91
89
|
- lib/generators/dry_crud/templates/test/unit/helpers/standard_form_builder_test.rb
|
92
90
|
- lib/generators/dry_crud/templates/test/unit/helpers/standard_helper_test.rb
|
93
91
|
- lib/generators/dry_crud/templates/test/unit/helpers/standard_table_builder_test.rb
|
@@ -101,7 +99,7 @@ files:
|
|
101
99
|
- test/templates/app/models/person.rb
|
102
100
|
- test/templates/app/views/ajax/_actions_index.html.erb
|
103
101
|
- test/templates/app/views/ajax/_hello.html.erb
|
104
|
-
- test/templates/app/views/ajax/ajax.js.
|
102
|
+
- test/templates/app/views/ajax/ajax.js.erb
|
105
103
|
- test/templates/app/views/cities/_form.html.erb
|
106
104
|
- test/templates/app/views/cities/_hello.html.erb
|
107
105
|
- test/templates/app/views/cities/_list.html.erb
|
@@ -1,153 +0,0 @@
|
|
1
|
-
# Allows one to render inheritable views and partials.
|
2
|
-
# If no view file is found for the current controller, the corresponding file
|
3
|
-
# is looked up in its superclass hierarchy. This module must only be
|
4
|
-
# included in the root controller of the desired lookup hierarchy.
|
5
|
-
#
|
6
|
-
# By default, this module only supports direct inheritance over one level. By overriding
|
7
|
-
# the method lookup_path, you may define a custom lookup path. By providing an object
|
8
|
-
# for the 'with' parameter, this path may even be dynamic.
|
9
|
-
module RenderInheritable
|
10
|
-
|
11
|
-
# Add inheritable_root_path method to including controller.
|
12
|
-
def self.included(controller_class)
|
13
|
-
controller_class.send(:extend, ClassMethods)
|
14
|
-
|
15
|
-
controller_class.send(:class_variable_set, :@@inheritable_root_controller, controller_class)
|
16
|
-
controller_class.cattr_reader :inheritable_root_controller
|
17
|
-
end
|
18
|
-
|
19
|
-
# Performs a lookup for the given filename and returns the most specific
|
20
|
-
# folder that contains the file.
|
21
|
-
def find_inheritable_template_folder(name, partial = false)
|
22
|
-
self.class.find_inheritable_template_folder(view_context, name, partial, formats, template_lookup_param)
|
23
|
-
end
|
24
|
-
|
25
|
-
# Override this method to specify a dynamic parameter used in the lookup path.
|
26
|
-
# For the default inheritance lookup, this parameter is not needed.
|
27
|
-
def template_lookup_param
|
28
|
-
nil
|
29
|
-
end
|
30
|
-
|
31
|
-
module ClassMethods
|
32
|
-
|
33
|
-
# Performs a lookup for the given filename and returns the most specific
|
34
|
-
# folder that contains the file.
|
35
|
-
def find_inheritable_template_folder(view_context, name, partial, formats, param = nil)
|
36
|
-
find_inheritable_template_folder_cached(view_context, name, partial, formats, param) do
|
37
|
-
find_inheritable_artifact(param) do |folder|
|
38
|
-
view_context.template_exists?(name, folder, partial)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Performs a lookup for a controller and returns the name of the most specific one found.
|
44
|
-
# This method is primarly usefull when given a 'param' argument that is used
|
45
|
-
# in a custom #template_lookup_path. In this case, no controller class would need to
|
46
|
-
# exist to render templates from corresponding view folders.
|
47
|
-
def inheritable_controller(param = nil)
|
48
|
-
descendants = inheritable_root_controller.descendants
|
49
|
-
c = find_inheritable_artifact(param) do |folder|
|
50
|
-
descendants.any? { |s| s.controller_path == folder }
|
51
|
-
end
|
52
|
-
c || inheritable_root_controller.controller_path
|
53
|
-
end
|
54
|
-
|
55
|
-
# Runs through the lookup path and yields each folder to the passed block.
|
56
|
-
# If the block returns true, this folder is returned and no further lookup
|
57
|
-
# happens. If no folder is found, the nil is returned.
|
58
|
-
def find_inheritable_artifact(param = nil)
|
59
|
-
template_lookup_path(param).each { |folder| return folder if yield(folder) }
|
60
|
-
nil
|
61
|
-
end
|
62
|
-
|
63
|
-
# An array of controller names / folders, ordered from most specific to most general.
|
64
|
-
# May be dynamic dependening on the passed 'param' argument.
|
65
|
-
# You may override this method in an own controller to customize the lookup path.
|
66
|
-
def template_lookup_path(param = nil)
|
67
|
-
inheritance_lookup_path
|
68
|
-
end
|
69
|
-
|
70
|
-
# The inheritance path of controllers that is used as default lookup path.
|
71
|
-
def inheritance_lookup_path
|
72
|
-
path = [self]
|
73
|
-
until path.last == inheritable_root_controller
|
74
|
-
path << path.last.superclass
|
75
|
-
end
|
76
|
-
path.collect(&:controller_path)
|
77
|
-
end
|
78
|
-
|
79
|
-
# Override view context class to include the render inheritable modules.
|
80
|
-
def view_context_class
|
81
|
-
@view_context_class ||= begin
|
82
|
-
Class.new(super) do
|
83
|
-
include RenderInheritable::View
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
private
|
89
|
-
|
90
|
-
# Performs a lookup for a template folder using the cache.
|
91
|
-
def find_inheritable_template_folder_cached(view_context, name, partial, formats, param = nil)
|
92
|
-
prefix = inheritable_cache_get(formats, name, partial, param)
|
93
|
-
return prefix if prefix
|
94
|
-
|
95
|
-
prefix = yield
|
96
|
-
|
97
|
-
if prefix
|
98
|
-
template = view_context.find_template_without_lookup(name, prefix, partial)
|
99
|
-
inheritable_cache_set(template.formats, name, partial, param, prefix)
|
100
|
-
end
|
101
|
-
prefix
|
102
|
-
end
|
103
|
-
|
104
|
-
# A simple template lookup cache for each controller.
|
105
|
-
def inheritable_cache #:nodoc:
|
106
|
-
# do not store keys on each access, only return default structure
|
107
|
-
@inheritable_cache ||= Hash.new do |h1, k1|
|
108
|
-
Hash.new do |h2, k2|
|
109
|
-
Hash.new do |h3, k3|
|
110
|
-
Hash.new
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
# Gets the prefix from the cache. Returns nil if it's not there yet.
|
117
|
-
def inheritable_cache_get(formats, name, partial, param)
|
118
|
-
prefixes = formats.collect { |format| inheritable_cache[format.to_sym][partial][name][param] }
|
119
|
-
prefixes.compact!
|
120
|
-
prefixes.empty? ? nil : prefixes.first
|
121
|
-
end
|
122
|
-
|
123
|
-
# Stores the found prefix in the cache.
|
124
|
-
def inheritable_cache_set(formats, name, partial, param, prefix)
|
125
|
-
formats.each do |format|
|
126
|
-
# assign hash default values to respective key
|
127
|
-
inheritable_cache[format.to_sym] = hf = inheritable_cache[format.to_sym]
|
128
|
-
hf[partial] = hp = hf[partial]
|
129
|
-
hp[name] = hn = hp[name]
|
130
|
-
# finally store prefix in the deepest hash
|
131
|
-
hn[param] = prefix
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
end
|
136
|
-
|
137
|
-
# Extend ActionView so templates are looked up on a find_template call.
|
138
|
-
module View
|
139
|
-
def self.included(base)
|
140
|
-
base.send :alias_method_chain, :find_template, :lookup
|
141
|
-
end
|
142
|
-
|
143
|
-
# Perform a template lookup if the prefix corresponds to the current controller's path.
|
144
|
-
def find_template_with_lookup(name, prefix = nil, partial = false)
|
145
|
-
if prefix == controller_path
|
146
|
-
folder = controller.find_inheritable_template_folder(name, partial)
|
147
|
-
prefix = folder if folder
|
148
|
-
end
|
149
|
-
find_template_without_lookup(name, prefix, partial)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
end
|
@@ -1,153 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
TEST_VIEW_PATH = File.join(Rails.root, 'test', 'test_views')
|
4
|
-
|
5
|
-
class RootController < ApplicationController
|
6
|
-
include RenderInheritable
|
7
|
-
|
8
|
-
attr_accessor :default_template_format
|
9
|
-
|
10
|
-
append_view_path(TEST_VIEW_PATH)
|
11
|
-
|
12
|
-
def initialize(*args)
|
13
|
-
super(*args)
|
14
|
-
self.default_template_format = :html
|
15
|
-
end
|
16
|
-
|
17
|
-
def view_paths
|
18
|
-
self.class.view_paths
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
class ChildrenController < RootController
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
class GrandChildrenController < ChildrenController
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
# mock File object
|
32
|
-
class File
|
33
|
-
class << self
|
34
|
-
def touched
|
35
|
-
@touched ||= []
|
36
|
-
end
|
37
|
-
|
38
|
-
alias_method :orig_exists?, :exists?
|
39
|
-
def exists?(filename, *args)
|
40
|
-
touched.include?(filename) || orig_exists?(filename, *args)
|
41
|
-
end
|
42
|
-
|
43
|
-
def touch_template(file)
|
44
|
-
touched << File.join(ActionController::Base.view_paths.first, "#{file}.html.erb")
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
class RenderInheritableTest < ActiveSupport::TestCase
|
50
|
-
|
51
|
-
attr_reader :controller, :grand_controller
|
52
|
-
|
53
|
-
def setup
|
54
|
-
teardown
|
55
|
-
@controller = ChildrenController.new
|
56
|
-
@grand_controller = GrandChildrenController.new
|
57
|
-
ChildrenController.send(:inheritable_cache).clear
|
58
|
-
GrandChildrenController.send(:inheritable_cache).clear
|
59
|
-
end
|
60
|
-
|
61
|
-
def teardown
|
62
|
-
FileUtils.rm_rf(TEST_VIEW_PATH)
|
63
|
-
end
|
64
|
-
|
65
|
-
test "inheritable_root_controller" do
|
66
|
-
assert_equal RootController, RootController.inheritable_root_controller
|
67
|
-
assert_equal RootController, ChildrenController.inheritable_root_controller
|
68
|
-
assert_equal RootController, GrandChildrenController.inheritable_root_controller
|
69
|
-
end
|
70
|
-
|
71
|
-
test "lookup path" do
|
72
|
-
assert_equal ['children', 'root'], ChildrenController.send(:inheritance_lookup_path)
|
73
|
-
assert_equal ['grand_children', 'children', 'root'], GrandChildrenController.send(:inheritance_lookup_path)
|
74
|
-
end
|
75
|
-
|
76
|
-
test "inheritable controller finds controller instance" do
|
77
|
-
assert_equal 'children', ChildrenController.send(:inheritable_controller)
|
78
|
-
assert_equal 'grand_children', GrandChildrenController.send(:inheritable_controller)
|
79
|
-
end
|
80
|
-
|
81
|
-
test "find non-existing inheritable file" do
|
82
|
-
assert_nil @controller.send(:find_inheritable_template_folder, 'foo')
|
83
|
-
end
|
84
|
-
|
85
|
-
test "find inheritable file not overwritten" do
|
86
|
-
touch("root/root.html.erb")
|
87
|
-
|
88
|
-
assert_equal 'root', @controller.send(:find_inheritable_template_folder, 'root')
|
89
|
-
assert_equal 'root', @grand_controller.send(:find_inheritable_template_folder, 'root')
|
90
|
-
end
|
91
|
-
|
92
|
-
test "find inheritable file partially overwritten" do
|
93
|
-
touch("root/child.html.erb")
|
94
|
-
touch("children/child.html.erb")
|
95
|
-
|
96
|
-
assert_equal 'children', @controller.send(:find_inheritable_template_folder, 'child')
|
97
|
-
assert_equal 'children', @grand_controller.send(:find_inheritable_template_folder, 'child')
|
98
|
-
end
|
99
|
-
|
100
|
-
test "find inheritable file partially overwritten with gaps" do
|
101
|
-
touch("root/grandchild.html.erb")
|
102
|
-
touch("grand_children/grandchild.rhtml")
|
103
|
-
|
104
|
-
assert_equal 'root', @controller.send(:find_inheritable_template_folder, 'grandchild')
|
105
|
-
assert_equal 'grand_children', @grand_controller.send(:find_inheritable_template_folder, 'grandchild')
|
106
|
-
end
|
107
|
-
|
108
|
-
test "find inheritable file for js format" do
|
109
|
-
touch("root/_grandchild.js.rjs")
|
110
|
-
touch("grand_children/_grandchild.js.rjs")
|
111
|
-
|
112
|
-
assert_equal 'root', @controller.send(:find_inheritable_template_folder, 'grandchild', true)
|
113
|
-
assert_equal 'grand_children', @grand_controller.send(:find_inheritable_template_folder, 'grandchild', true)
|
114
|
-
|
115
|
-
assert_equal({:js => { true => {'grandchild' => {nil => 'root'}}}}, ChildrenController.send(:inheritable_cache))
|
116
|
-
assert_equal({:js => { true => {'grandchild' => {nil => 'grand_children'}}}}, GrandChildrenController.send(:inheritable_cache))
|
117
|
-
end
|
118
|
-
|
119
|
-
test "find inheritable file for xml format" do
|
120
|
-
touch("root/_grandchild.xml.builder")
|
121
|
-
touch("grand_children/_grandchild.xml.builder")
|
122
|
-
|
123
|
-
assert_equal 'root', @controller.send(:find_inheritable_template_folder, 'grandchild', true)
|
124
|
-
assert_equal 'grand_children', @grand_controller.send(:find_inheritable_template_folder, 'grandchild', true)
|
125
|
-
end
|
126
|
-
|
127
|
-
test "find inheritable file all overwritten" do
|
128
|
-
touch("root/all.html.erb")
|
129
|
-
touch("children/all.rhtml")
|
130
|
-
touch("grand_children/all.html.erb")
|
131
|
-
|
132
|
-
assert_equal 'children', @controller.send(:find_inheritable_template_folder, 'all')
|
133
|
-
assert_equal 'grand_children', @grand_controller.send(:find_inheritable_template_folder, 'all')
|
134
|
-
|
135
|
-
assert_equal({:html => { false => { 'all' => {nil => 'children'}}}}, ChildrenController.send(:inheritable_cache))
|
136
|
-
assert_equal({:html => { false => { 'all' => {nil => 'grand_children'}}}}, GrandChildrenController.send(:inheritable_cache))
|
137
|
-
|
138
|
-
assert_equal 'children', @controller.send(:find_inheritable_template_folder, 'all')
|
139
|
-
assert_equal 'grand_children', @grand_controller.send(:find_inheritable_template_folder, 'all')
|
140
|
-
|
141
|
-
assert_equal({:html => { false => { 'all' => {nil => 'children'}}}}, ChildrenController.send(:inheritable_cache))
|
142
|
-
assert_equal({:html => { false => { 'all' => {nil => 'grand_children'}}}}, GrandChildrenController.send(:inheritable_cache))
|
143
|
-
end
|
144
|
-
|
145
|
-
private
|
146
|
-
|
147
|
-
def touch(file)
|
148
|
-
f = File.join(TEST_VIEW_PATH, file)
|
149
|
-
FileUtils.mkdir_p(File.dirname(f))
|
150
|
-
FileUtils.touch(f)
|
151
|
-
end
|
152
|
-
|
153
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
page.replace_html(:response, :partial => 'hello')
|