dry_crud 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. data/MIT-LICENSE +19 -0
  2. data/README.rdoc +208 -0
  3. data/Rakefile +101 -0
  4. data/VERSION +1 -0
  5. data/rails_generators/dry_crud/USAGE +1 -0
  6. data/rails_generators/dry_crud/dry_crud_generator.rb +22 -0
  7. data/rails_generators/dry_crud/templates/INSTALL +13 -0
  8. data/rails_generators/dry_crud/templates/app/controllers/crud_controller.rb +182 -0
  9. data/rails_generators/dry_crud/templates/app/helpers/crud_helper.rb +45 -0
  10. data/rails_generators/dry_crud/templates/app/helpers/standard_helper.rb +209 -0
  11. data/rails_generators/dry_crud/templates/app/views/crud/_attrs.html.erb +1 -0
  12. data/rails_generators/dry_crud/templates/app/views/crud/_form.html.erb +1 -0
  13. data/rails_generators/dry_crud/templates/app/views/crud/_list.html.erb +1 -0
  14. data/rails_generators/dry_crud/templates/app/views/crud/edit.html.erb +8 -0
  15. data/rails_generators/dry_crud/templates/app/views/crud/index.html.erb +14 -0
  16. data/rails_generators/dry_crud/templates/app/views/crud/new.html.erb +7 -0
  17. data/rails_generators/dry_crud/templates/app/views/crud/show.html.erb +9 -0
  18. data/rails_generators/dry_crud/templates/app/views/layouts/crud.html.erb +20 -0
  19. data/rails_generators/dry_crud/templates/app/views/shared/_labeled.html.erb +5 -0
  20. data/rails_generators/dry_crud/templates/lib/crud_callbacks.rb +55 -0
  21. data/rails_generators/dry_crud/templates/lib/render_inheritable.rb +118 -0
  22. data/rails_generators/dry_crud/templates/lib/standard_form_builder.rb +161 -0
  23. data/rails_generators/dry_crud/templates/lib/standard_table_builder.rb +104 -0
  24. data/rails_generators/dry_crud/templates/public/stylesheets/crud.css +91 -0
  25. data/rails_generators/dry_crud/templates/test/crud_test_model.rb +124 -0
  26. data/rails_generators/dry_crud/templates/test/functional/crud_controller_test_helper.rb +172 -0
  27. data/rails_generators/dry_crud/templates/test/functional/crud_test_models_controller_test.rb +96 -0
  28. data/rails_generators/dry_crud/templates/test/unit/crud_helper_test.rb +57 -0
  29. data/rails_generators/dry_crud/templates/test/unit/render_inheritable_test.rb +161 -0
  30. data/rails_generators/dry_crud/templates/test/unit/standard_form_builder_test.rb +83 -0
  31. data/rails_generators/dry_crud/templates/test/unit/standard_helper_test.rb +183 -0
  32. data/rails_generators/dry_crud/templates/test/unit/standard_table_builder_test.rb +99 -0
  33. data/test/templates/app/controllers/ajax_controller.rb +7 -0
  34. data/test/templates/app/controllers/application_controller.rb +11 -0
  35. data/test/templates/app/controllers/cities_controller.rb +13 -0
  36. data/test/templates/app/controllers/people_controller.rb +7 -0
  37. data/test/templates/app/helpers/people_helper.rb +7 -0
  38. data/test/templates/app/models/city.rb +13 -0
  39. data/test/templates/app/models/person.rb +9 -0
  40. data/test/templates/app/views/ajax/_hello.html.erb +1 -0
  41. data/test/templates/app/views/ajax/ajax.js.rjs +1 -0
  42. data/test/templates/app/views/ajax/index.html.erb +9 -0
  43. data/test/templates/app/views/cities/_attrs.html.erb +1 -0
  44. data/test/templates/app/views/cities/_form.html.erb +4 -0
  45. data/test/templates/app/views/cities/_hello.html.erb +1 -0
  46. data/test/templates/app/views/cities/_list.html.erb +5 -0
  47. data/test/templates/config/routes.rb +11 -0
  48. data/test/templates/db/migrate/20100511174904_create_people_and_cities.rb +23 -0
  49. data/test/templates/test/fixtures/cities.yml +11 -0
  50. data/test/templates/test/fixtures/people.yml +14 -0
  51. data/test/templates/test/functional/cities_controller_test.rb +35 -0
  52. data/test/templates/test/functional/people_controller_test.rb +30 -0
  53. metadata +127 -0
@@ -0,0 +1,104 @@
1
+ # A simple helper to easily define tables listing several rows of the same data type.
2
+ #
3
+ # Example Usage:
4
+ # StandardTableBuilder.table(entries, template) do |t|
5
+ # t.col('My Header', :class => 'css') {|e| link_to 'Show', e }
6
+ # t.attrs :name, :city
7
+ # end
8
+ class StandardTableBuilder
9
+ attr_reader :entries, :cols, :template
10
+
11
+ # Delegate called methods to template.
12
+ # including StandardHelper would lead to problems with indirectly called methods.
13
+ delegate :content_tag, :format_attr, :column_type, :belongs_to_association,
14
+ :captionize, :tr_alt, :to => :template
15
+
16
+ def initialize(entries, template)
17
+ @entries = entries
18
+ @template = template
19
+ @cols = []
20
+ end
21
+
22
+ # Convenience method to directly generate a table. Renders a row for each entry in entries.
23
+ # Takes a block that gets the table object as parameter for configuration.
24
+ # Returns the generated html for the table.
25
+ def self.table(entries, template)
26
+ t = new(entries, template)
27
+ yield t
28
+ t.to_html
29
+ end
30
+
31
+ # Define a column for the table with the given header, the html_options used for
32
+ # each td and a block rendering the contents of a cell for the current entry.
33
+ # The columns appear in the order they are defined.
34
+ def col(header = '', html_options = {}, &block)
35
+ @cols << Col.new(header, html_options, @template, block)
36
+ end
37
+
38
+ # Convenience method to add one or more attribute columns.
39
+ # The attribute name will become the header, the cells will contain
40
+ # the formatted attribute value for the current entry.
41
+ def attrs(*attrs)
42
+ attrs.each do |a|
43
+ col(captionize(a, entry_class), :class => align_class(a)) { |e| format_attr(e, a) }
44
+ end
45
+ end
46
+
47
+ # Renders the table as HTML.
48
+ def to_html
49
+ content_tag :table, :class => 'list' do
50
+ [html_header] +
51
+ entries.collect { |e| html_row(e) }
52
+ end
53
+ end
54
+
55
+ # Returns css classes used for alignment of the cell data.
56
+ # Based on the column type of the attribute.
57
+ def align_class(attr)
58
+ entry = entries.first
59
+ case column_type(entry, attr)
60
+ when :integer, :float, :decimal
61
+ 'right_align' unless belongs_to_association(entry, attr)
62
+ when :boolean
63
+ 'center_align'
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def html_header
70
+ content_tag :tr do
71
+ cols.collect { |c| c.html_header }
72
+ end
73
+ end
74
+
75
+ def html_row(entry)
76
+ tr_alt do
77
+ cols.collect { |c| c.html_cell(entry) }
78
+ end
79
+ end
80
+
81
+ def entry_class
82
+ entries.first.class
83
+ end
84
+
85
+ # Helper class to store column information.
86
+ class Col < Struct.new(:header, :html_options, :template, :block) #:nodoc:
87
+
88
+ delegate :content_tag, :to => :template
89
+
90
+ def content(entry)
91
+ block.call(entry)
92
+ end
93
+
94
+ def html_header
95
+ content_tag :th, header
96
+ end
97
+
98
+ def html_cell(entry)
99
+ content_tag :td, content(entry), html_options
100
+ end
101
+
102
+ end
103
+
104
+ end
@@ -0,0 +1,91 @@
1
+ body, div, p, td, th {
2
+ font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
3
+ font-size: 11pt;
4
+ }
5
+
6
+ td {
7
+ vertical-align: top;
8
+ }
9
+
10
+ tr.even {
11
+ background-color: #DDD;
12
+ }
13
+
14
+ tr.odd {
15
+ background-color: #EEE;
16
+ }
17
+
18
+ table.list {}
19
+
20
+ /* div rendered if no entries available for list */
21
+ div.list {}
22
+
23
+ .right_align {
24
+ text-align: right;
25
+ }
26
+
27
+ .center_align {
28
+ text-align: center;
29
+ }
30
+
31
+ .labeled {
32
+ vertical-align: top;
33
+ margin: 1pt;
34
+ }
35
+
36
+ .labeled .caption {
37
+ font-style: italic;
38
+ width: 120pt;
39
+ padding-right: 5pt;
40
+ float: left;
41
+ }
42
+
43
+ .labeled .value {
44
+ margin-left: 125pt;
45
+ }
46
+
47
+ .labeled .value p {
48
+ margin: 0px;
49
+ }
50
+
51
+ .attributes {}
52
+
53
+ a.action {
54
+ color: red;
55
+ text-decoration: none;
56
+ }
57
+
58
+ a:hover.action {
59
+ text-decoration: underline;
60
+ }
61
+
62
+ a:visited.action {
63
+ color: red;
64
+ }
65
+
66
+ #flash_notice {
67
+ color: #663333;
68
+ }
69
+
70
+ div.errorExplanation {
71
+ border: solid 1px #999999;
72
+ margin: 10pt;
73
+ padding: 5pt;
74
+ background-color: #FFBBBB;
75
+ }
76
+
77
+ .errorExplanation h2 {
78
+ font-size: 12pt;
79
+ margin-top: 0pt;
80
+ }
81
+
82
+ .errorExplanation ul {
83
+ margin-bottom: 5pt;
84
+ }
85
+
86
+ div.fieldWithErrors {
87
+ background-color: #FFBBBB;
88
+ display: inline-block;
89
+ padding: 2px;
90
+ }
91
+
@@ -0,0 +1,124 @@
1
+ class CrudTestModel < ActiveRecord::Base #:nodoc:
2
+ validates_presence_of :name
3
+
4
+ default_scope :order => 'name'
5
+
6
+ belongs_to :companion, :class_name => 'CrudTestModel'
7
+
8
+ def label
9
+ name
10
+ end
11
+ end
12
+
13
+ class CrudTestModelsController < CrudController #:nodoc:
14
+ HANDLE_PREFIX = 'handle_'
15
+
16
+ before_create :possibly_redirect
17
+ before_create :handle_name
18
+
19
+ before_render_new :possibly_redirect
20
+ before_render_new :set_companions
21
+
22
+ attr_reader :called_callbacks
23
+ attr_accessor :should_redirect
24
+
25
+ hide_action :called_callbacks, :should_redirect, :should_redirect=
26
+
27
+ private
28
+
29
+ # custom callback
30
+ def handle_name
31
+ if @entry.name == 'illegal'
32
+ flash[:error] = "illegal name"
33
+ return false
34
+ end
35
+ end
36
+
37
+ [:create, :update, :save, :destroy].each do |a|
38
+ callback = "before_#{a.to_s}"
39
+ send(callback.to_sym, :"#{HANDLE_PREFIX}#{callback}")
40
+ callback = "after_#{a.to_s}"
41
+ send(callback.to_sym, :"#{HANDLE_PREFIX}#{callback}")
42
+ end
43
+
44
+ def method_missing(sym, *args)
45
+ called_callback(sym.to_s[HANDLE_PREFIX.size..-1].to_sym) if sym.to_s.starts_with?(HANDLE_PREFIX)
46
+ end
47
+
48
+ def possibly_redirect
49
+ redirect_to :action => 'index' if should_redirect && !performed?
50
+ !should_redirect
51
+ end
52
+
53
+ def set_companions
54
+ @companions = CrudTestModel.all :conditions => {:human => true}
55
+ end
56
+
57
+ def called_callback(callback)
58
+ @called_callbacks ||= []
59
+ @called_callbacks << callback
60
+ end
61
+
62
+ end
63
+
64
+ ActionController::Routing::Routes.draw do |map|
65
+ map.resources :crud_test_models
66
+ end
67
+
68
+ # A simple test helper to prepare the test database with a CrudTestModel model.
69
+ module CrudTestHelper
70
+
71
+ protected
72
+
73
+ # Sets up the test database with a crud_test_models table.
74
+ # Look at the source to view the column definition.
75
+ def setup_db
76
+ silence_stream(STDOUT) do
77
+ ActiveRecord::Base.connection.create_table :crud_test_models, :force => true do |t|
78
+ t.string :name, :null => false, :limit => 50
79
+ t.string :whatever
80
+ t.integer :children
81
+ t.integer :companion_id
82
+ t.float :rating
83
+ t.decimal :income, :precision => 14, :scale => 2
84
+ t.date :birthdate
85
+ t.boolean :human, :default => true
86
+ t.text :remarks
87
+
88
+ t.timestamps
89
+ end
90
+ end
91
+ end
92
+
93
+ # Removes the crud_test_models table from the database.
94
+ def reset_db
95
+ [:crud_test_models].each do |table|
96
+ ActiveRecord::Base.connection.drop_table(table) rescue nil
97
+ end
98
+ end
99
+
100
+ # Creates 6 dummy entries for the crud_test_models table.
101
+ def create_test_data
102
+ (1..6).inject(nil) {|prev, i| create(i, prev) }
103
+ end
104
+
105
+ # Fixture-style accessor method to get CrudTestModel instances by name
106
+ def crud_test_models(name)
107
+ CrudTestModel.find_by_name(name.to_s)
108
+ end
109
+
110
+ private
111
+
112
+ def create(index, companion)
113
+ c = (index + 64).chr * 5
114
+ CrudTestModel.create!(:name => c,
115
+ :children => index,
116
+ :companion => companion,
117
+ :rating => "#{index}.#{index}".to_f,
118
+ :income => 10000000 * index + 0.1 * index,
119
+ :birthdate => "#{1900 + 10 * index}-#{index}-#{index}",
120
+ :human => index % 2 == 0,
121
+ :remarks => "#{c} #{c} #{c}\n" * 3)
122
+ end
123
+
124
+ end
@@ -0,0 +1,172 @@
1
+ # A module to include into your functional tests for your crud controller subclasses.
2
+ # Simply implement the two methods :test_entry and :test_entry_attrs to test the basic
3
+ # crud functionality. Override the test methods if you changed the behaviour in your subclass
4
+ # controller.
5
+ module CrudControllerTestHelper
6
+
7
+ def test_index
8
+ get :index
9
+ assert_response :success
10
+ assert_template 'index'
11
+ assert_not_nil assigns(:entries)
12
+ end
13
+
14
+ def test_index_xml
15
+ get :index, :format => 'xml'
16
+ assert_response :success
17
+ assert_not_nil assigns(:entries)
18
+ assert @response.body.starts_with?("<?xml")
19
+ end
20
+
21
+ def test_show
22
+ get :show, :id => test_entry.id
23
+ assert_response :success
24
+ assert_template 'show'
25
+ assert_equal test_entry, assigns(:entry)
26
+ end
27
+
28
+ def test_show_xml
29
+ get :show, :id => test_entry.id, :format => 'xml'
30
+ assert_response :success
31
+ assert_equal test_entry, assigns(:entry)
32
+ assert @response.body.starts_with?("<?xml")
33
+ end
34
+
35
+ def test_show_with_not_existing_id_raises_RecordNotFound
36
+ assert_raise(ActiveRecord::RecordNotFound) do
37
+ get :show, :id => 9999
38
+ end
39
+ end
40
+
41
+ def test_show_without_id_redirects_to_index
42
+ get :show
43
+ assert_redirected_to_index
44
+ end
45
+
46
+ def test_new
47
+ get :new
48
+ assert_response :success
49
+ assert_template 'new'
50
+ assert assigns(:entry).new_record?
51
+ end
52
+
53
+ def test_create
54
+ assert_difference("#{model_class.name}.count") do
55
+ post :create, model_identifier => test_entry_attrs
56
+ end
57
+ assert_redirected_to assigns(:entry)
58
+ assert ! assigns(:entry).new_record?
59
+ assert_test_attrs_equal
60
+ end
61
+
62
+ def test_create_with_wrong_http_method_redirects
63
+ get :create, model_identifier => test_entry_attrs
64
+ assert_redirected_to_index
65
+
66
+ put :create, model_identifier => test_entry_attrs
67
+ assert_redirected_to_index
68
+
69
+ delete :create, model_identifier => test_entry_attrs
70
+ assert_redirected_to_index
71
+ end
72
+
73
+ def test_create_xml
74
+ assert_difference("#{model_class.name}.count") do
75
+ post :create, model_identifier => test_entry_attrs, :format => 'xml'
76
+ end
77
+ assert_response :success
78
+ assert @response.body.starts_with?("<?xml")
79
+ end
80
+
81
+ def test_edit
82
+ get :edit, :id => test_entry.id
83
+ assert_response :success
84
+ assert_template 'edit'
85
+ assert_equal test_entry, assigns(:entry)
86
+ end
87
+
88
+ def test_edit_without_id_raises_RecordNotFound
89
+ assert_raise(ActiveRecord::RecordNotFound) do
90
+ get :edit
91
+ end
92
+ end
93
+
94
+ def test_update
95
+ assert_no_difference("#{model_class.name}.count") do
96
+ put :update, :id => test_entry.id, model_identifier => test_entry_attrs
97
+ end
98
+ assert_test_attrs_equal
99
+ assert_redirected_to assigns(:entry)
100
+ end
101
+
102
+ def test_update_with_wrong_http_method_redirects
103
+ get :update, :id => test_entry.id, model_identifier => test_entry_attrs
104
+ assert_redirected_to_index
105
+
106
+ delete :update, :id => test_entry.id, model_identifier => test_entry_attrs
107
+ assert_redirected_to_index
108
+ end
109
+
110
+ def test_update_xml
111
+ assert_no_difference("#{model_class.name}.count") do
112
+ put :update, :id => test_entry.id, model_identifier => test_entry_attrs, :format => 'xml'
113
+ end
114
+ assert_response :success
115
+ assert_equal "", @response.body.strip
116
+ end
117
+
118
+ def test_destroy
119
+ assert_difference("#{model_class.name}.count", -1) do
120
+ delete :destroy, :id => test_entry.id
121
+ end
122
+ assert_redirected_to_index
123
+ end
124
+
125
+ def test_destroy_with_wrong_http_method_redirects
126
+ get :destroy, :id => test_entry.id
127
+ assert_redirected_to_index
128
+
129
+ put :destroy, :id => test_entry.id
130
+ assert_redirected_to_index
131
+ end
132
+
133
+ def test_destroy_xml
134
+ assert_difference("#{model_class.name}.count", -1) do
135
+ delete :destroy, :id => test_entry.id, :format => 'xml'
136
+ end
137
+ assert_response :success
138
+ assert_equal "", @response.body.strip
139
+ end
140
+
141
+ protected
142
+
143
+ def assert_redirected_to_index
144
+ assert_redirected_to :action => 'index'
145
+ end
146
+
147
+ def assert_test_attrs_equal
148
+ test_entry_attrs.each do |key, value|
149
+ actual = assigns(:entry).send(key)
150
+ assert_equal value, actual, "#{key} is expected to be <#{value.inspect}>, got <#{actual.inspect}>"
151
+ end
152
+ end
153
+
154
+ def model_class
155
+ @controller.controller_name.classify.constantize
156
+ end
157
+
158
+ def model_identifier
159
+ @controller.controller_name.singularize.to_sym
160
+ end
161
+
162
+ # Test object used in several tests
163
+ def test_entry
164
+ raise "Implement this method in your test class"
165
+ end
166
+
167
+ # Attribute hash used in several tests
168
+ def test_entry_attrs
169
+ raise "Implement this method in your test class"
170
+ end
171
+
172
+ end
@@ -0,0 +1,96 @@
1
+ require 'test_helper'
2
+ require 'crud_test_model'
3
+ require File.join(File.dirname(__FILE__), 'crud_controller_test_helper')
4
+
5
+ class CrudTestModelsControllerTest < ActionController::TestCase
6
+
7
+ include CrudControllerTestHelper
8
+ include CrudTestHelper
9
+
10
+ attr_accessor :models
11
+
12
+ setup :reset_db, :setup_db, :create_test_data
13
+
14
+ teardown :reset_db
15
+
16
+ def test_setup
17
+ assert_equal 6, CrudTestModel.count
18
+ assert_equal CrudTestModelsController, @controller.class
19
+ assert_recognizes({:controller => 'crud_test_models', :action => 'index'}, '/crud_test_models')
20
+ assert_recognizes({:controller => 'crud_test_models', :action => 'show', :id => '1'}, '/crud_test_models/1')
21
+ assert_equal %w(index show new create edit update destroy).to_set, CrudTestModelsController.send(:action_methods)
22
+ end
23
+
24
+ def test_index
25
+ super
26
+ assert_equal 6, assigns(:entries).size
27
+ assert_equal assigns(:entries).sort_by {|a| a.name }, assigns(:entries)
28
+ end
29
+
30
+ def test_new
31
+ super
32
+ assert assigns(:companions)
33
+ end
34
+
35
+ def test_create
36
+ super
37
+ assert_equal [:before_create, :before_save, :after_save, :after_create], @controller.called_callbacks
38
+ end
39
+
40
+ def test_update
41
+ super
42
+ assert_equal [:before_update, :before_save, :after_save, :after_update], @controller.called_callbacks
43
+ end
44
+
45
+ def test_destroy
46
+ super
47
+ assert_equal [:before_destroy, :after_destroy], @controller.called_callbacks
48
+ end
49
+
50
+ def test_create_with_before_callback
51
+ assert_no_difference("#{model_class.name}.count") do
52
+ post :create, :crud_test_model => {:name => 'illegal', :children => 2}
53
+ end
54
+ assert_template 'new'
55
+ assert assigns(:entry).new_record?
56
+ assert assigns(:companions)
57
+ assert flash[:error].present?
58
+ assert_equal 'illegal', assigns(:entry).name
59
+ assert_nil @controller.called_callbacks
60
+ end
61
+
62
+ def test_create_with_before_callback_redirect
63
+ @controller.should_redirect = true
64
+ assert_no_difference("#{model_class.name}.count") do
65
+ post :create, :crud_test_model => {:name => 'illegal', :children => 2}
66
+ end
67
+ assert_redirected_to :action => 'index'
68
+ assert_nil @controller.called_callbacks
69
+ end
70
+
71
+ def test_new_with_before_render_callback_redirect_does_not_set_companions
72
+ @controller.should_redirect = true
73
+ get :new
74
+ assert_redirected_to :action => 'index'
75
+ assert_nil assigns(:companions)
76
+ end
77
+
78
+
79
+ protected
80
+
81
+ def test_entry
82
+ crud_test_models(:AAAAA)
83
+ end
84
+
85
+ def test_entry_attrs
86
+ {:name => 'foo',
87
+ :children => 42,
88
+ :companion_id => 3,
89
+ :rating => 99.99,
90
+ :income => 2.42,
91
+ :birthdate => '31-12-1999'.to_date,
92
+ :human => true,
93
+ :remarks => "some custom\n\tremarks"}
94
+ end
95
+
96
+ end
@@ -0,0 +1,57 @@
1
+ require 'test_helper'
2
+ require 'crud_test_model'
3
+
4
+ class CrudHelperTest < ActionView::TestCase
5
+
6
+ include StandardHelper
7
+ include CrudTestHelper
8
+
9
+ setup :reset_db, :setup_db, :create_test_data
10
+ teardown :reset_db
11
+
12
+ def model_class
13
+ CrudTestModel
14
+ end
15
+
16
+ test "standard crud table" do
17
+ @entries = CrudTestModel.all
18
+ t = crud_table
19
+ assert_match /(<tr.+?<\/tr>){7}/m, t
20
+ assert_match /(<th.+?<\/th>){14}/m, t
21
+ assert_match /(<a href.+?<\/a>.*?){18}/m, t
22
+ end
23
+
24
+ test "custom crud table" do
25
+ @entries = CrudTestModel.all
26
+ t = crud_table do |t|
27
+ t.attrs :name, :children, :companion_id
28
+ t.col("head") {|e| content_tag :span, e.income.to_s }
29
+ end
30
+ assert_match /(<tr.+?<\/tr>){7}/m, t
31
+ assert_match /(<th.+?<\/th>){4}/m, t
32
+ assert_match /(<span>.+?<\/span>.*?){6}/m, t
33
+ assert_no_match /(<a href.+?<\/a>.*?)/m, t
34
+ end
35
+
36
+ test "crud form" do
37
+ @entry = CrudTestModel.first
38
+ f = capture { crud_form }
39
+
40
+ assert_match /form .*?action="\/crud_test_models\/#{@entry.id}"/, f
41
+ assert_match /input .*?name="crud_test_model\[name\]" .*?type="text"/, f
42
+ assert_match /input .*?name="crud_test_model\[whatever\]" .*?type="text"/, f
43
+ assert_match /input .*?name="crud_test_model\[children\]" .*?type="text"/, f
44
+ assert_match /input .*?name="crud_test_model\[rating\]" .*?type="text"/, f
45
+ assert_match /input .*?name="crud_test_model\[income\]" .*?type="text"/, f
46
+ assert_match /select .*?name="crud_test_model\[birthdate\(1i\)\]"/, f
47
+ assert_match /input .*?name="crud_test_model\[human\]" .*?type="checkbox"/, f
48
+ assert_match /select .*?name="crud_test_model\[companion_id\]"/, f
49
+ assert_match /textarea .*?name="crud_test_model\[remarks\]"/, f
50
+ end
51
+
52
+ test "default attributes do not include id" do
53
+ assert_equal [:name, :whatever, :children, :companion_id, :rating, :income,
54
+ :birthdate, :human, :remarks, :created_at, :updated_at], default_attrs
55
+ end
56
+
57
+ end