repeated_auto_complete 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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 %>