dry_crud 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +32 -24
- data/Rakefile +73 -19
- data/VERSION +1 -1
- data/lib/generators/dry_crud/dry_crud_generator.rb +11 -2
- data/lib/generators/dry_crud/templates/app/assets/images/actions/delete.png +0 -0
- data/lib/generators/dry_crud/templates/app/assets/stylesheets/crud.scss +64 -0
- data/lib/generators/dry_crud/templates/app/assets/stylesheets/sample.scss +258 -0
- data/lib/generators/dry_crud/templates/app/controllers/crud_controller.rb +30 -24
- data/lib/generators/dry_crud/templates/app/controllers/list_controller.rb +93 -7
- data/lib/generators/dry_crud/templates/app/helpers/crud_helper.rb +70 -16
- data/lib/generators/dry_crud/templates/app/helpers/list_helper.rb +1 -0
- data/lib/generators/dry_crud/templates/app/helpers/standard_form_builder.rb +11 -3
- data/lib/generators/dry_crud/templates/app/helpers/standard_helper.rb +36 -45
- data/lib/generators/dry_crud/templates/app/helpers/standard_table_builder.rb +4 -3
- data/lib/generators/dry_crud/templates/app/views/crud/_actions_edit.html.erb +2 -2
- data/lib/generators/dry_crud/templates/app/views/crud/_actions_edit.html.haml +3 -0
- data/lib/generators/dry_crud/templates/app/views/crud/_actions_index.html.haml +1 -0
- data/lib/generators/dry_crud/templates/app/views/crud/_actions_show.html.erb +2 -2
- data/lib/generators/dry_crud/templates/app/views/crud/_actions_show.html.haml +3 -0
- data/lib/generators/dry_crud/templates/app/views/crud/_attrs.html.erb +1 -1
- data/lib/generators/dry_crud/templates/app/views/crud/_attrs.html.haml +1 -0
- data/lib/generators/dry_crud/templates/app/views/crud/_form.html.haml +1 -0
- data/lib/generators/dry_crud/templates/app/views/crud/_list.html.haml +1 -0
- data/lib/generators/dry_crud/templates/app/views/crud/edit.html.erb +0 -2
- data/lib/generators/dry_crud/templates/app/views/crud/edit.html.haml +5 -0
- data/lib/generators/dry_crud/templates/app/views/crud/new.html.erb +0 -2
- data/lib/generators/dry_crud/templates/app/views/crud/new.html.haml +5 -0
- data/lib/generators/dry_crud/templates/app/views/crud/show.html.erb +0 -2
- data/lib/generators/dry_crud/templates/app/views/crud/show.html.haml +7 -0
- data/lib/generators/dry_crud/templates/app/views/layouts/_flash.html.erb +8 -0
- data/lib/generators/dry_crud/templates/app/views/layouts/_flash.html.haml +4 -0
- data/lib/generators/dry_crud/templates/app/views/layouts/_menu.html.erb +3 -0
- data/lib/generators/dry_crud/templates/app/views/layouts/_menu.html.haml +3 -0
- data/lib/generators/dry_crud/templates/app/views/layouts/_nav.html.erb +6 -0
- data/lib/generators/dry_crud/templates/app/views/layouts/_nav.html.haml +3 -0
- data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.erb +40 -21
- data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.haml +42 -0
- data/lib/generators/dry_crud/templates/app/views/list/_actions_index.html.haml +0 -0
- data/lib/generators/dry_crud/templates/app/views/list/_list.html.haml +1 -0
- data/lib/generators/dry_crud/templates/app/views/list/_search.html.erb +4 -3
- data/lib/generators/dry_crud/templates/app/views/list/_search.html.haml +5 -0
- data/lib/generators/dry_crud/templates/app/views/list/index.html.erb +2 -4
- data/lib/generators/dry_crud/templates/app/views/list/index.html.haml +7 -0
- data/lib/generators/dry_crud/templates/app/views/shared/_error_messages.html.erb +1 -1
- data/lib/generators/dry_crud/templates/app/views/shared/_error_messages.html.haml +6 -0
- data/lib/generators/dry_crud/templates/app/views/shared/_labeled.html.erb +1 -1
- data/lib/generators/dry_crud/templates/app/views/shared/_labeled.html.haml +3 -0
- data/lib/generators/dry_crud/templates/config/locales/en_crud.yml +6 -6
- data/lib/generators/dry_crud/templates/test/crud_test_model.rb +5 -1
- data/lib/generators/dry_crud/templates/test/custom_assertions.rb +4 -4
- data/lib/generators/dry_crud/templates/test/functional/crud_controller_test_helper.rb +40 -32
- data/lib/generators/dry_crud/templates/test/functional/crud_test_models_controller_test.rb +3 -5
- data/lib/generators/dry_crud/templates/test/unit/helpers/crud_helper_test.rb +5 -3
- data/lib/generators/dry_crud/templates/test/unit/helpers/standard_form_builder_test.rb +4 -4
- data/lib/generators/dry_crud/templates/test/unit/helpers/standard_helper_test.rb +11 -25
- data/lib/generators/dry_crud/templates/test/unit/helpers/standard_table_builder_test.rb +9 -9
- data/test/templates/Gemfile +13 -6
- data/test/templates/app/controllers/admin/cities_controller.rb +14 -0
- data/test/templates/app/controllers/admin/countries_controller.rb +14 -0
- data/test/templates/app/controllers/people_controller.rb +1 -1
- data/test/templates/app/controllers/vips_controller.rb +2 -2
- data/test/templates/app/helpers/cities_helper.rb +9 -0
- data/test/templates/app/models/city.rb +4 -3
- data/test/templates/app/models/country.rb +14 -0
- data/test/templates/app/views/admin/cities/_actions_index.html.erb +2 -0
- data/test/templates/app/views/admin/cities/_actions_index.html.haml +2 -0
- data/test/templates/app/views/admin/cities/_form.html.erb +1 -0
- data/test/templates/app/views/admin/cities/_form.html.haml +1 -0
- data/test/templates/app/views/{cities → admin/cities}/_hello.html.erb +0 -0
- data/test/templates/app/views/admin/cities/_hello.html.haml +1 -0
- data/test/templates/app/views/admin/cities/_list.html.erb +6 -0
- data/test/templates/app/views/admin/cities/_list.html.haml +5 -0
- data/test/templates/app/views/admin/countries/_list.html.erb +5 -0
- data/test/templates/app/views/admin/countries/_list.html.haml +4 -0
- data/test/templates/app/views/ajax/_actions_index.html.haml +8 -0
- data/test/templates/app/views/ajax/_hello.html.haml +1 -0
- data/test/templates/app/views/ajax/ajax.js.haml +1 -0
- data/test/templates/app/views/layouts/_menu.html.erb +1 -1
- data/test/templates/app/views/layouts/_menu.html.haml +3 -0
- data/test/templates/app/views/people/_attrs.html.haml +4 -0
- data/test/templates/app/views/people/_list.html.haml +1 -0
- data/test/templates/config/database.yml +8 -9
- data/test/templates/config/locales/en_cities.yml +3 -3
- data/test/templates/config/routes.rb +16 -8
- data/test/templates/db/migrate/20100511174904_create_people_and_cities.rb +7 -7
- data/test/templates/db/seeds.rb +11 -5
- data/test/templates/test/fixtures/cities.yml +3 -3
- data/test/templates/test/fixtures/countries.yml +11 -0
- data/test/templates/test/functional/admin/cities_controller_test.rb +59 -0
- data/test/templates/test/functional/admin/countries_controller_test.rb +43 -0
- data/test/templates/test/functional/people_controller_test.rb +6 -1
- metadata +54 -15
- data/lib/generators/dry_crud/templates/app/assets/stylesheets/crud.css +0 -239
- data/test/templates/app/controllers/cities_controller.rb +0 -10
- data/test/templates/app/views/cities/_form.html.erb +0 -8
- data/test/templates/app/views/cities/_list.html.erb +0 -4
- data/test/templates/test/functional/cities_controller_test.rb +0 -45
data/README.rdoc
CHANGED
@@ -1,40 +1,42 @@
|
|
1
1
|
= DRY CRUD
|
2
2
|
|
3
|
-
DRY CRUD generates simple and extendable controller, views and helpers that support you to DRY up the CRUD code in your Rails project. Start with these elements and build a clean base to efficiently develop your application upon.
|
3
|
+
DRY CRUD generates simple and extendable controller, views and helpers that support you to DRY up the CRUD code in your Rails project. Start with these elements and build a clean base to efficiently develop your application upon.
|
4
4
|
|
5
|
-
|
5
|
+
Create your Rails application directly with the DRY CRUD application template:
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
gem 'dry_crud'
|
11
|
-
end
|
12
|
-
|
13
|
-
Don't worry, it's a simple development dependency. You may even savely remove it after you have run in once. So now, you should run the generator to get the goodies:
|
7
|
+
rails new [APP_NAME] -m https://raw.github.com/codez/dry_crud/master/template.rb
|
8
|
+
|
9
|
+
If your application already exists or you prefer the DIY way, then install the Gem (<tt>gem install dry_crud</tt>), add it to your Gemfile and run the generator. You may remove the Gemfile entry again afterwards, it is not required anymore.
|
14
10
|
|
15
11
|
rails generate dry_crud
|
12
|
+
|
13
|
+
If you prefer HAML templates instead of ERB, run
|
14
|
+
|
15
|
+
rails generate dry_crud -t haml
|
16
16
|
|
17
17
|
To integrate DRY CRUD into your code, only a few additions are required:
|
18
18
|
|
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.5 and higher are built for Rails 3.2. 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 and above are fully compatible with Ruby 1.8.7, Ruby 1.9.2 and JRuby.
|
23
23
|
|
24
24
|
== Overview
|
25
25
|
|
26
|
-
In most Rails applications, you have some models that require basic CRUD (create, read, update, delete) functionality. There are various possibilities like Rails scaffolding, {Inherited Resources}[https://github.com/josevalim/inherited_resources] or {Dry Scaffold}[http://github.com/grimen/dry_scaffold]. Still, various parts in your application remain duplicated. While you might pull up common methods into a common superclass controller, most views still contain very similar code.
|
26
|
+
In most Rails applications, you have some models that require basic CRUD (create, read, update, delete) functionality. There are various possibilities like Rails scaffolding, {Inherited Resources}[https://github.com/josevalim/inherited_resources] or {Dry Scaffold}[http://github.com/grimen/dry_scaffold]. Still, various parts in your application remain duplicated. While you might pull up common methods into a common superclass controller, most views still contain very similar code. And then you also have to remember the entire API of these frameworks.
|
27
27
|
|
28
28
|
Enter DRY CRUD.
|
29
29
|
|
30
30
|
<b>
|
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
|
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 browse easily and adapt freely 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
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.
|
35
35
|
|
36
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.
|
37
37
|
|
38
|
+
A basic CSS gets you started with your application's layout. For advanced needs, DRY CRUD supports the styles and classes used in {Bootstrap}[http://twitter.github.com/bootstrap/]. A great design never was so close.
|
39
|
+
|
38
40
|
If you find yourself adapting the same parts of DRY CRUD for your applications over and over, please feel free to {fork me on Github}[http://github.com/codez/dry_crud].
|
39
41
|
|
40
42
|
See the Examples section for some use cases and the Generated Files section below for details on the single classes and templates.
|
@@ -83,12 +85,6 @@ In <tt>app/views/list/index.html.erb</tt>, add the following line for the pagina
|
|
83
85
|
<%= will_paginate @entries %>
|
84
86
|
|
85
87
|
And we are done again. All our controllers inheriting from +ListController+, including above +PeopleController+, now have paginated index views. Because our customization for the people table is in the separate <tt>_list</tt> partial, no further modifications are required.
|
86
|
-
If the current page should be remembered while viewing or editing an entry, just add :page to the remembered_params in <tt>ListController::Memory</tt>:
|
87
|
-
|
88
|
-
controller.remember_params = [:q, :sort, :sort_dir, :page]
|
89
|
-
|
90
|
-
In this case, you should also pass the parameter <tt>page=1</tt> with a hidden field in your <tt>list/_search.html.erb</tt> to start displaying search results at page one.
|
91
|
-
|
92
88
|
|
93
89
|
==== Special formatting for selected attributes
|
94
90
|
|
@@ -101,7 +97,7 @@ In <tt>app/helpers/people.rb</tt>:
|
|
101
97
|
|
102
98
|
Should you have attributes with the same name for multiple models that you want to be formatted the same way, you may define a helper method <tt>format_{attr}</tt> for these attributes.
|
103
99
|
|
104
|
-
By the way: The method <tt>:f</tt> in +StandardHelper+ uniformly formats arbitrary values according to their class.
|
100
|
+
By the way: The method <tt>:f</tt> in +StandardHelper+ uniformly formats arbitrary values according to their class.
|
105
101
|
|
106
102
|
|
107
103
|
==== Filtering the index list
|
@@ -185,11 +181,23 @@ Even +belongs_to+ associations are automatically rendered with a select field. B
|
|
185
181
|
|
186
182
|
Yes, it's bad practice to use finder logic in your views! Define the variable <tt>@hometowns</tt> in your controller instead (as shown in the example above), and you do not even have to specify the <tt>:list</tt> option.
|
187
183
|
|
184
|
+
|
185
|
+
=== Nested Resources
|
186
|
+
|
187
|
+
In case you define nested resources, your +CrudController+ subclass should know. Listing and creating entries as well as displaying links for these resources is dependent on the nesting hierarchy. This is how you declare the namespaces and parent resources in your controller:
|
188
|
+
|
189
|
+
self.nesting = :my_namspace, ParentResource
|
190
|
+
|
191
|
+
This declaration is for a controller nested in +parent_resources+ within a +:my_namespace+ scope. +ParentResource+ is the corresponding +ActiveRecord+ model. The request param +:parent_resource_id+ is used to load the parent entry, which in turn is used to filter the entries listed and created in your controller.
|
192
|
+
|
193
|
+
The <tt>ListController::Nesting</tt> module defines this basic behaviour. For more complex setups, have a look there and adjust it to your needs.
|
194
|
+
|
195
|
+
|
188
196
|
=== Internationalization (I18N)
|
189
197
|
|
190
198
|
All text strings used are externalized to an english locale yaml. The keys are organized by controller and template name plus a generic global scope.
|
191
199
|
|
192
|
-
To represent
|
200
|
+
To represent your controller hierarchy, a special translation helper <tt>:ti</tt> looks up keys along the hierarchy in the following order:
|
193
201
|
{controller_name}.{template_name}.{key}
|
194
202
|
{controller_name}.{action_name}.{key}
|
195
203
|
{controller_name}.global.{key}
|
@@ -215,7 +223,7 @@ All generated files are supposed to provide a reasonable foundation for the CRUD
|
|
215
223
|
|
216
224
|
{controller/crud_controller.rb}[http://codez.ch/dry_crud/?q=CrudController]:: Abstract controller providing basic CRUD actions. This implementation mainly follows the one of the Rails scaffolding controller and responses to HTML and XML requests. Some enhancements were made to ease extendability. Several protected helper methods are there to be (optionally) overriden by subclasses. With the help of additional callbacks, it is possible to hook into the action procedures without overriding the entire method. This class is based on +ListController+.
|
217
225
|
|
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.
|
226
|
+
{controller/list_controller.rb}[http://codez.ch/dry_crud/?q=ListController]:: Abstract controller providing a basic list action. Use this controller if you require read-only functionality. 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.
|
219
227
|
|
220
228
|
|
221
229
|
=== Helpers:
|
@@ -275,9 +283,9 @@ views/layouts/crud.html.erb:: An example layout showing how to use the <tt>@titl
|
|
275
283
|
|
276
284
|
views/layouts/_menu.html.erb:: An empty file to put your menu items into. Included from <tt>crud.html.erb</tt>.
|
277
285
|
|
278
|
-
|
286
|
+
app/assets/stylesheets/crud.scss:: A simple SCSS with all the classes and ids used in the CRUD code.
|
279
287
|
|
280
|
-
|
288
|
+
app/assets/images/action/*.png:: Some sample action icons from the {Open Icon Library}[http://openiconlibrary.sourceforge.net].
|
281
289
|
|
282
290
|
|
283
291
|
=== Tests:
|
@@ -291,4 +299,4 @@ public/images/action/*.png:: Some sample action icons from the {Open Icon Librar
|
|
291
299
|
test/several other tests:: Testing the provided implementation and a great base to test your adaptions of the CRUD code.
|
292
300
|
|
293
301
|
|
294
|
-
|
302
|
+
{<img src="https://secure.travis-ci.org/codez/dry_crud.png" />}[http://travis-ci.org/codez/dry_crud]
|
data/Rakefile
CHANGED
@@ -19,16 +19,6 @@ task :test => ['test:app:init'] do
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
require 'rcov/rcovtask'
|
23
|
-
Rcov::RcovTask.new do |test|
|
24
|
-
test.libs << "test/test_app/test"
|
25
|
-
test.test_files = Dir[ "test/test_app/test/**/*_test.rb" ]
|
26
|
-
test.rcov_opts = ['--text-report',
|
27
|
-
'-i', '"test\/test_app\/app\/.*"',
|
28
|
-
'-x', '"\/Library\/Ruby\/.*"']
|
29
|
-
test.verbose = true
|
30
|
-
end
|
31
|
-
|
32
22
|
namespace :test do
|
33
23
|
namespace :app do
|
34
24
|
task :environment do
|
@@ -41,7 +31,7 @@ namespace :test do
|
|
41
31
|
desc "Create a rails test application"
|
42
32
|
task :create do
|
43
33
|
unless File.exist?(TEST_APP_ROOT)
|
44
|
-
sh "rails new #{TEST_APP_ROOT}"
|
34
|
+
sh "rails new #{TEST_APP_ROOT} --skip-bundle"
|
45
35
|
FileUtils.cp(File.join(File.dirname(__FILE__), 'test', 'templates', 'Gemfile'), TEST_APP_ROOT)
|
46
36
|
sh "cd #{TEST_APP_ROOT}; bundle install" # update Gemfile.lock
|
47
37
|
FileUtils.rm_f(File.join(TEST_APP_ROOT, 'test', 'performance', 'browsing_test.rb'))
|
@@ -52,21 +42,64 @@ namespace :test do
|
|
52
42
|
task :generate_crud => [:create, :environment] do
|
53
43
|
require File.join(GENERATOR_ROOT, 'dry_crud_generator')
|
54
44
|
|
55
|
-
DryCrudGenerator.new('', {:force => true}, :destination_root => TEST_APP_ROOT).invoke_all
|
45
|
+
DryCrudGenerator.new('', {:force => true, :templates => ENV['HAML'] ? 'haml' : 'erb'}, :destination_root => TEST_APP_ROOT).invoke_all
|
56
46
|
end
|
57
47
|
|
58
|
-
desc "
|
59
|
-
task :
|
48
|
+
desc "Populates the test application with some models and controllers"
|
49
|
+
task :populate => :generate_crud do
|
50
|
+
# copy test app templates
|
60
51
|
FileUtils.cp_r(File.join(File.dirname(__FILE__), 'test', 'templates', '.'), TEST_APP_ROOT)
|
52
|
+
|
53
|
+
# replace some unused files
|
61
54
|
FileUtils.rm_f(File.join(TEST_APP_ROOT, 'public', 'index.html'))
|
62
|
-
|
63
|
-
|
64
|
-
|
55
|
+
layouts = File.join(TEST_APP_ROOT, 'app', 'views', 'layouts')
|
56
|
+
FileUtils.mv(File.join(layouts, 'crud.html.erb'),
|
57
|
+
File.join(layouts, 'application.html.erb'),
|
58
|
+
:force => true) if File.exists?(File.join(layouts, 'crud.html.erb'))
|
59
|
+
FileUtils.mv(File.join(layouts, 'crud.html.haml'),
|
60
|
+
File.join(layouts, 'application.html.haml'),
|
61
|
+
:force => true) if File.exists?(File.join(layouts, 'crud.html.haml'))
|
62
|
+
|
63
|
+
# remove unused template type, erb or haml
|
64
|
+
exclude = ENV['HAML'] ? 'erb' : 'haml'
|
65
|
+
Dir.glob(File.join(TEST_APP_ROOT, 'app', 'views', '**', "*.#{exclude}")).each do |f|
|
66
|
+
FileUtils.rm(f)
|
67
|
+
end
|
68
|
+
|
69
|
+
# migrate the database
|
65
70
|
FileUtils.cd(TEST_APP_ROOT) do
|
66
|
-
sh "rake db:migrate db:seed RAILS_ENV=development"
|
67
|
-
sh "rake db:migrate RAILS_ENV=test" # db:test:prepare does not work for jdbcsqlite3
|
71
|
+
sh "rake db:migrate db:seed RAILS_ENV=development --trace"
|
72
|
+
sh "rake db:migrate RAILS_ENV=test --trace" # db:test:prepare does not work for jdbcsqlite3
|
68
73
|
end
|
69
74
|
end
|
75
|
+
|
76
|
+
desc "Initializes the test application with a couple of classes"
|
77
|
+
task :init => [:populate,
|
78
|
+
:customize]
|
79
|
+
|
80
|
+
desc "Customize some of the functionality provided by dry_crud"
|
81
|
+
task :customize => ['test:app:add_pagination'
|
82
|
+
#'test:app:use_bootstrap'
|
83
|
+
]
|
84
|
+
|
85
|
+
desc "Adds pagination to the test app"
|
86
|
+
task :add_pagination => :generate_crud do
|
87
|
+
list_ctrl = File.join(TEST_APP_ROOT, 'app', 'controllers', 'list_controller.rb')
|
88
|
+
file_replace(list_ctrl, "@entries = list_entries",
|
89
|
+
"@entries = list_entries.page(params[:page]).per(10)")
|
90
|
+
file_replace(File.join(TEST_APP_ROOT, 'app', 'views', 'list', 'index.html.erb'),
|
91
|
+
"<%= render 'list' %>", "<%= paginate @entries %>\n\n<%= render 'list' %>")
|
92
|
+
file_replace(File.join(TEST_APP_ROOT, 'app', 'views', 'list', 'index.html.haml'),
|
93
|
+
"= render 'list'", "= paginate @entries\n\n= render 'list'")
|
94
|
+
end
|
95
|
+
|
96
|
+
desc "Use Boostrap in the test app"
|
97
|
+
task :use_bootstrap => :generate_crud do
|
98
|
+
file_replace(File.join(TEST_APP_ROOT, 'app', 'assets', 'stylesheets', 'application.css'), " *= require_self", "*= require twitter/bootstrap\n *= require_self")
|
99
|
+
file_replace(File.join(TEST_APP_ROOT, 'app', 'assets', 'javascripts', 'application.js'), "//= require_tree .", "//= require twitter/bootstrap\n//= require_tree .")
|
100
|
+
FileUtils.rm(File.join(TEST_APP_ROOT, 'app', 'assets', 'stylesheets', 'sample.scss'))
|
101
|
+
end
|
102
|
+
|
70
103
|
end
|
71
104
|
end
|
72
105
|
|
@@ -91,6 +124,18 @@ task :site => :rdoc do
|
|
91
124
|
end
|
92
125
|
end
|
93
126
|
|
127
|
+
if RUBY_VERSION == '1.8.7' && RUBY_PLATFORM != 'java'
|
128
|
+
require 'rcov/rcovtask'
|
129
|
+
Rcov::RcovTask.new do |test|
|
130
|
+
test.libs << "test/test_app/test"
|
131
|
+
test.test_files = Dir[ "test/test_app/test/**/*_test.rb" ]
|
132
|
+
test.rcov_opts = ['--text-report',
|
133
|
+
'-i', '"test\/test_app\/app\/.*"',
|
134
|
+
'-x', '"\/Library\/Ruby\/.*"']
|
135
|
+
test.verbose = true
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
94
139
|
# :package task
|
95
140
|
Gem::PackageTask.new(DRY_CRUD_GEMSPEC) do |pkg|
|
96
141
|
if Rake.application.top_level_tasks.include?('release')
|
@@ -125,3 +170,12 @@ task :release do
|
|
125
170
|
puts " $ rake repackage"
|
126
171
|
puts " $ gem push pkg/dry_crud-#{version}.gem"
|
127
172
|
end
|
173
|
+
|
174
|
+
|
175
|
+
def file_replace(file, expression, replacement)
|
176
|
+
return unless File.exists?(file)
|
177
|
+
text = File.read(file)
|
178
|
+
replaced = text.gsub(expression, replacement)
|
179
|
+
puts "WARN: Nothing replaced in '#{file}' for '#{expression}'" if text == replaced
|
180
|
+
File.open(file, "w") { |f| f.puts replaced }
|
181
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.5.0
|
@@ -2,15 +2,24 @@ require 'rails/generators'
|
|
2
2
|
|
3
3
|
class DryCrudGenerator < Rails::Generators::Base
|
4
4
|
|
5
|
+
class_options %w(templates -t) => 'erb'
|
6
|
+
|
7
|
+
|
5
8
|
def self.source_root
|
6
9
|
File.join(File.dirname(__FILE__), 'templates')
|
7
10
|
end
|
8
11
|
|
9
12
|
def install_dry_crud
|
10
13
|
# copy everything in template subfolders
|
14
|
+
exclude = options[:templates].downcase == 'haml' ? '.erb' : '.haml'
|
15
|
+
|
11
16
|
Dir.chdir(self.class.source_root) do
|
12
|
-
Dir.glob(
|
13
|
-
|
17
|
+
Dir.glob(File.join('**', '**')).sort.each do |file_source|
|
18
|
+
if !File.directory?(file_source) &&
|
19
|
+
!file_source.ends_with?(exclude) &&
|
20
|
+
file_source != 'INSTALL'
|
21
|
+
copy_file(file_source)
|
22
|
+
end
|
14
23
|
end
|
15
24
|
end
|
16
25
|
|
Binary file
|
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
.right {
|
3
|
+
text-align: right;
|
4
|
+
}
|
5
|
+
|
6
|
+
.center {
|
7
|
+
text-align: center;
|
8
|
+
}
|
9
|
+
|
10
|
+
.labeled {
|
11
|
+
vertical-align: top;
|
12
|
+
padding-bottom: 5px;
|
13
|
+
clear: both;
|
14
|
+
}
|
15
|
+
|
16
|
+
.labeled label {
|
17
|
+
width: 120px;
|
18
|
+
padding-right: 5px;
|
19
|
+
float: left;
|
20
|
+
}
|
21
|
+
|
22
|
+
.labeled .value {
|
23
|
+
margin-left: 130px;
|
24
|
+
}
|
25
|
+
|
26
|
+
.labeled .value p {
|
27
|
+
margin: 0;
|
28
|
+
}
|
29
|
+
|
30
|
+
.control-group {
|
31
|
+
clear: both;
|
32
|
+
}
|
33
|
+
|
34
|
+
.control-group label {
|
35
|
+
float: left;
|
36
|
+
width: 120px;
|
37
|
+
padding-top: 5px;
|
38
|
+
padding-right: 5px;
|
39
|
+
}
|
40
|
+
|
41
|
+
.controls {
|
42
|
+
margin-left: 130px;
|
43
|
+
}
|
44
|
+
|
45
|
+
.required {
|
46
|
+
font-size: 80%;
|
47
|
+
vertical-align: top;
|
48
|
+
margin-left: 2px;
|
49
|
+
}
|
50
|
+
|
51
|
+
#error_explanation h2 {
|
52
|
+
font-size: 100%;
|
53
|
+
margin-top: 0px;
|
54
|
+
}
|
55
|
+
|
56
|
+
#error_explanation ul {
|
57
|
+
margin-bottom: 5px;
|
58
|
+
}
|
59
|
+
|
60
|
+
.controls div.field_with_errors {
|
61
|
+
background-color: #da9;
|
62
|
+
display: inline-block;
|
63
|
+
padding: 1px 1px;
|
64
|
+
}
|
@@ -0,0 +1,258 @@
|
|
1
|
+
$container_width: 1000px;
|
2
|
+
$theme_color: #2580a2;
|
3
|
+
|
4
|
+
body, div, p, td, th {
|
5
|
+
font-family: Verdana, Geneva, Helvetica, Arial, sans-serif;
|
6
|
+
font-size: 13px;
|
7
|
+
}
|
8
|
+
|
9
|
+
body {
|
10
|
+
text-align: center;
|
11
|
+
margin: 0;
|
12
|
+
background-color: #ddf;
|
13
|
+
}
|
14
|
+
|
15
|
+
.container {
|
16
|
+
padding: 20px 20px;
|
17
|
+
margin: 0 auto;
|
18
|
+
text-align: left;
|
19
|
+
max-width: $container_width;
|
20
|
+
min-width: $container_width - 200px;
|
21
|
+
height: 100%;
|
22
|
+
background-color: #f6f6ff;
|
23
|
+
-moz-box-shadow: 0px 0px 5px $theme_color;
|
24
|
+
-webkit-box-shadow: 0px 0px 5px $theme_color;
|
25
|
+
box-shadow: 0px 0px 5px $theme_color;
|
26
|
+
}
|
27
|
+
|
28
|
+
#content {
|
29
|
+
clear: both;
|
30
|
+
padding-top: 5px;
|
31
|
+
}
|
32
|
+
|
33
|
+
h1 {
|
34
|
+
font-size: 150%;
|
35
|
+
margin: 30px 0 15px 0;
|
36
|
+
}
|
37
|
+
|
38
|
+
.table thead tr:nth-child(odd), .table thead tr:nth-child(even) {
|
39
|
+
background-color: #D0D0D0;
|
40
|
+
}
|
41
|
+
|
42
|
+
.table tr:nth-child(odd) {
|
43
|
+
background-color: #F8F8F8;
|
44
|
+
}
|
45
|
+
|
46
|
+
.table tr:nth-child(even) {
|
47
|
+
background-color: #F0F0F0;
|
48
|
+
}
|
49
|
+
|
50
|
+
td {
|
51
|
+
vertical-align: top;
|
52
|
+
}
|
53
|
+
|
54
|
+
td p {
|
55
|
+
margin: 0;
|
56
|
+
}
|
57
|
+
|
58
|
+
a {
|
59
|
+
color: #2580a2;
|
60
|
+
text-decoration: none;
|
61
|
+
}
|
62
|
+
|
63
|
+
a:hover {
|
64
|
+
text-decoration: underline;
|
65
|
+
}
|
66
|
+
|
67
|
+
a:visited {
|
68
|
+
color: #2580a2;
|
69
|
+
}
|
70
|
+
|
71
|
+
a img {
|
72
|
+
border: none;
|
73
|
+
}
|
74
|
+
|
75
|
+
.table {
|
76
|
+
margin-top: 10px;
|
77
|
+
}
|
78
|
+
|
79
|
+
table.table {
|
80
|
+
border-collapse: collapse;
|
81
|
+
width: 100%;
|
82
|
+
padding: 0;
|
83
|
+
}
|
84
|
+
|
85
|
+
/* div rendered if no entries available for list */
|
86
|
+
div.table {}
|
87
|
+
|
88
|
+
table.table th {
|
89
|
+
text-align: left;
|
90
|
+
background-color: $theme_color;
|
91
|
+
color: white;
|
92
|
+
font-weight: bold;
|
93
|
+
padding: 2px 4px;
|
94
|
+
}
|
95
|
+
|
96
|
+
table.table th a {
|
97
|
+
color: white;
|
98
|
+
text-decoration: none;
|
99
|
+
}
|
100
|
+
|
101
|
+
table.table td {
|
102
|
+
padding: 2px 4px;
|
103
|
+
}
|
104
|
+
|
105
|
+
table.table td.action {
|
106
|
+
width: 20px;
|
107
|
+
text-align: center;
|
108
|
+
}
|
109
|
+
|
110
|
+
label {
|
111
|
+
font-style: italic;
|
112
|
+
}
|
113
|
+
|
114
|
+
.form-actions {
|
115
|
+
margin-left: 130px;
|
116
|
+
}
|
117
|
+
|
118
|
+
a.action {
|
119
|
+
padding: 0 5px;
|
120
|
+
}
|
121
|
+
|
122
|
+
a[class^="icon-"] {
|
123
|
+
margin-right: 5px;
|
124
|
+
margin-left: 5px;
|
125
|
+
}
|
126
|
+
|
127
|
+
a[class^="icon-"] img {
|
128
|
+
vertical-align: text-top;
|
129
|
+
}
|
130
|
+
|
131
|
+
[class^="icon-"] {
|
132
|
+
width: 16px;
|
133
|
+
height: 16px;
|
134
|
+
display: inline-block;
|
135
|
+
background: no-repeat;
|
136
|
+
vertical-align: top;
|
137
|
+
}
|
138
|
+
|
139
|
+
.icon-plus { background-image: image-url('actions/add.png'); }
|
140
|
+
.icon-remove { background-image: image-url('actions/delete.png'); }
|
141
|
+
.icon-pencil { background-image: image-url('actions/edit.png'); }
|
142
|
+
.icon-list { background-image: image-url('actions/list.png'); }
|
143
|
+
.icon-zoom-in { background-image: image-url('actions/show.png'); }
|
144
|
+
|
145
|
+
input, textarea {
|
146
|
+
font-family: Verdana, Geneva, Helvetica, Arial, sans-serif;
|
147
|
+
font-size: 10px;
|
148
|
+
}
|
149
|
+
|
150
|
+
input[type=text], input[type=password] {
|
151
|
+
width: 180px;
|
152
|
+
}
|
153
|
+
|
154
|
+
input[type=number] {
|
155
|
+
width: 80px;
|
156
|
+
}
|
157
|
+
|
158
|
+
textarea {
|
159
|
+
width: 180px;
|
160
|
+
height: 80px;
|
161
|
+
}
|
162
|
+
|
163
|
+
.cancel {
|
164
|
+
font-size: 80%;
|
165
|
+
margin-left: 7px;
|
166
|
+
}
|
167
|
+
|
168
|
+
.alert {
|
169
|
+
margin: 15px;
|
170
|
+
padding: 5px 10px;
|
171
|
+
}
|
172
|
+
|
173
|
+
.alert-success {
|
174
|
+
border: solid 2px #6a6;
|
175
|
+
background-color: #afa;
|
176
|
+
}
|
177
|
+
|
178
|
+
.alert-error {
|
179
|
+
border: solid 2px #da9;
|
180
|
+
background-color: #fec;
|
181
|
+
}
|
182
|
+
|
183
|
+
.close {
|
184
|
+
float: right;
|
185
|
+
}
|
186
|
+
|
187
|
+
.pull-right {
|
188
|
+
float: right;
|
189
|
+
}
|
190
|
+
|
191
|
+
.pull-left {
|
192
|
+
float: left;
|
193
|
+
}
|
194
|
+
|
195
|
+
.navbar {
|
196
|
+
background: #333;
|
197
|
+
-moz-box-shadow: 0px 1px 1px $theme_color;
|
198
|
+
-webkit-box-shadow: 0px 1px 1px $theme_color;
|
199
|
+
box-shadow: 0px 1px 1px $theme_color;
|
200
|
+
padding: 0 20px;
|
201
|
+
max-width: $container_width;
|
202
|
+
min-width: $container_width - 200px;
|
203
|
+
height: 33px;
|
204
|
+
margin: -20px;
|
205
|
+
}
|
206
|
+
|
207
|
+
.brand {
|
208
|
+
float: left;
|
209
|
+
display: block;
|
210
|
+
font-weight: bold;
|
211
|
+
font-size: 130%;
|
212
|
+
color: #ddd;
|
213
|
+
padding: 5px;
|
214
|
+
}
|
215
|
+
|
216
|
+
a.brand:hover {
|
217
|
+
text-decoration: none;
|
218
|
+
color: #ddd;
|
219
|
+
}
|
220
|
+
|
221
|
+
.nav {
|
222
|
+
list-style: none;
|
223
|
+
margin: 0;
|
224
|
+
float: left;
|
225
|
+
}
|
226
|
+
|
227
|
+
.nav li {
|
228
|
+
float: left;
|
229
|
+
font-size: 110%;
|
230
|
+
margin: 0;
|
231
|
+
padding: 0;
|
232
|
+
}
|
233
|
+
|
234
|
+
.nav a {
|
235
|
+
background: #333 bottom right no-repeat;
|
236
|
+
color: #ddd;
|
237
|
+
display: block;
|
238
|
+
float: left;
|
239
|
+
margin: 0;
|
240
|
+
padding: 8px 12px 8px;
|
241
|
+
text-decoration: none;
|
242
|
+
}
|
243
|
+
|
244
|
+
.nav a:hover {
|
245
|
+
background: $theme_color bottom center no-repeat;
|
246
|
+
color: #fff;
|
247
|
+
}
|
248
|
+
|
249
|
+
footer {
|
250
|
+
margin: auto;
|
251
|
+
text-align: right;
|
252
|
+
max-width: $container_width;
|
253
|
+
min-width: $container_width - 200px;
|
254
|
+
}
|
255
|
+
|
256
|
+
footer * {
|
257
|
+
font-size: 80%;
|
258
|
+
}
|