基于响应建议和我自己的进一步调查,我得出的结论是从关联表中获取表单中的大量选项的最佳方式。
看起来自动完成是最好的解决方案。这是一个常规文本字段,但是当您输入第二个字母时,它会提取前 10 个匹配项,并在下面列出它们。每个额外的字母都会优化搜索。由于我对 JavaScript 的熟练程度不高,因此我没有按照建议添加一个以我自己的 JS 为补充的插件,而是选择使用 gem 来抽象 JS 编码,特别是rails-jquery-autocomplete。
以下是步骤:
设置
生成脚手架:
rails generate scaffold City name state
rails generate scaffold Business name address city:references state zip
rake db:migrate
安装宝石。它使用jQuery-UI 的自动完成小部件,因此也为此安装 rails gem。
# gemfile
gem 'jquery-ui-rails'
gem 'rails-jquery-autocomplete'
将这些添加到您的 javascript 和样式表资产中:
# app/assets/javascripts/application.js > put these after //= require jquery_ujs
//= require jquery-ui/autocomplete
//= require autocomplete-rails
# app/assets/stylesheets/application.css
*= require jquery-ui/autocomplete
楷模
首先创建关联:
# app/model/city.rb
has_many :businesses
# app/model/business.rb
belongs_to :city
如果要确保输入的城市在城市表中,请添加验证:
# app/models/business.rb
validates :city, presence: true
业务表有一个字段为 city_id 而不是城市名称。我们可以使用 getter 和 setter 方法在业务模型文件中创建一个虚拟属性。自从我从一个 4 岁的 RailsCast 那里得到它以来,可能有一种更新的方法来做到这一点,但它确实有效。
#getter method
def city_name
city.try(:name)
end
#setter method
def city_name=(name)
self.city = City.find_by(name: name) if name.present?
end
路线
这就是 gem 的魅力所在。添加一条到业务 REST 资源的路由,格式为 autocomplete_model_attribute:
# config/routes.rb
resources :businesses do
get 'autocomplete_city_name' on: :collection
end
控制器
在控制器的顶部调用自动完成操作,将类名和属性传递给它。默认情况下,自动完成将匹配从单词开头开始的文本。如果您想搜索单词中的任何位置,请将“full”选项设置为 true,否则将其省略。
# app/controllers/business_controller.rb
autocomplete :city, :name, full: true
由于我们在业务模型中创建了 city_name 虚拟属性,因此我们需要将其添加到允许的参数列表中
def business_params
params.require(:business).permit(:name, :address, :city_id, :state, :zip, :city_name)
end
意见
在创建或编辑新业务实例的表单中,使用 autocomplete_field 帮助器将 city_id 字段更改为 city_name 虚拟属性。'data-auto-focus' 选项将自动选择列表中的第一个值。如果你不想这样,就把它关掉。
# app/views/businesses/_form.html.erb
<div class="field">
<%= f.label :city_name %><br>
<%= f.autocomplete_field :city_name, autocomplete_city_name_businesses_path, 'data-auto-focus' => true %>
</div>
完毕!