repeated_auto_complete 0.1.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 (33) hide show
  1. data/.gitignore +21 -0
  2. data/README +102 -0
  3. data/Rakefile +52 -0
  4. data/VERSION +1 -0
  5. data/init.rb +3 -0
  6. data/lib/auto_complete.rb +49 -0
  7. data/lib/auto_complete_form_builder_helper.rb +38 -0
  8. data/lib/auto_complete_macros_helper.rb +152 -0
  9. data/lib/repeated_auto_complete.rb +4 -0
  10. data/lib/view_mapper/README +4 -0
  11. data/lib/view_mapper/has_many_auto_complete_view.rb +88 -0
  12. data/lib/view_mapper/templates/controller.rb +90 -0
  13. data/lib/view_mapper/templates/layout.html.erb +19 -0
  14. data/lib/view_mapper/templates/style.css +82 -0
  15. data/lib/view_mapper/templates/view_child_form.html.erb +16 -0
  16. data/lib/view_mapper/templates/view_form.html.erb +24 -0
  17. data/rails/init.rb +3 -0
  18. data/repeated_auto_complete.gemspec +78 -0
  19. data/test/auto_complete_form_builder_helper_test.rb +123 -0
  20. data/test/auto_complete_nested_attributes_test.rb +143 -0
  21. data/test/auto_complete_test.rb +136 -0
  22. data/test/helper.rb +14 -0
  23. data/test/view_mapper/expected_templates/_form.html.erb +26 -0
  24. data/test/view_mapper/expected_templates/_person.html.erb +22 -0
  25. data/test/view_mapper/expected_templates/create_parents.rb +16 -0
  26. data/test/view_mapper/expected_templates/edit.html.erb +11 -0
  27. data/test/view_mapper/expected_templates/index.html.erb +20 -0
  28. data/test/view_mapper/expected_templates/new.html.erb +10 -0
  29. data/test/view_mapper/expected_templates/parent.rb +15 -0
  30. data/test/view_mapper/expected_templates/show.html.erb +37 -0
  31. data/test/view_mapper/expected_templates/testies_controller.rb +92 -0
  32. data/test/view_mapper/has_many_auto_complete_view_test.rb +587 -0
  33. 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,11 @@
1
+ <h1>Editing parent</h1>
2
+
3
+ <% form_for(@parent) do |f| %>
4
+ <%= render :partial => 'form', :locals => { :f => f } %>
5
+ <p>
6
+ <%= f.submit 'Update' %>
7
+ </p>
8
+ <% end %>
9
+
10
+ <%= link_to 'Show', @parent %> |
11
+ <%= link_to 'Back', parents_path %>
@@ -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,10 @@
1
+ <h1>New parent</h1>
2
+
3
+ <% form_for(@parent) do |f| %>
4
+ <%= render :partial => 'form', :locals => { :f => f } %>
5
+ <p>
6
+ <%= f.submit 'Create' %>
7
+ </p>
8
+ <% end %>
9
+
10
+ <%= link_to 'Back', parents_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 %>