repeated_auto_complete 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +21 -0
- data/README +102 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/init.rb +3 -0
- data/lib/auto_complete.rb +49 -0
- data/lib/auto_complete_form_builder_helper.rb +38 -0
- data/lib/auto_complete_macros_helper.rb +152 -0
- data/lib/repeated_auto_complete.rb +4 -0
- data/lib/view_mapper/README +4 -0
- data/lib/view_mapper/has_many_auto_complete_view.rb +88 -0
- data/lib/view_mapper/templates/controller.rb +90 -0
- data/lib/view_mapper/templates/layout.html.erb +19 -0
- data/lib/view_mapper/templates/style.css +82 -0
- data/lib/view_mapper/templates/view_child_form.html.erb +16 -0
- data/lib/view_mapper/templates/view_form.html.erb +24 -0
- data/rails/init.rb +3 -0
- data/repeated_auto_complete.gemspec +78 -0
- data/test/auto_complete_form_builder_helper_test.rb +123 -0
- data/test/auto_complete_nested_attributes_test.rb +143 -0
- data/test/auto_complete_test.rb +136 -0
- data/test/helper.rb +14 -0
- data/test/view_mapper/expected_templates/_form.html.erb +26 -0
- data/test/view_mapper/expected_templates/_person.html.erb +22 -0
- data/test/view_mapper/expected_templates/create_parents.rb +16 -0
- data/test/view_mapper/expected_templates/edit.html.erb +11 -0
- data/test/view_mapper/expected_templates/index.html.erb +20 -0
- data/test/view_mapper/expected_templates/new.html.erb +10 -0
- data/test/view_mapper/expected_templates/parent.rb +15 -0
- data/test/view_mapper/expected_templates/show.html.erb +37 -0
- data/test/view_mapper/expected_templates/testies_controller.rb +92 -0
- data/test/view_mapper/has_many_auto_complete_view_test.rb +587 -0
- metadata +93 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
# Note: These tests require nested attributes (Rails 2.3 or greater).
|
4
|
+
|
5
|
+
Object.const_set("ParentTestModel", Class.new(ActiveRecord::Base))
|
6
|
+
Object.const_set("ChildTestModel", Class.new(ActiveRecord::Base))
|
7
|
+
|
8
|
+
ActiveRecord::Base.connection.create_table :parent_test_models, :force => true do |table|
|
9
|
+
table.column :name, :string
|
10
|
+
end
|
11
|
+
|
12
|
+
ActiveRecord::Base.connection.create_table :child_test_models, :force => true do |table|
|
13
|
+
table.column :name, :string
|
14
|
+
end
|
15
|
+
|
16
|
+
ParentTestModel.class_eval do
|
17
|
+
has_many :child_test_models
|
18
|
+
accepts_nested_attributes_for :child_test_models, :allow_destroy => true
|
19
|
+
end
|
20
|
+
|
21
|
+
ChildTestModel.class_eval do
|
22
|
+
belongs_to :parent_test_model
|
23
|
+
end
|
24
|
+
|
25
|
+
class AutoCompleteNestedAttributesTest < Test::Unit::TestCase
|
26
|
+
|
27
|
+
include AutoCompleteMacrosHelper
|
28
|
+
include ActionView::Helpers::UrlHelper
|
29
|
+
include ActionView::Helpers::TagHelper
|
30
|
+
include ActionView::Helpers::FormHelper
|
31
|
+
|
32
|
+
def setup
|
33
|
+
|
34
|
+
@parent = ParentTestModel.new :name => 'Name of existing parent model'
|
35
|
+
3.times do |i|
|
36
|
+
@parent.child_test_models.build :name => "Name of child model #{i}"
|
37
|
+
end
|
38
|
+
|
39
|
+
controller_class = Class.new do
|
40
|
+
def url_for(options)
|
41
|
+
url = "http://www.example.com/"
|
42
|
+
url << options[:action].to_s if options and options[:action]
|
43
|
+
url
|
44
|
+
end
|
45
|
+
end
|
46
|
+
@controller = controller_class.new
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_nested_attributes_all_have_different_ids
|
51
|
+
id_attribute_pattern = /id=\"[^\"]*\"/i
|
52
|
+
_erbout = []
|
53
|
+
fields_for @parent do |parent_form|
|
54
|
+
parent_form.fields_for :child_test_models do |child_form|
|
55
|
+
_erbout << child_form.text_field_with_auto_complete(:name, {}, { :method => :get })
|
56
|
+
end
|
57
|
+
end
|
58
|
+
assert_equal [], _erbout[0].scan(id_attribute_pattern) & _erbout[1].scan(id_attribute_pattern)
|
59
|
+
assert_equal [], _erbout[0].scan(id_attribute_pattern) & _erbout[2].scan(id_attribute_pattern)
|
60
|
+
assert_equal [], _erbout[1].scan(id_attribute_pattern) & _erbout[2].scan(id_attribute_pattern)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_ajax_url
|
64
|
+
_erbout = ''
|
65
|
+
fields_for @parent do |parent_form|
|
66
|
+
parent_form.fields_for :child_test_models do |child_form|
|
67
|
+
_erbout.concat child_form.text_field_with_auto_complete(:name, {}, { :method => :get })
|
68
|
+
end
|
69
|
+
end
|
70
|
+
assert _erbout.index('http://www.example.com/auto_complete_for_child_test_model_name')
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_ajax_param
|
74
|
+
_erbout = ''
|
75
|
+
fields_for @parent do |parent_form|
|
76
|
+
parent_form.fields_for :child_test_models do |child_form|
|
77
|
+
_erbout.concat child_form.text_field_with_auto_complete(:name, {}, { :method => :get })
|
78
|
+
end
|
79
|
+
end
|
80
|
+
assert _erbout.index("paramName:'child_test_model[name]'")
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_object_value
|
84
|
+
_erbout = ''
|
85
|
+
fields_for @parent do |parent_form|
|
86
|
+
parent_form.fields_for :child_test_models do |child_form|
|
87
|
+
_erbout.concat child_form.text_field_with_auto_complete(:name, {}, { :method => :get })
|
88
|
+
end
|
89
|
+
end
|
90
|
+
3.times do |i|
|
91
|
+
assert _erbout.index("value=\"Name of child model #{i}\"")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_sanitized_object_name
|
96
|
+
fields_for @parent do |parent_form|
|
97
|
+
assert_equal 'parent_test_model',
|
98
|
+
parent_form.sanitized_object_name
|
99
|
+
parent_form.fields_for :child_test_models, { :child_index => 1234 } do |child_form|
|
100
|
+
assert_equal 'parent_test_model_child_test_models_attributes_1234',
|
101
|
+
child_form.sanitized_object_name
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_is_used_as_nested_attribute
|
108
|
+
fields_for @parent do |parent_form|
|
109
|
+
assert !parent_form.is_used_as_nested_attribute?
|
110
|
+
parent_form.fields_for :child_test_models do |child_form|
|
111
|
+
assert child_form.is_used_as_nested_attribute?
|
112
|
+
end
|
113
|
+
end
|
114
|
+
fields_for 'parent[child_test_models_attributes][]', @parent do |rails_2_2_form|
|
115
|
+
assert !rails_2_2_form.is_used_as_nested_attribute?
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_child_index_fields_for_option
|
120
|
+
_erbout = ''
|
121
|
+
fields_for @parent, { :child_index => 5678 } do |parent_form|
|
122
|
+
_erbout.concat parent_form.text_field_with_auto_complete(:name, {}, { :method => :get })
|
123
|
+
assert _erbout.index('parent_test_model_5678_name')
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_child_index_completion_option
|
128
|
+
_erbout = ''
|
129
|
+
fields_for @parent do |parent_form|
|
130
|
+
_erbout.concat parent_form.text_field_with_auto_complete(:name, {}, { :method => :get, :child_index => 1234 })
|
131
|
+
assert _erbout.index('parent_test_model_1234_name')
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_child_index_completion_option_overrides_fields_for_option
|
136
|
+
_erbout = ''
|
137
|
+
fields_for @parent, { :child_index => 5678 } do |parent_form|
|
138
|
+
_erbout.concat parent_form.text_field_with_auto_complete(:name, {}, { :method => :get, :child_index => 1234 })
|
139
|
+
assert _erbout.index('parent_test_model_1234_name')
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
ActionController::Routing::Routes.draw do |map|
|
4
|
+
map.connect ':controller/:action/:id'
|
5
|
+
end
|
6
|
+
|
7
|
+
class AutoCompleteTest < ActionController::TestCase
|
8
|
+
include AutoComplete
|
9
|
+
include AutoCompleteMacrosHelper
|
10
|
+
|
11
|
+
include ActionView::Helpers::UrlHelper
|
12
|
+
include ActionView::Helpers::TagHelper
|
13
|
+
include ActionView::Helpers::TextHelper
|
14
|
+
include ActionView::Helpers::FormHelper
|
15
|
+
include ActionView::Helpers::CaptureHelper
|
16
|
+
include ActionController::Integration
|
17
|
+
|
18
|
+
def setup
|
19
|
+
@controller = Class.new(ActionController::Base) do
|
20
|
+
|
21
|
+
auto_complete_for :some_model, :some_field
|
22
|
+
|
23
|
+
auto_complete_for :some_model, :some_other_field do |items, params|
|
24
|
+
items.scoped( { :conditions => [ "a_third_field = ?", params['some_model']['a_third_field'] ] })
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :items
|
28
|
+
|
29
|
+
def url_for(options)
|
30
|
+
url = "http://www.example.com/"
|
31
|
+
url << options[:action].to_s if options and options[:action]
|
32
|
+
url
|
33
|
+
end
|
34
|
+
end
|
35
|
+
@controller = @controller.new
|
36
|
+
|
37
|
+
Object.const_set("SomeModel", Class.new(ActiveRecord::Base)) unless Object.const_defined?("SomeModel")
|
38
|
+
|
39
|
+
@request = ActionController::TestRequest.new
|
40
|
+
@response = ActionController::TestResponse.new
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def test_auto_complete_field
|
46
|
+
assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {})\n//]]>\n</script>),
|
47
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" });
|
48
|
+
assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {tokens:','})\n//]]>\n</script>),
|
49
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :tokens => ',');
|
50
|
+
assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {tokens:[',']})\n//]]>\n</script>),
|
51
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :tokens => [',']);
|
52
|
+
assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {minChars:3})\n//]]>\n</script>),
|
53
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :min_chars => 3);
|
54
|
+
assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {onHide:function(element, update){alert('me');}})\n//]]>\n</script>),
|
55
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :on_hide => "function(element, update){alert('me');}");
|
56
|
+
assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {frequency:2})\n//]]>\n</script>),
|
57
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :frequency => 2);
|
58
|
+
assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {afterUpdateElement:function(element,value){alert('You have chosen: '+value)}})\n//]]>\n</script>),
|
59
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" },
|
60
|
+
:after_update_element => "function(element,value){alert('You have chosen: '+value)}");
|
61
|
+
assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {paramName:'huidriwusch'})\n//]]>\n</script>),
|
62
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :param_name => 'huidriwusch');
|
63
|
+
assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {method:'get'})\n//]]>\n</script>),
|
64
|
+
auto_complete_field("some_input", :url => { :action => "autocomplete" }, :method => :get);
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_auto_complete_result
|
68
|
+
result = [ { :title => 'test1' }, { :title => 'test2' } ]
|
69
|
+
assert_equal %(<ul><li>test1</li><li>test2</li></ul>),
|
70
|
+
auto_complete_result(result, :title)
|
71
|
+
assert_equal %(<ul><li>t<strong class=\"highlight\">est</strong>1</li><li>t<strong class=\"highlight\">est</strong>2</li></ul>),
|
72
|
+
auto_complete_result(result, :title, "est")
|
73
|
+
|
74
|
+
resultuniq = [ { :title => 'test1' }, { :title => 'test1' } ]
|
75
|
+
assert_equal %(<ul><li>t<strong class=\"highlight\">est</strong>1</li></ul>),
|
76
|
+
auto_complete_result(resultuniq, :title, "est")
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_text_field_with_auto_complete
|
80
|
+
assert_match %(<style type="text/css">),
|
81
|
+
text_field_with_auto_complete(:message, :recipient)
|
82
|
+
|
83
|
+
assert_equal %(<input id=\"message_recipient\" name=\"message[recipient]\" size=\"30\" type=\"text\" /><div class=\"auto_complete\" id=\"message_recipient_auto_complete\"></div><script type=\"text/javascript\">\n//<![CDATA[\nvar message_recipient_auto_completer = new Ajax.Autocompleter('message_recipient', 'message_recipient_auto_complete', 'http://www.example.com/auto_complete_for_message_recipient', {})\n//]]>\n</script>),
|
84
|
+
text_field_with_auto_complete(:message, :recipient, {}, :skip_style => true)
|
85
|
+
end
|
86
|
+
|
87
|
+
# auto_complete_for :some_model, :some_field
|
88
|
+
def test_default_auto_complete_for
|
89
|
+
get :auto_complete_for_some_model_some_field, :some_model => { :some_field => "some_value" }
|
90
|
+
default_auto_complete_find_options = @controller.items.proxy_options
|
91
|
+
assert_equal "\"some_models\".some_field ASC", default_auto_complete_find_options[:order]
|
92
|
+
assert_equal 10, default_auto_complete_find_options[:limit]
|
93
|
+
assert_equal ["LOWER(\"some_models\".some_field) LIKE ?", "%some_value%"], default_auto_complete_find_options[:conditions]
|
94
|
+
end
|
95
|
+
|
96
|
+
# auto_complete_for :some_model, :some_other_field do |items, params|
|
97
|
+
# items.scoped( { :conditions => [ "a_third_field = ?", params['some_model']['a_third_field'] ] })
|
98
|
+
# end
|
99
|
+
def test_auto_complete_for_with_block
|
100
|
+
get :auto_complete_for_some_model_some_other_field, :some_model => { :some_other_field => "some_value", :a_third_field => "some_value" }
|
101
|
+
custom_auto_complete_find_options = @controller.items.proxy_options
|
102
|
+
assert_equal [ "a_third_field = ?", 'some_value' ], custom_auto_complete_find_options[:conditions]
|
103
|
+
|
104
|
+
default_auto_complete_scope = @controller.items.proxy_scope
|
105
|
+
assert !default_auto_complete_scope.nil?
|
106
|
+
default_auto_complete_find_options = default_auto_complete_scope.proxy_options
|
107
|
+
assert_equal "\"some_models\".some_other_field ASC", default_auto_complete_find_options[:order]
|
108
|
+
assert_equal 10, default_auto_complete_find_options[:limit]
|
109
|
+
assert_equal ["LOWER(\"some_models\".some_other_field) LIKE ?", "%some_value%"], default_auto_complete_find_options[:conditions]
|
110
|
+
end
|
111
|
+
|
112
|
+
# Quoted table name seems to have changed in Rails 2.3...
|
113
|
+
# For Rails 2.2 or earlier:
|
114
|
+
|
115
|
+
# def test_default_auto_complete_for
|
116
|
+
# get :auto_complete_for_some_model_some_field, :some_model => { :some_field => "some_value" }
|
117
|
+
# default_auto_complete_find_options = @controller.items.proxy_options
|
118
|
+
# assert_equal "`some_models`.some_field ASC", default_auto_complete_find_options[:order]
|
119
|
+
# assert_equal 10, default_auto_complete_find_options[:limit]
|
120
|
+
# assert_equal ["LOWER(`some_models`.some_field) LIKE ?", "%some_value%"], default_auto_complete_find_options[:conditions]
|
121
|
+
# end
|
122
|
+
|
123
|
+
# def test_auto_complete_for_with_block
|
124
|
+
# get :auto_complete_for_some_model_some_other_field, :some_model => { :some_other_field => "some_value", :a_third_field => "some_value" }
|
125
|
+
# custom_auto_complete_find_options = @controller.items.proxy_options
|
126
|
+
# assert_equal [ "a_third_field = ?", 'some_value' ], custom_auto_complete_find_options[:conditions]
|
127
|
+
#
|
128
|
+
# default_auto_complete_scope = @controller.items.proxy_scope
|
129
|
+
# assert !default_auto_complete_scope.nil?
|
130
|
+
# default_auto_complete_find_options = default_auto_complete_scope.proxy_options
|
131
|
+
# assert_equal "`some_models`.some_other_field ASC", default_auto_complete_find_options[:order]
|
132
|
+
# assert_equal 10, default_auto_complete_find_options[:limit]
|
133
|
+
# assert_equal ["LOWER(`some_models`.some_other_field) LIKE ?", "%some_value%"], default_auto_complete_find_options[:conditions]
|
134
|
+
# end
|
135
|
+
|
136
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'action_controller'
|
4
|
+
require 'active_record'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
require 'repeated_auto_complete'
|
9
|
+
require File.join(File.dirname(__FILE__), '..', 'init')
|
10
|
+
|
11
|
+
class Test::Unit::TestCase
|
12
|
+
end
|
13
|
+
|
14
|
+
ActiveRecord::Base.establish_connection({ :adapter => 'sqlite3', :database => ':memory:' })
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<%= f.error_messages %>
|
2
|
+
|
3
|
+
<p>
|
4
|
+
<%= f.label :name %><br />
|
5
|
+
<%= f.text_field_with_auto_complete :name, {}, { :method => :get, :skip_style => true } %>
|
6
|
+
</p>
|
7
|
+
|
8
|
+
<div id='some_other_model_children'>
|
9
|
+
<% f.fields_for :some_other_models do |some_other_model_form| %>
|
10
|
+
<%= render :partial => 'some_other_model', :locals => { :f => some_other_model_form } %>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<p>
|
15
|
+
<%= add_child_link 'Add a SomeOtherModel', 'some_other_model', f %>
|
16
|
+
</p>
|
17
|
+
|
18
|
+
<div id='testy_children'>
|
19
|
+
<% f.fields_for :testies do |testy_form| %>
|
20
|
+
<%= render :partial => 'testy', :locals => { :f => testy_form } %>
|
21
|
+
<% end %>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<p>
|
25
|
+
<%= add_child_link 'Add a Testy', 'testy', f %>
|
26
|
+
</p>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<div class="child">
|
2
|
+
<p>
|
3
|
+
Testy <%= f.label :first_name %><br />
|
4
|
+
<%= f.text_field_with_auto_complete :first_name, {}, { :method => :get, :skip_style => true } %>
|
5
|
+
</p>
|
6
|
+
<p>
|
7
|
+
Testy <%= f.label :last_name %><br />
|
8
|
+
<%= f.text_field_with_auto_complete :last_name, {}, { :method => :get, :skip_style => true } %>
|
9
|
+
</p>
|
10
|
+
<p>
|
11
|
+
Testy <%= f.label :address %><br />
|
12
|
+
<%= f.text_field_with_auto_complete :address, {}, { :method => :get, :skip_style => true } %>
|
13
|
+
</p>
|
14
|
+
<p>
|
15
|
+
Testy <%= f.label :some_flag %><br />
|
16
|
+
<%= f.check_box :some_flag %>
|
17
|
+
</p>
|
18
|
+
<p>
|
19
|
+
<%= f.hidden_field :_delete, :class => 'delete' %>
|
20
|
+
<%= remove_child_link 'remove', f %>
|
21
|
+
</p>
|
22
|
+
</div>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateParents < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :parents do |t|
|
4
|
+
t.string :first_name
|
5
|
+
t.string :last_name
|
6
|
+
t.string :address
|
7
|
+
t.boolean :some_flag
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :parents
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<h1>Listing parents</h1>
|
2
|
+
|
3
|
+
<table>
|
4
|
+
<tr>
|
5
|
+
<th>Name</th>
|
6
|
+
</tr>
|
7
|
+
|
8
|
+
<% @parents.each do |parent| %>
|
9
|
+
<tr>
|
10
|
+
<td><%=h parent.name %></td>
|
11
|
+
<td><%= link_to 'Show', parent %></td>
|
12
|
+
<td><%= link_to 'Edit', edit_parent_path(parent) %></td>
|
13
|
+
<td><%= link_to 'Destroy', parent, :confirm => 'Are you sure?', :method => :delete %></td>
|
14
|
+
</tr>
|
15
|
+
<% end %>
|
16
|
+
</table>
|
17
|
+
|
18
|
+
<br />
|
19
|
+
|
20
|
+
<%= link_to 'New parent', new_parent_path %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Parent < ActiveRecord::Base
|
2
|
+
has_many :some_other_models
|
3
|
+
has_many :testies
|
4
|
+
accepts_nested_attributes_for :some_other_models,
|
5
|
+
:allow_destroy => true,
|
6
|
+
:reject_if => proc { |attrs| attrs['name'].blank? }
|
7
|
+
accepts_nested_attributes_for :testies,
|
8
|
+
:allow_destroy => true,
|
9
|
+
:reject_if => proc { |attrs|
|
10
|
+
attrs['first_name'].blank? &&
|
11
|
+
attrs['last_name'].blank? &&
|
12
|
+
attrs['address'].blank? &&
|
13
|
+
attrs['some_flag'].blank?
|
14
|
+
}
|
15
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<p>
|
2
|
+
<b>Name:</b>
|
3
|
+
<%=h @parent.name %>
|
4
|
+
</p>
|
5
|
+
|
6
|
+
<% @parent.some_other_models.each do |some_other_model| %>
|
7
|
+
<div class="child">
|
8
|
+
<p>
|
9
|
+
<b>SomeOtherModel Name:</b>
|
10
|
+
<%=h some_other_model.name %>
|
11
|
+
</p>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<% @parent.testies.each do |testy| %>
|
16
|
+
<div class="child">
|
17
|
+
<p>
|
18
|
+
<b>Testy First name:</b>
|
19
|
+
<%=h testy.first_name %>
|
20
|
+
</p>
|
21
|
+
<p>
|
22
|
+
<b>Testy Last name:</b>
|
23
|
+
<%=h testy.last_name %>
|
24
|
+
</p>
|
25
|
+
<p>
|
26
|
+
<b>Testy Address:</b>
|
27
|
+
<%=h testy.address %>
|
28
|
+
</p>
|
29
|
+
<p>
|
30
|
+
<b>Testy Some flag:</b>
|
31
|
+
<%=h testy.some_flag %>
|
32
|
+
</p>
|
33
|
+
</div>
|
34
|
+
<% end %>
|
35
|
+
|
36
|
+
<%= link_to 'Edit', edit_parent_path(@parent) %> |
|
37
|
+
<%= link_to 'Back', parents_path %>
|