【问题标题】:How to use Selectize.js to find or create a rails belongs_to association?如何使用 Selectize.js 查找或创建 rails belongs_to 关联?
【发布时间】:2019-01-07 09:15:55
【问题描述】:

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

我尝试过使用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

如何通过 Selective 样式的集合选择通过 Quote.new 表单创建新的艺术家(作为“演讲者”)? Selectize 行为是我正在寻找的用户体验,我只是不知道如何通过 Quote 表单创建新的 Artist。

【问题讨论】:

  • 为什么不将代码(如果可能,仅相关)添加到问题本身而不是附加链接?
  • 感谢@JagdeepSingh 我用相关代码编辑了问题。
  • 哪里坏了?您能否清楚区分此过程中的每个步骤,以及我们对此故障的线索是什么。 1)用户填写表格(它有效吗?是通过http提交的参数吗?) 2)rails控制器接收到请求(这里到底有什么不工作?或者这完全在你的控制器逻辑之外并且在gem内部? ) 3) 模型实例和保存(错误..?)

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


【解决方案1】:

如果您必须使用 selectize 用户体验,您可能需要使用 javascript 通过 ajax 创建艺术家/演讲者。使用 selectize-rails gemjquery-rails 和一些 javascript 代码,您可以:

  1. 通过 ajax 创建艺术家/演讲者并将值和 id 分配给引号表单输入 - see demo

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

我已尝试使用您尝试实现的基本结构来构建此simple rails app,以向您展示选项 1 的示例。我在自述文件中包含了设置说明和演示。

所需的主要更改是:

宝石变化:

selectize-railsjquery-rails gem 添加到您的Gemfile 并运行捆绑安装。

HTML 表单更改:

将选择类添加到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。

【讨论】:

  • 真的很感激!我在 Stackoverflow 上看到的最详细的回复。我肯定在尝试实现选项 1。我不知道如何通过 Ajax 创建艺术家,所以你肯定为我指明了正确的方向。我遇到的第一个问题是我必须将speaker_id 传递给collection_select,否则我会在quotes/new 上收到method missing 错误,然后我必须从我的ApplicationController 中删除protect_from_forgery with: :exception(因为它也是在您的演示应用程序中),否则我会收到此错误-ActionController::InvalidAuthenticityToken。这安全吗?
  • 很高兴它有助于为您指明正确的方向。实际上,演示应用程序是使用 rails 5.2 制作的,默认情况下 ActionController::Base.default_protect_from_forgery 设置为 true。您能否添加您的代码当前外观的链接,以便我查看是否可以复制您遇到的新错误?
  • 感谢您的帮助。最终切换到选项 2,使用模式,因为我意识到在创建新艺术家时需要设置除名称之外的另一个属性。
【解决方案2】:

如果您提供缺失时创建功能,并且唯一需要的值是选择器输入中的值,请考虑完全跳过 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 中进行匹配更改)

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

【讨论】:

  • 这是有道理的。没有意识到我可以在没有 ID 的情况下创建关联。感谢您指出这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多