如何使用Selectize.js查找或创建Rails About_to关联?

时间:2018-07-31 04:36:13

标签: javascript ruby-on-rails ruby forms selectize.js

我很难弄清楚如何将Selectize.js与rails中的belongs_to关联。我想做这张照片:

enter image description here

我尝试使用accepts_nested_attributes,但似乎不适用于belongs_to关系。

我尝试进行类似railscast episode的自动完成关联。

我真正想做的是使用Selectize样式集合选择来创建“扬声器”关联(如果该关联已存在于数据库中),但是添加一个新的(如果该关联不存在的话)。 Selectize使我可以添加一个新记录,但是在将其传递给表单以在关联模型中创建新记录时遇到麻烦。

这是我的模特:

class Quote < ApplicationRecord
  belongs_to :speaker,  class_name: "Artist"
  belongs_to :topic,    class_name: "Artist"
end

Quote.rb

class Artist < ApplicationRecord
  has_many :spoken_quotes, class_name: "Quote", foreign_key: :speaker_id
  has_many :topic_quotes,  class_name: "Quote", foreign_key: :topic_id
end

Artist.rb

我的表单:

<%= f.label :speaker, 'Who said it?' %>
<%= f.collection_select :speaker_id, Artist.order(:name), :id, :name, {prompt: 'Select an artist'}, {class: 'form-control select-artist'} %>

_form.html.erb

控制器:

quotes_controller.rb

artists_controller.rb

如何通过Quote.new表单和Selective-style集合select创建一个新的Artist(作为“发言人”)? Selectize行为是我想要的用户体验,我只是想不通如何通过Quote表单创建新的Artist。

2 个答案:

答案 0 :(得分:4)

如果必须使用选择用户体验,则可能需要使用JavaScript通过ajax创建艺术家/扬声器。使用selectize-rails gemjquery-rails和一些JavaScript代码,您可以:

  1. 通过ajax创建艺术家/扬声器,并将值和ID分配给引号形式的输入-see demo

  2. 弹出带有艺术家表格的模式,通过ajax提交表格,并将值和id分配给引号形式输入

我已经尝试用您要实现的基本结构来简化此simple rails app,以向您展示选项1的示例。我在自述文件中包含了安装说明和演示。 / p>

所需的主要更改是:

宝石变化:

selectize-railsjquery-rails宝石添加到Gemfile中,然后运行捆绑安装。

HTML表单更改:

将selectize类添加到collection_select输入标记中

# /views/quotes/_form.html.erb

<%= f.collection_select :artist_id, Artist.order(:name), :id, :name, {prompt: 'Select an artist'}, {class: 'selectize'} %>

JavaScript更改:

创建/assets/javascript/quotes.js并进行以下更改。

# /assets/javascript/quotes.js

$(document).on("turbolinks:load", function(){
  $(".selectize").selectize({
    create: function(input, callback) {
      $.post('/artists.json', { artist: { name: input } })
        .done(function(response){
          console.log(response)
          callback({value: response.id, text: response.name });
        })
    }
    });
})

修改您的artists_controller

修改artists_controller#create操作方法以能够呈现json响应。

  # POST /artists
  # POST /artists.json
  def create
    @artist = Artist.new(artist_params)

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

您还可以观看this GoRails video,了解如何实现选项2。

答案 1 :(得分:1)

如果要提供缺少时创建功能,并且唯一需要的值是选择器输入中的值,请考虑完全跳过id

class Quote < ApplicationRecord
  def speaker_name
    speaker&.name
  end

  def speaker_name=(name)
    self.speaker = name.presence && Artist.find_or_initialize_by(name: name)
  end

在视图中:

<%= f.label :speaker, 'Who said it?' %>
<%= f.collection_select :speaker_name, Artist.order(:name), :name, :name, {prompt: 'Select an artist'}, {class: 'form-control select-artist'} %>

(在QuotesController#quote_params中有匹配的更改)

然后,当您对输入进行Selectify化时,允许输入新值,它应该可以正常工作。值得注意的是,这避免了通过AJAX急切创建艺术家记录,如果有人键入条目但从未提交表格,则AJAX可以创建孤儿。