如何使用Selectize.js查找或创建railsbelongs_to关联?
How to use Selectize.js to find or create a rails belongs_to association?
我很难弄清楚如何将 Selectize.js 与 rails 中的 belongs_to 关联结合起来。我想做类似这张照片的事情:
我尝试过使用 accepts_nested_attributes
,但这似乎不适用于 belongs_to
关系。
我试过像这样 auto-complete 关联 railscast episode。
我真正想做的是使用 Selectize 样式 collection select 创建 "Speaker" 关联(如果它已经在数据库中),但添加一个新的如果它还不存在。 Selectize 使我能够添加一个新记录,但我无法通过表单传递它以在关联模型中创建新记录。
这是我的模型:
class Quote < ApplicationRecord
belongs_to :speaker, class_name: "Artist"
belongs_to :topic, class_name: "Artist"
end
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
还有我的表格:
<%= 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'} %>
控制器:
如何通过 Selective-style collection select 通过 Quote.new 表单创建新艺术家(如 "Speaker")? Selectize 行为是我正在寻找的用户体验,我只是不知道如何通过报价表创建新的艺术家。
如果您必须使用 selectize 用户体验,您可能需要使用 javascript 通过 ajax 创建 artist/speaker。使用 selectize-rails
gem、jquery-rails
和一些 javascript 代码,您可以:
通过 ajax 创建 artist/speaker 并将值和 ID 分配给引号表单输入 - see demo 或
弹出一个带有艺术家表单的模式,通过ajax提交表单并将值和id分配给报价表单输入
我试图用您想要实现的基本结构来构建此 simple rails app 以向您展示选项 1 的示例。我在自述文件中包含了设置说明和演示.
需要进行的主要更改是:
Gem 变化:
将 selectize-rails
和 jquery-rails
gem 添加到您的 Gemfile
和 运行 捆绑安装中。
HTML 表格变化:
将 selectize class 添加到 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。
如果您要提供缺失时创建功能,并且唯一需要的值是选择器输入中的值,请考虑完全跳过 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 急切地创建艺术家记录,如果有人键入条目但从未提交表单,这可能会创建孤儿。
我很难弄清楚如何将 Selectize.js 与 rails 中的 belongs_to 关联结合起来。我想做类似这张照片的事情:
我尝试过使用 accepts_nested_attributes
,但这似乎不适用于 belongs_to
关系。
我试过像这样 auto-complete 关联 railscast episode。
我真正想做的是使用 Selectize 样式 collection select 创建 "Speaker" 关联(如果它已经在数据库中),但添加一个新的如果它还不存在。 Selectize 使我能够添加一个新记录,但我无法通过表单传递它以在关联模型中创建新记录。
这是我的模型:
class Quote < ApplicationRecord
belongs_to :speaker, class_name: "Artist"
belongs_to :topic, class_name: "Artist"
end
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
还有我的表格:
<%= 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'} %>
控制器:
如何通过 Selective-style collection select 通过 Quote.new 表单创建新艺术家(如 "Speaker")? Selectize 行为是我正在寻找的用户体验,我只是不知道如何通过报价表创建新的艺术家。
如果您必须使用 selectize 用户体验,您可能需要使用 javascript 通过 ajax 创建 artist/speaker。使用 selectize-rails
gem、jquery-rails
和一些 javascript 代码,您可以:
通过 ajax 创建 artist/speaker 并将值和 ID 分配给引号表单输入 - see demo 或
弹出一个带有艺术家表单的模式,通过ajax提交表单并将值和id分配给报价表单输入
我试图用您想要实现的基本结构来构建此 simple rails app 以向您展示选项 1 的示例。我在自述文件中包含了设置说明和演示.
需要进行的主要更改是:
Gem 变化:
将 selectize-rails
和 jquery-rails
gem 添加到您的 Gemfile
和 运行 捆绑安装中。
HTML 表格变化:
将 selectize class 添加到 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。
如果您要提供缺失时创建功能,并且唯一需要的值是选择器输入中的值,请考虑完全跳过 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 急切地创建艺术家记录,如果有人键入条目但从未提交表单,这可能会创建孤儿。