Rails 4:自动完成无法使用rails 4-autocomplete gem

时间:2015-01-08 19:04:11

标签: ruby-on-rails autocomplete has-many-through

我有3个带有has_many关系的模型:食物(例如:巧克力),Sub(巧克力食物替代品),关节(联合表)。

我正在使用rails4-autocomplete gem来运行保存在数据库中的现有替代品(来自我的Sub模型)的简单自动完成,这样当我创建一个新的食物(食物模型)时,我可以将这个"新食物"如果我愿意,可以使用现有替代品。我按照gem doc的步骤进行了操作,但我无法使其正常工作。

我的问题是让自动填充工作,以便在填写表格时(在views / food / _form中)显示已存在的替代品(用我的Sub模型保存)

非常感谢您的帮助,请在下面找到所有相关代码:

application.js :(这里我需要autocomplete-rails)

//= require jquery
//= require jquery_ujs
//= require cocoon
//= require turbolinks
//= require autocomplete-rails
//= require_tree .

我的路线:

  resources :foods do
    get :autocomplete_sub_name, :on => :collection
  end

  resources :subs

  resources :joints

  root "foods#index"

我的3个型号:

class Food < ActiveRecord::Base
    has_many :joints
    has_many :subs, :through => :joints
    accepts_nested_attributes_for :subs, reject_if: :all_blank, allow_destroy: true
end
class Sub < ActiveRecord::Base
    has_many :joints
    has_many :foods, :through => :joints
    accepts_nested_attributes_for :foods, reject_if: :all_blank, allow_destroy: true
end
class Joint < ActiveRecord::Base
    belongs_to :food
    belongs_to :sub
end

我的食物控制员:

class FoodsController < ApplicationController
  before_action :set_food, only: [:show, :edit, :update, :destroy]
  autocomplete :sub, :name, :full => true

  # GET /foods
  # GET /foods.json
  def index
    @foods = Food.all
  end

  # GET /foods/1
  # GET /foods/1.json
  def show
  end

  # GET /foods/new
  def new
    @food = Food.new
    @food.subs.build
  end

  # GET /foods/1/edit
  def edit
  end

  # POST /foods
  # POST /foods.json
  def create
    @food = Food.new(food_params)

    respond_to do |format|
      if @food.save
        format.html { redirect_to @food, notice: 'Food was successfully created.' }
        format.json { render :show, status: :created, location: @food }
      else
        format.html { render :new }
        format.json { render json: @food.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /foods/1
  # PATCH/PUT /foods/1.json
  def update
    respond_to do |format|
      if @food.update(food_params)
        format.html { redirect_to @food, notice: 'Food was successfully updated.' }
        format.json { render :show, status: :ok, location: @food }
      else
        format.html { render :edit }
        format.json { render json: @food.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /foods/1
  # DELETE /foods/1.json
  def destroy
    @food.destroy
    respond_to do |format|
      format.html { redirect_to foods_url, notice: 'Food was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_food
      @food = Food.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def food_params
      params.require(:food).permit(:name, :description, subs_attributes: [:id, :name, :description, :_destroy])
    end
end

我的db-schema FYI:

create_table "foods", force: true do |t|
    t.string   "name"
    t.text     "description"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
  end

  create_table "joints", force: true do |t|
    t.integer  "food_id"
    t.integer  "sub_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "subs", force: true do |t|
    t.string   "name"
    t.text     "description"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
  end

最后是mi _form和_sub_fields,它是在_form中部分呈现的,我尝试使用自动完成:

<%= form_for(@food) do |f| %>
  <% if @food.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@food.errors.count, "error") %> prohibited this food from being saved:</h2>

      <ul>
      <% @food.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :description %><br>
    <%= f.text_area :description %>
  </div>

  <div>
    <%= f.fields_for :subs do |sub| %>
      <%= render 'sub_fields', :f => sub %>
      <%= link_to_add_association 'Add sub', f, :subs %>
    <% end %>
  </div>


  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

_sub_fields partial:

<div class="nested-fields">
    <div class="field">
        <%= f.label :name %>
        <%= f.text_field :name %>
        <%= f.autocomplete_field :sub_name, autocomplete_sub_name_foods_path %>

    </div>
    <div class="field">
        <%= f.label :description %>
        <%= f.text_area :description %>
    </div>
    <%= link_to_remove_association 'remove sub', f %>
</div>

非常感谢您的帮助! 安托

1 个答案:

答案 0 :(得分:0)

从您的所有代码中我只能猜出问题的可能原因:

您正在使用嵌套模型表单中的自动填充字段。 link_to_add_association - 链接动态地向页面添加新元素。请注意新添加的元素附加了必要的Javascript事件处理程序。 gem的Javascript包含以下行:

jQuery(document).ready(function(){
  jQuery('input[data-autocomplete]').railsAutocomplete()
});

因此事件处理程序仅附加到页面完全加载后已存在的元素。尝试将这些行更改为:

jQuery(document).ready(function(){
  jQuery('body').on('focus', 'input[data-autocomplete]', function(){
    jQuery(this).railsAutocomplete()
  })
})

这样,每次添加一组新的嵌套字段时都会附加事件处理程序。