rails4-autocomplete 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +31 -0
- data/README.md +374 -0
- data/Rakefile +21 -0
- data/lib/assets/javascripts/autocomplete-rails-uncompressed.js +136 -0
- data/lib/assets/javascripts/autocomplete-rails.js +16 -0
- data/lib/cucumber/autocomplete.rb +6 -0
- data/lib/generators/autocomplete/install_generator.rb +14 -0
- data/lib/generators/autocomplete/uncompressed_generator.rb +14 -0
- data/lib/rails4-autocomplete.rb +23 -0
- data/lib/rails4-autocomplete/autocomplete.rb +96 -0
- data/lib/rails4-autocomplete/form_helper.rb +47 -0
- data/lib/rails4-autocomplete/formtastic.rb +41 -0
- data/lib/rails4-autocomplete/formtastic_plugin.rb +44 -0
- data/lib/rails4-autocomplete/orm.rb +8 -0
- data/lib/rails4-autocomplete/orm/active_record.rb +52 -0
- data/lib/rails4-autocomplete/orm/mongo_mapper.rb +30 -0
- data/lib/rails4-autocomplete/orm/mongoid.rb +34 -0
- data/lib/rails4-autocomplete/rails/engine.rb +5 -0
- data/lib/rails4-autocomplete/simple_form_plugin.rb +84 -0
- data/lib/rails4-autocomplete/version.rb +3 -0
- data/lib/steak/autocomplete.rb +12 -0
- data/test/form_helper_test.rb +25 -0
- data/test/generators/autocomplete/install_generator_test.rb +25 -0
- data/test/generators/autocomplete/uncompressed_generator_test.rb +25 -0
- data/test/lib/rails3-jquery-autocomplete/autocomplete_test.rb +59 -0
- data/test/lib/rails3-jquery-autocomplete/orm/active_record_test.rb +145 -0
- data/test/lib/rails3-jquery-autocomplete/orm/mongo_mapper_test.rb +60 -0
- data/test/lib/rails3-jquery-autocomplete/orm/mongoid_test.rb +60 -0
- data/test/lib/rails3-jquery-autocomplete/simple_form_plugin_test.rb +33 -0
- data/test/lib/rails3-jquery-autocomplete_test.rb +38 -0
- data/test/test_helper.rb +36 -0
- data/test/view_test_helper.rb +108 -0
- metadata +268 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
module SimpleForm
|
2
|
+
module Inputs
|
3
|
+
module Autocomplete
|
4
|
+
#
|
5
|
+
# Method used to rename the autocomplete key to a more standard
|
6
|
+
# data-autocomplete key
|
7
|
+
#
|
8
|
+
def rewrite_autocomplete_option
|
9
|
+
new_options = {}
|
10
|
+
new_options["data-update-elements"] = JSON.generate(options.delete :update_elements) if options[:update_elements]
|
11
|
+
new_options["data-id-element"] = options.delete :id_element if options[:id_element]
|
12
|
+
input_html_options.merge new_options
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class AutocompleteInput < Base
|
17
|
+
include Autocomplete
|
18
|
+
|
19
|
+
def input
|
20
|
+
@builder.autocomplete_field(
|
21
|
+
attribute_name,
|
22
|
+
options[:url],
|
23
|
+
rewrite_autocomplete_option
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
def limit
|
29
|
+
column && column.limit
|
30
|
+
end
|
31
|
+
|
32
|
+
def has_placeholder?
|
33
|
+
placeholder_present?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class AutocompleteCollectionInput < CollectionInput
|
38
|
+
include Autocomplete
|
39
|
+
|
40
|
+
def input
|
41
|
+
# http://www.codeofficer.com/blog/entry/form_builders_in_rails_discovering_field_names_and_ids_for_javascript/
|
42
|
+
hidden_id = "#{object_name}_#{attribute_name}_hidden".gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "")
|
43
|
+
id_element = options[:id_element]
|
44
|
+
if id_element
|
45
|
+
id_element << ", #" << hidden_id
|
46
|
+
else
|
47
|
+
id_element = "#" + hidden_id
|
48
|
+
end
|
49
|
+
options[:id_element] = id_element
|
50
|
+
autocomplete_options = rewrite_autocomplete_option
|
51
|
+
#
|
52
|
+
label_method, value_method = detect_collection_methods
|
53
|
+
association = object.send(reflection.name)
|
54
|
+
if association && association.respond_to?(label_method)
|
55
|
+
autocomplete_options[:value] = association.send(label_method)
|
56
|
+
end
|
57
|
+
out = @builder.autocomplete_field(
|
58
|
+
attribute_name,
|
59
|
+
options[:url],
|
60
|
+
autocomplete_options
|
61
|
+
)
|
62
|
+
hidden_options = if association && association.respond_to?(value_method)
|
63
|
+
new_options = {}
|
64
|
+
new_options[:value] = association.send(value_method)
|
65
|
+
input_html_options.merge new_options
|
66
|
+
else
|
67
|
+
input_html_options
|
68
|
+
end
|
69
|
+
hidden_options[:id] = hidden_id
|
70
|
+
out << @builder.hidden_field(
|
71
|
+
attribute_name,
|
72
|
+
hidden_options
|
73
|
+
)
|
74
|
+
out.html_safe
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class FormBuilder
|
80
|
+
map_type :autocomplete, :to => SimpleForm::Inputs::AutocompleteInput
|
81
|
+
map_type :autocomplete_collection, :to => SimpleForm::Inputs::AutocompleteCollectionInput
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Steak
|
2
|
+
module Autocomplete
|
3
|
+
def choose_autocomplete_result(text, input_id="input[data-autocomplete]")
|
4
|
+
page.execute_script %Q{ $('#{input_id}').trigger("focus") }
|
5
|
+
page.execute_script %Q{ $('#{input_id}').trigger("keydown") }
|
6
|
+
sleep 1
|
7
|
+
page.execute_script %Q{ $('.ui-menu-item a:contains("#{text}")').trigger("mouseenter").trigger("click"); }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
RSpec.configuration.include Steak::Autocomplete, :type => :acceptance
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class Post
|
4
|
+
attr_accessor :author
|
5
|
+
end
|
6
|
+
|
7
|
+
class FormHelperTest < ActionView::TestCase
|
8
|
+
def test_text_field_tag
|
9
|
+
assert_match(/autocomplete=\"some\/path\"/, text_field_tag('field_name', '', :autocomplete => 'some/path'))
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_text_field
|
13
|
+
post = Post.new
|
14
|
+
assert_match(/autocomplete=\"some\/path\"/, text_field(:post, :author, :autocomplete => 'some/path'))
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_autocomplete_field_tag
|
18
|
+
assert_match(/data-autocomplete=\"some\/path\"/, autocomplete_field_tag('field_name', '', 'some/path'))
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_autocomplete_field
|
22
|
+
post= Post.new
|
23
|
+
assert_match(/data-autocomplete=\"some\/path\"/, autocomplete_field(:post, :author, 'some/path'))
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'generators/autocomplete/install_generator'
|
3
|
+
|
4
|
+
module Autocomplete
|
5
|
+
class InstallGeneratorTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@destination = File.join('tmp', 'test_app')
|
8
|
+
@source = InstallGenerator.source_root
|
9
|
+
@filename = File.join(@destination, 'public', 'javascripts', 'autocomplete-rails.js')
|
10
|
+
|
11
|
+
File.unlink(@filename) if File.exists?(@filename)
|
12
|
+
|
13
|
+
InstallGenerator.start([], :destination_root => @destination)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_install
|
17
|
+
assert File.exists?(@filename)
|
18
|
+
|
19
|
+
assert_equal(
|
20
|
+
File.read(File.join(@source, 'autocomplete-rails.js')),
|
21
|
+
File.read(@filename)
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'generators/autocomplete/uncompressed_generator'
|
3
|
+
|
4
|
+
module Autocomplete
|
5
|
+
class UncompressedGeneratorTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@destination = File.join('tmp', 'test_app')
|
8
|
+
@source = UncompressedGenerator.source_root
|
9
|
+
@filename = File.join(@destination, 'public', 'javascripts', 'autocomplete-rails.js')
|
10
|
+
|
11
|
+
File.unlink(@filename) if File.exists?(@filename)
|
12
|
+
|
13
|
+
UncompressedGenerator.start([], :destination_root => @destination)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_install
|
17
|
+
assert File.exists?(@filename)
|
18
|
+
|
19
|
+
assert_equal(
|
20
|
+
File.read(File.join(@source, 'autocomplete-rails-uncompressed.js')),
|
21
|
+
File.read(@filename)
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Rails4Autocomplete
|
4
|
+
class AutocompleteTest < Test::Unit::TestCase
|
5
|
+
include Rails4Autocomplete::Autocomplete
|
6
|
+
|
7
|
+
context '#get_autocomplete_limit' do
|
8
|
+
context 'the limit option was specified' do
|
9
|
+
should "return the limit option" do
|
10
|
+
assert_equal 99, get_autocomplete_limit({:limit => 99})
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'the limit option is not specified' do
|
15
|
+
should 'return 10' do
|
16
|
+
assert_equal 10, get_autocomplete_limit({})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context '#get_object' do
|
22
|
+
should 'return the specified sym as a class name' do
|
23
|
+
symbol = Object.new
|
24
|
+
class_object = Class.new
|
25
|
+
mock(symbol).to_s.mock!.camelize.mock!.constantize { class_object }
|
26
|
+
assert_equal class_object, get_object(symbol)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context '#json_for_autocomplete' do
|
31
|
+
should 'parse items to JSON' do
|
32
|
+
item = mock(Object)
|
33
|
+
mock(item).send(:name).times(2) { 'Object Name' }
|
34
|
+
mock(item).id { 1 }
|
35
|
+
items = [item]
|
36
|
+
response = self.json_for_autocomplete(items, :name).first
|
37
|
+
assert_equal response["id"], "1"
|
38
|
+
assert_equal response["value"], "Object Name"
|
39
|
+
assert_equal response["label"], "Object Name"
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'with extra data' do
|
43
|
+
should 'add that extra data to result' do
|
44
|
+
item = mock(Object)
|
45
|
+
mock(item).send(:name).times(2) { 'Object Name' }
|
46
|
+
mock(item).id { 1 }
|
47
|
+
mock(item).send("extra") { 'Object Extra ' }
|
48
|
+
|
49
|
+
items = [item]
|
50
|
+
response = self.json_for_autocomplete(items, :name, ["extra"]).first
|
51
|
+
|
52
|
+
assert_equal "1" , response["id"]
|
53
|
+
assert_equal "Object Name" , response["value"]
|
54
|
+
assert_equal "Object Name" , response["label"]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Rails4Autocomplete
|
4
|
+
module Orm
|
5
|
+
class ActiveRecordTest < Test::Unit::TestCase
|
6
|
+
include Rails4Autocomplete::Orm::ActiveRecord
|
7
|
+
|
8
|
+
context "#get_autocomplete_order" do
|
9
|
+
context 'order is specified' do
|
10
|
+
should 'returns that order option' do
|
11
|
+
assert_equal "field ASC", get_autocomplete_order(:field, {:order => 'field ASC'})
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'no order is specified' do
|
16
|
+
should 'return the order clause by the field ASC' do
|
17
|
+
assert_equal "field ASC", get_autocomplete_order(:field, {})
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'a different model is specified' do
|
21
|
+
should 'return the order clause by the table_name.field ASC' do
|
22
|
+
model = Object.new
|
23
|
+
mock(model).table_name { 'table_name' }
|
24
|
+
assert_equal "table_name.field ASC", get_autocomplete_order(:field, {}, model)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context '#get_autocomplete_items' do
|
31
|
+
should 'retrieve the items from ActiveRecord' do
|
32
|
+
class Dog ; end
|
33
|
+
|
34
|
+
model = Dog
|
35
|
+
scoped = []
|
36
|
+
whered = []
|
37
|
+
term = 'query'
|
38
|
+
method = :field
|
39
|
+
|
40
|
+
options = {
|
41
|
+
:model => model,
|
42
|
+
:term => term,
|
43
|
+
:method => method,
|
44
|
+
:options => {}
|
45
|
+
}
|
46
|
+
|
47
|
+
mock(self).get_autocomplete_limit(anything) { 10 }
|
48
|
+
mock(self).get_autocomplete_order(anything, anything, anything) { "order ASC" }
|
49
|
+
mock(self).get_autocomplete_select_clause(model, method, {}) { ["field"] }
|
50
|
+
mock(self).get_autocomplete_where_clause(model, term, method, {}) { ["WHERE something"] }
|
51
|
+
mock(model).table_name.times(any_times) { 'model_table_name' }
|
52
|
+
|
53
|
+
mock(model).scoped { model }
|
54
|
+
mock(model).select(["field"]) { model }
|
55
|
+
mock(model).where(["WHERE something"]).mock!.limit(10).mock!.
|
56
|
+
order("order ASC") { 1 }
|
57
|
+
|
58
|
+
assert_equal 1, get_autocomplete_items(options)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context '#get_autocomplete_select_clause' do
|
63
|
+
setup do
|
64
|
+
@model = Object.new
|
65
|
+
mock(@model).table_name { 'table_name' }
|
66
|
+
mock(@model).primary_key { 'id' }
|
67
|
+
end
|
68
|
+
|
69
|
+
should 'create a select clause' do
|
70
|
+
assert_equal ["table_name.id", "table_name.method"],
|
71
|
+
get_autocomplete_select_clause(@model, :method, {})
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'with extra options' do
|
75
|
+
should 'return those extra fields on the clause' do
|
76
|
+
options = {:extra_data => ['table_name.created_at']}
|
77
|
+
|
78
|
+
assert_equal ["table_name.id", "table_name.method", "table_name.created_at"],
|
79
|
+
get_autocomplete_select_clause(@model, :method, options)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context '#get_autocomplete_where_clause' do
|
85
|
+
setup do
|
86
|
+
@model = Object.new
|
87
|
+
mock(@model).table_name { 'table_name' }
|
88
|
+
|
89
|
+
@term = 'query'
|
90
|
+
@options = {}
|
91
|
+
@method = :method
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'Not Postgres' do
|
95
|
+
should 'return options for where' do
|
96
|
+
mock(self).postgres?(@model) { false }
|
97
|
+
assert_equal ["LOWER(table_name.method) LIKE ?", "query%"], get_autocomplete_where_clause(@model, @term, @method, @options)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'Postgres' do
|
102
|
+
should 'return options for where with ILIKE' do
|
103
|
+
mock(self).postgres?(@model) { true }
|
104
|
+
assert_equal ["LOWER(table_name.method) ILIKE ?", "query%"], get_autocomplete_where_clause(@model, @term, @method, @options)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'full search' do
|
109
|
+
should 'return options for where with the term sourrounded by %%' do
|
110
|
+
mock(self).postgres?(@model) { false }
|
111
|
+
@options[:full] = true
|
112
|
+
assert_equal ["LOWER(table_name.method) LIKE ?", "%query%"], get_autocomplete_where_clause(@model, @term, @method, @options)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context '#postgres?' do
|
118
|
+
setup do
|
119
|
+
@model = stub
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'the connection class is not postgres' do
|
123
|
+
setup do
|
124
|
+
mock(@model).connection { stub }
|
125
|
+
end
|
126
|
+
|
127
|
+
should 'return nil if the connection class matches PostgreSQLAdapter' do
|
128
|
+
assert_nil self.postgres?(@model)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'the connection class matches PostgreSQLAdapter' do
|
133
|
+
setup do
|
134
|
+
class PostgreSQLAdapter; end
|
135
|
+
mock(@model).connection { PostgreSQLAdapter.new }
|
136
|
+
end
|
137
|
+
|
138
|
+
should 'return true' do
|
139
|
+
assert self.postgres?(@model)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Rails4Autocomplete
|
4
|
+
module Orm
|
5
|
+
class MongoMapperTest < Test::Unit::TestCase
|
6
|
+
include Rails4Autocomplete::Orm::MongoMapper
|
7
|
+
|
8
|
+
context "#get_autocomplete_order" do
|
9
|
+
context "order is specified" do
|
10
|
+
should 'returns the parametrized order for Mongoid' do
|
11
|
+
assert_equal [[:field, :asc], [:state, :desc]],
|
12
|
+
get_autocomplete_order(:method, :order => 'field ASC, state DESC')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'order is not specified' do
|
17
|
+
should 'return the method ordered ASC by default' do
|
18
|
+
assert_equal [[:method, :asc]],
|
19
|
+
get_autocomplete_order(:method, {})
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "#get_autocomplete_items" do
|
25
|
+
setup do
|
26
|
+
@model = mock(Object)
|
27
|
+
|
28
|
+
@parameters = {
|
29
|
+
:model => @model,
|
30
|
+
:method => :field,
|
31
|
+
:term => 'query',
|
32
|
+
:options => {:full => false}
|
33
|
+
}
|
34
|
+
mock(self).get_autocomplete_limit(anything) { 10 }
|
35
|
+
mock(self).get_autocomplete_order(anything, anything) { [[:order, :asc]] }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'not a full search' do
|
39
|
+
should 'do stuff' do
|
40
|
+
mock(@model).where({:field=>/^query.*/i}).mock!.limit(10).
|
41
|
+
mock!.sort([[:order, :asc]])
|
42
|
+
|
43
|
+
get_autocomplete_items(@parameters)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'full search' do
|
48
|
+
should 'return a full search query' do
|
49
|
+
@parameters[:options] = {:full => true}
|
50
|
+
|
51
|
+
mock(@model).where({:field => /.*query.*/i}).mock!.limit(10).
|
52
|
+
mock!.sort([[:order, :asc]])
|
53
|
+
|
54
|
+
get_autocomplete_items(@parameters)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|