autocomplete_for 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.log
2
+ *.swp
3
+ .rvmrc
4
+ tags
5
+ pkg
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Nulogy Corporation
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,40 @@
1
+ AutocompleteFor
2
+ ===============
3
+
4
+ This plugin implements model-side logic for autocompleting belongs_to associations. It handles validations, autocompleting the same association via different fields (say name or login) and the ability to specify a custom finder block.
5
+
6
+ It works out-of-the-box with existing front-end autocompletion solutions because all it does is set the value of the belongs_to association based on an attribute that can be set directly or via update_attributes (see examples below.)
7
+
8
+ ### Example
9
+
10
+ class Author < ActiveRecord::Base
11
+ # has a login and open_id column
12
+ end
13
+
14
+ class Post < ActiveRecord::Base
15
+ belongs_to :author
16
+
17
+ # set the author_login field to autocomplete by author login
18
+ autocomplete_for :author, :login do
19
+ self.author = Author.find(:first, :conditions => {:login => @author_login})
20
+ end
21
+
22
+ # set the author_open_id field to autocomplete by author open_id
23
+ autocomplete_for :author, :open_id do
24
+ self.author = Author.find(:first, :conditions => {:open_id => @author_open_id})
25
+ end
26
+ end
27
+
28
+ Using autocomplete_for in your models to set belongs_to associations:
29
+
30
+ author = Author.create! :login => 'baz'
31
+ post = Post.create! :author_login => 'baz' # automatically finds the author with the login 'baz'
32
+ puts post.author.login # will output 'baz'
33
+
34
+ Errors are generated automatically if the given information does not correspond to a valid model:
35
+
36
+ author = Author.create! :login => 'baz'
37
+ post = Post.create :author_login => 'quux'
38
+ puts post.errors[:author_login] # will print an error message
39
+
40
+ Copyright (c) 2010 Nulogy Corporation, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,41 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |s|
8
+ s.name = "autocomplete_for"
9
+ s.summary = "Model-side logic for autocompleting belongs_to associations"
10
+ s.description = "Model-side logic for autocompleting belongs_to associations"
11
+ s.email = "sskirby@gmail.com"
12
+ s.homepage = "http://github.com/sskirby/autocomplete_for"
13
+ s.rubyforge_project = 'autocomplete_for'
14
+ s.authors = ["Sean Kirby"]
15
+ s.add_dependency('activerecord', '~> 2.3.4')
16
+ s.add_development_dependency('pg')
17
+ end
18
+
19
+ rescue LoadError
20
+ puts "Jeweler not available. Install it with: gem install jeweler"
21
+ end
22
+
23
+ desc 'Default: run unit tests.'
24
+ task :default => :test
25
+
26
+ desc 'Test the autocomplete_for plugin.'
27
+ Rake::TestTask.new(:test) do |t|
28
+ t.libs << 'lib'
29
+ t.libs << 'test'
30
+ t.pattern = 'test/**/*_test.rb'
31
+ t.verbose = true
32
+ end
33
+
34
+ desc 'Generate documentation for the autocomplete_for plugin.'
35
+ Rake::RDocTask.new(:rdoc) do |rdoc|
36
+ rdoc.rdoc_dir = 'rdoc'
37
+ rdoc.title = 'AutocompleteFor'
38
+ rdoc.options << '--line-numbers' << '--inline-source'
39
+ rdoc.rdoc_files.include('README.markdown')
40
+ rdoc.rdoc_files.include('lib/**/*.rb')
41
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,61 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{autocomplete_for}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Sean Kirby"]
12
+ s.date = %q{2010-09-24}
13
+ s.description = %q{Model-side logic for autocompleting belongs_to associations}
14
+ s.email = %q{sskirby@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.markdown"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "MIT-LICENSE",
21
+ "README.markdown",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "autocomplete_for.gemspec",
25
+ "lib/autocomplete_for.rb",
26
+ "lib/autocomplete_for/autocomplete_for.rb",
27
+ "rails/init.rb",
28
+ "test/autocomplete_for_test.rb",
29
+ "test/database.yml",
30
+ "test/schema.rb",
31
+ "test/test_helper.rb"
32
+ ]
33
+ s.homepage = %q{http://github.com/sskirby/autocomplete_for}
34
+ s.rdoc_options = ["--charset=UTF-8"]
35
+ s.require_paths = ["lib"]
36
+ s.rubyforge_project = %q{autocomplete_for}
37
+ s.rubygems_version = %q{1.3.7}
38
+ s.summary = %q{Model-side logic for autocompleting belongs_to associations}
39
+ s.test_files = [
40
+ "test/schema.rb",
41
+ "test/autocomplete_for_test.rb",
42
+ "test/test_helper.rb"
43
+ ]
44
+
45
+ if s.respond_to? :specification_version then
46
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
47
+ s.specification_version = 3
48
+
49
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
+ s.add_runtime_dependency(%q<activerecord>, ["~> 2.3.4"])
51
+ s.add_development_dependency(%q<pg>, [">= 0"])
52
+ else
53
+ s.add_dependency(%q<activerecord>, ["~> 2.3.4"])
54
+ s.add_dependency(%q<pg>, [">= 0"])
55
+ end
56
+ else
57
+ s.add_dependency(%q<activerecord>, ["~> 2.3.4"])
58
+ s.add_dependency(%q<pg>, [">= 0"])
59
+ end
60
+ end
61
+
@@ -0,0 +1,101 @@
1
+ module AutocompleteFor
2
+ def self.included(base)
3
+ base.send :extend, ClassMethods
4
+ end
5
+
6
+ module ClassMethods
7
+ def autocomplete_for association, field, options = {}, &block
8
+ allow_nil = options[:allow_nil] || false
9
+ validate :"validate_#{association}_by_#{field}"
10
+ before_validation :"associate_#{association}_by_#{field}"
11
+ instance_variable_set(:"@#{association}_#{field}_allow_nil", allow_nil)
12
+
13
+ # method to set the name of the entity to autocomplete
14
+ # def customer_name=(name)
15
+ # @customer_name = name
16
+ # end
17
+ define_method(:"#{association}_#{field}=") do |name|
18
+ instance_variable_set(:"@#{association}_#{field}", name)
19
+ end
20
+
21
+ # method to retrieve the name of the entity to autocomplete
22
+ # def customer_name
23
+ # self.customer_to.name : @customer_name
24
+ # end
25
+ define_method(:"#{association}_#{field}") do
26
+ send(association.to_sym) ? send(association.to_sym).send(field.to_sym) : instance_variable_get(:"@#{association}_#{field}")
27
+ end
28
+
29
+ # Validation method to make sure the autocompleted name resolves to an actual entity
30
+ # def validate_customer_by_name
31
+ # return unless @customer_name
32
+ # return if self.customer
33
+ # return if @@customer_name_allow_nil && @customer_name == ""
34
+ #
35
+ # self.errors.add :customer_name, "#{@customer_name} does not exist"
36
+ # end
37
+ define_method(:"validate_#{association}_by_#{field}") do
38
+ return unless instance_variable_get(:"@#{association}_#{field}")
39
+ return if send(association.to_sym)
40
+ return if self.class.instance_variable_get(:"@#{association}_#{field}_allow_nil") && instance_variable_get(:"@#{association}_#{field}") == ""
41
+ self.errors.add(:"#{association}_#{field}", "\"#{instance_variable_get(:"@#{association}_#{field}")}\" does not exist")
42
+ end
43
+
44
+ # Resolve the autocompleted name to an actual entity
45
+ # def autocomplete_find_customer_by_name
46
+ # if self.site
47
+ # self.customer = self.site.floor_locations.find(:first, :include => :location, :conditions => {:'locations.name' => @customer_name})
48
+ # end
49
+ # end
50
+ define_method(:"autocomplete_find_#{association}_by_#{field}", block)
51
+
52
+ # def associate_customer_by_name
53
+ # return unless @customer_name
54
+ #
55
+ # if @customer_name == ''
56
+ # self.customer = nil
57
+ # return
58
+ # end
59
+ #
60
+ # autocomplete_find_customer_by_name
61
+ # end
62
+ define_method(:"associate_#{association}_by_#{field}") do
63
+ return unless instance_variable_get(:"@#{association}_#{field}")
64
+ if instance_variable_get(:"@#{association}_#{field}") == ''
65
+ self.send(:"#{association}=", nil)
66
+ return
67
+ end
68
+
69
+ self.send(:"autocomplete_find_#{association}_by_#{field}")
70
+ end
71
+
72
+ # set up validation on association in case the customer_name isn't set
73
+ error_fields_name = :"@#{association}_autocomplete_error_fields"
74
+ error_fields = instance_variable_get(error_fields_name) || []
75
+ error_fields << :"#{association}_#{field}"
76
+
77
+ instance_variable_set(error_fields_name, error_fields)
78
+
79
+ unless allow_nil
80
+ # we must make sure that the validate_by_customer validation runs
81
+ # after ALL validations on autocomplete fields
82
+ # see rails/activesupport/lib/active_support/callbacks.rb line #208
83
+ # probably won't work in Rails 3
84
+ @validate_callbacks.delete(:"validate_by_#{association}")
85
+ validate :"validate_by_#{association}"
86
+
87
+ unless instance_methods.include?("validate_by_#{association}")
88
+
89
+ # def validate_by_customer
90
+ # self.errors.add_on_blank(:customer) unless @@customer_autocompolete_error_fields.any? {|ef| self.errors[ef]}
91
+ # end
92
+ define_method(:"validate_by_#{association}") do
93
+ self.errors.add_on_blank(:"#{association}") unless self.class.instance_variable_get(error_fields_name).any? {|ef| self.errors[ef]}
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ ActiveRecord::Base.send :include, AutocompleteFor
@@ -0,0 +1 @@
1
+ require 'autocomplete_for/autocomplete_for.rb'
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'autocomplete_for'
@@ -0,0 +1,149 @@
1
+ require 'test_helper'
2
+
3
+ class AutocompleteForTest < ActiveSupport::TestCase
4
+ load_schema
5
+
6
+ class Vendor < ActiveRecord::Base; end
7
+ class Customer < ActiveRecord::Base; end
8
+
9
+ class AutoCompleteForCustomerTestModel < ActiveRecord::Base
10
+ belongs_to :customer
11
+
12
+ autocomplete_for :customer, :name, :allow_nil => true do
13
+ self.customer = Customer.find(:first, :conditions => {:name => @customer_name})
14
+ end
15
+ autocomplete_for :customer, :code, :allow_nil => true do
16
+ self.customer = Customer.find(:first, :conditions => {:code => @customer_code})
17
+ end
18
+ end
19
+
20
+ class AutoCompleteForVendorTestModel < ActiveRecord::Base
21
+ belongs_to :vendor
22
+
23
+ autocomplete_for :vendor, :name do
24
+ self.vendor = Vendor.find(:first, :conditions => {:name => @vendor_name})
25
+ end
26
+ autocomplete_for :vendor, :code do
27
+ self.vendor = Vendor.find(:first, :conditions => {:code => @vendor_code})
28
+ end
29
+ end
30
+
31
+ def setup
32
+ Vendor.destroy_all
33
+ Customer.destroy_all
34
+ @vendor_nil_code = Vendor.create! :name => "Nil Code"
35
+ @vendor = Vendor.create! :name => "Vendor Name", :code => "Vendor Code"
36
+ @autocomplete_for_vendor = AutoCompleteForVendorTestModel.new
37
+
38
+ @customer = Customer.create! :name => "Customer Name", :code => "Customer Code"
39
+ @autocomplete_for_customer = AutoCompleteForCustomerTestModel.new
40
+ end
41
+
42
+ test "with valid name" do
43
+ @autocomplete_for_vendor.update_attributes! :vendor_name => @vendor.name
44
+
45
+ assert_equal @vendor, @autocomplete_for_vendor.vendor
46
+ end
47
+
48
+ test "with invalid name" do
49
+ @autocomplete_for_vendor.update_attributes :vendor_name => "Not a Vendor Name"
50
+
51
+ assert_nil @autocomplete_for_vendor.vendor
52
+ assert @autocomplete_for_vendor.errors.on(:vendor_name)
53
+ assert_nil @autocomplete_for_vendor.errors.on(:vendor_code)
54
+ assert_nil @autocomplete_for_vendor.errors.on(:vendor)
55
+ end
56
+
57
+ test "with blank name" do
58
+ @autocomplete_for_vendor.update_attributes :vendor_name => ""
59
+
60
+ assert_nil @autocomplete_for_vendor.vendor
61
+ assert @autocomplete_for_vendor.errors.on(:vendor_name)
62
+ assert_nil @autocomplete_for_vendor.errors.on(:vendor_code)
63
+ assert_nil @autocomplete_for_vendor.errors.on(:vendor)
64
+ end
65
+
66
+ test "with nil name" do
67
+ @autocomplete_for_vendor.update_attributes :vendor_name => nil
68
+
69
+ assert_nil @autocomplete_for_vendor.vendor
70
+ assert @autocomplete_for_vendor.errors.on(:vendor)
71
+ assert_nil @autocomplete_for_vendor.errors.on(:vendor_code)
72
+ assert_nil @autocomplete_for_vendor.errors.on(:vendor_name)
73
+ end
74
+
75
+ test "should clear existing association" do
76
+ @autocomplete_for_vendor.update_attributes! :vendor => @vendor
77
+ assert_equal @vendor, @autocomplete_for_vendor.vendor
78
+
79
+ @autocomplete_for_vendor.update_attributes :vendor_name => ""
80
+ assert_nil @autocomplete_for_vendor.vendor
81
+ assert @autocomplete_for_vendor.errors.on(:vendor_name)
82
+
83
+ assert_nil @autocomplete_for_vendor.errors.on(:vendor_code)
84
+ assert_nil @autocomplete_for_vendor.errors.on(:vendor)
85
+ end
86
+
87
+ test "should not clear existing association" do
88
+ @autocomplete_for_vendor.update_attributes! :vendor => @vendor
89
+ assert_equal @vendor, @autocomplete_for_vendor.vendor
90
+
91
+ @autocomplete_for_vendor.update_attributes! :vendor_name => nil
92
+ assert_equal @vendor, @autocomplete_for_vendor.vendor
93
+ end
94
+
95
+ test "should clear existing association using field that can be nil" do
96
+ @autocomplete_for_vendor.update_attributes! :vendor => @vendor
97
+ assert_equal @vendor, @autocomplete_for_vendor.vendor
98
+
99
+ @autocomplete_for_vendor.update_attributes :vendor_code => ""
100
+ assert_nil @autocomplete_for_vendor.vendor
101
+ assert @autocomplete_for_vendor.errors.on(:vendor_code)
102
+
103
+ assert_nil @autocomplete_for_vendor.errors.on(:vendor_name)
104
+ assert_nil @autocomplete_for_vendor.errors.on(:vendor)
105
+ end
106
+
107
+ test "allow_nil with valid name" do
108
+ @autocomplete_for_customer.update_attributes! :customer_name => @customer.name
109
+
110
+ assert_equal @customer, @autocomplete_for_customer.customer
111
+ end
112
+
113
+ test "allow_nil with invalid name" do
114
+ @autocomplete_for_customer.update_attributes :customer_name => "Not A Customer Name"
115
+
116
+ assert_nil @autocomplete_for_customer.customer
117
+ assert @autocomplete_for_customer.errors.on(:customer_name)
118
+ assert_nil @autocomplete_for_customer.errors.on(:customer_code)
119
+ assert_nil @autocomplete_for_customer.errors.on(:customer)
120
+ end
121
+
122
+ test "allow_nil with blank name" do
123
+ @autocomplete_for_customer.update_attributes! :customer_name => ""
124
+
125
+ assert_nil @autocomplete_for_customer.customer
126
+ end
127
+
128
+ test "allow_nil with nil name" do
129
+ @autocomplete_for_customer.update_attributes! :customer_name => nil
130
+
131
+ assert_nil @autocomplete_for_customer.customer
132
+ end
133
+
134
+ test "allow_nil should clear existing association" do
135
+ @autocomplete_for_customer.update_attributes! :customer => @customer
136
+ assert_equal @customer, @autocomplete_for_customer.customer
137
+
138
+ @autocomplete_for_customer.update_attributes! :customer_name => ""
139
+ assert_nil @autocomplete_for_customer.customer
140
+ end
141
+
142
+ test "allow_nil should not clear existing association" do
143
+ @autocomplete_for_customer.update_attributes! :customer => @customer
144
+ assert_equal @customer, @autocomplete_for_customer.customer
145
+
146
+ @autocomplete_for_customer.update_attributes! :customer_name => nil
147
+ assert_equal @customer, @autocomplete_for_customer.customer
148
+ end
149
+ end
data/test/database.yml ADDED
@@ -0,0 +1,6 @@
1
+ postgresql:
2
+ adapter: postgresql
3
+ database: autocomplete_for_plugin_test
4
+ username: test
5
+ password: pass
6
+ host: localhost
data/test/schema.rb ADDED
@@ -0,0 +1,16 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ create_table :customers, :force => true do |t|
3
+ t.string :name, :unique => true
4
+ t.string :code, :unique => true
5
+ end
6
+ create_table :vendors, :force => true do |t|
7
+ t.string :name, :unique => true
8
+ t.string :code, :unique => true
9
+ end
10
+ create_table :auto_complete_for_customer_test_models, :force => true do |t|
11
+ t.integer :customer_id
12
+ end
13
+ create_table :auto_complete_for_vendor_test_models, :force => true do |t|
14
+ t.integer :vendor_id
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_support/test_case'
4
+
5
+ require 'test/unit'
6
+ require 'active_record'
7
+
8
+ def load_schema
9
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
10
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
11
+ db_adapter = ENV['DB'] || 'postgresql'
12
+
13
+ if config[db_adapter].nil?
14
+ raise "DB Adapter #{db_adapter} has no entries in database.yml."
15
+ end
16
+
17
+ ActiveRecord::Base.establish_connection(config[db_adapter])
18
+ load(File.dirname(__FILE__) + "/schema.rb")
19
+ require File.dirname(__FILE__) + '/../rails/init'
20
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: autocomplete_for
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Sean Kirby
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-24 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activerecord
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 11
30
+ segments:
31
+ - 2
32
+ - 3
33
+ - 4
34
+ version: 2.3.4
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: pg
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ type: :development
50
+ version_requirements: *id002
51
+ description: Model-side logic for autocompleting belongs_to associations
52
+ email: sskirby@gmail.com
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ extra_rdoc_files:
58
+ - README.markdown
59
+ files:
60
+ - .gitignore
61
+ - MIT-LICENSE
62
+ - README.markdown
63
+ - Rakefile
64
+ - VERSION
65
+ - autocomplete_for.gemspec
66
+ - lib/autocomplete_for.rb
67
+ - lib/autocomplete_for/autocomplete_for.rb
68
+ - rails/init.rb
69
+ - test/autocomplete_for_test.rb
70
+ - test/database.yml
71
+ - test/schema.rb
72
+ - test/test_helper.rb
73
+ has_rdoc: true
74
+ homepage: http://github.com/sskirby/autocomplete_for
75
+ licenses: []
76
+
77
+ post_install_message:
78
+ rdoc_options:
79
+ - --charset=UTF-8
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ hash: 3
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ requirements: []
101
+
102
+ rubyforge_project: autocomplete_for
103
+ rubygems_version: 1.3.7
104
+ signing_key:
105
+ specification_version: 3
106
+ summary: Model-side logic for autocompleting belongs_to associations
107
+ test_files:
108
+ - test/schema.rb
109
+ - test/autocomplete_for_test.rb
110
+ - test/test_helper.rb