Rails 祖先 gem + 渲染并选择 category/subcategory 新形式
Rails ancestry gem + Render and choose category/subcategory in new form
我有 Rails 5.2.2,我正在尝试实现祖先 gem。
所以我想要的是:
我希望用户为汽车零件创建报价,但在新表格中我希望能够选择 category/subcategories 然后输入我拥有的其他详细信息,然后提交表格来创建报价。假设有人想添加销售刹车片。
但首先要select父类。
例如
汽车->刹车->刹车片
所以在选择刹车片后,他可以创建报价。
我有:
#category.rb
class Category < ApplicationRecord
has_ancestry
has_many :parts
end
-
#part.rb
class Part < ApplicationRecord
belongs_to :category
end
目前,我已经在控制台中创建了一个以使其正常工作:
例如
car = Category.create!(name: "Car")
brakes = Category.create!(name: "Brakes", parent: car)
brake_pads = Category.create!(name: "Brake Pads", parent: brakes)
我也已经运行迁移了rails g migration add_category_to_parts category:references
。
而我的观点:
#views/parts/new.html.haml
.container
%h2.center Create offer
= simple_form_for(@part, html: {class: "form-group" }) do |f|
.form-group.col-md-8.col-md-offset-2.well
= f.input :title
= f.input :make_name, label: "Make"
= f.input :code, label: 'Part number'
= f.association :condition, label_method: :name, prompt: "-"
= f.input :description
.form-actions
= f.button :submit, class: "btn btn-primary btn-dark-blue"
问题是:
我如何在我的视图中呈现 categories/subcategories -> 部分 -> new.html.haml 表单,其中包含 3 个下拉菜单(每个子类别一个,因为我会有很多 categories/subcategories),以便用户可以选择它们并然后创建报价?
无论如何你都需要 CategoriesController,因为你需要依赖下拉列表。当用户在第一个类别中选择类别时,您需要AJAX请求获取子类别等
# config/routes.rb
resources :categories, only: [] do
get :select_item, on: :collection
end
# app/assets/javascripts/application.js
$('#first-dropdown').on('change', function() {
$.ajax({
url: 'categories/select_item?category_id=' + $(this).val(),
dataType: 'json',
success: function(data) {
var childElement = $('#second-dropdown');
childElement.html('');
data.forEach(function(v) {
var id = v.id;
var name = v.name;
childElement.append('<option value="' + id + '">' + name + '</option>');
});
}
});
});
# app/controllers/categories_controller.rb
Class CategoriesController < ApplicationController
def select_item
category = @category.find params[:category_id]
render json: category.children
end
end
# app/inputs/fake_select_input.rb
class FakeSelectInput < SimpleForm::Inputs::CollectionSelectInput
def input(wrapper_options = nil)
label_method, value_method = detect_collection_methods
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options).merge(input_options.slice(:multiple, :include_blank, :disabled, :prompt))
template.select_tag(
attribute_name,
template.options_from_collection_for_select(collection, value_method, label_method, selected: input_options[:selected], disabled: input_options[:disabled]),
merged_input_options
)
end
end
# views/parts/new.html.haml
.form-group.col-md-8.col-md-offset-2.well
= f.input :title
= f.input :make_name, label: "Make"
= f.input :code, label: 'Part number'
= f.association :condition, label_method: :name, prompt: "-"
= f.input :description
= f.input :parent_category_id, as: :fake_select, collection: Category.roots, input_html: { id: 'first-dropdown' }
= f.input category_id, collection: [], input_html: { id: 'second-dropdown' }
.form-actions
= f.button :submit, class: "btn btn-primary btn-dark-blue"
由于 simple_form 依赖于使用模型,您需要为非模型字段(父类别)创建自定义输入。您只需要保存一个 category_id 到@part,父类别总是可以从中获取。
如果您需要的下拉菜单不止 2 个,只需再添加一个功能或(更好)更改它,这样您就可以将依赖的下拉菜单作为参数传递
我有 Rails 5.2.2,我正在尝试实现祖先 gem。
所以我想要的是:
我希望用户为汽车零件创建报价,但在新表格中我希望能够选择 category/subcategories 然后输入我拥有的其他详细信息,然后提交表格来创建报价。假设有人想添加销售刹车片。 但首先要select父类。 例如
汽车->刹车->刹车片
所以在选择刹车片后,他可以创建报价。
我有:
#category.rb
class Category < ApplicationRecord
has_ancestry
has_many :parts
end
-
#part.rb
class Part < ApplicationRecord
belongs_to :category
end
目前,我已经在控制台中创建了一个以使其正常工作: 例如
car = Category.create!(name: "Car")
brakes = Category.create!(name: "Brakes", parent: car)
brake_pads = Category.create!(name: "Brake Pads", parent: brakes)
我也已经运行迁移了rails g migration add_category_to_parts category:references
。
而我的观点:
#views/parts/new.html.haml
.container
%h2.center Create offer
= simple_form_for(@part, html: {class: "form-group" }) do |f|
.form-group.col-md-8.col-md-offset-2.well
= f.input :title
= f.input :make_name, label: "Make"
= f.input :code, label: 'Part number'
= f.association :condition, label_method: :name, prompt: "-"
= f.input :description
.form-actions
= f.button :submit, class: "btn btn-primary btn-dark-blue"
问题是: 我如何在我的视图中呈现 categories/subcategories -> 部分 -> new.html.haml 表单,其中包含 3 个下拉菜单(每个子类别一个,因为我会有很多 categories/subcategories),以便用户可以选择它们并然后创建报价?
无论如何你都需要 CategoriesController,因为你需要依赖下拉列表。当用户在第一个类别中选择类别时,您需要AJAX请求获取子类别等
# config/routes.rb
resources :categories, only: [] do
get :select_item, on: :collection
end
# app/assets/javascripts/application.js
$('#first-dropdown').on('change', function() {
$.ajax({
url: 'categories/select_item?category_id=' + $(this).val(),
dataType: 'json',
success: function(data) {
var childElement = $('#second-dropdown');
childElement.html('');
data.forEach(function(v) {
var id = v.id;
var name = v.name;
childElement.append('<option value="' + id + '">' + name + '</option>');
});
}
});
});
# app/controllers/categories_controller.rb
Class CategoriesController < ApplicationController
def select_item
category = @category.find params[:category_id]
render json: category.children
end
end
# app/inputs/fake_select_input.rb
class FakeSelectInput < SimpleForm::Inputs::CollectionSelectInput
def input(wrapper_options = nil)
label_method, value_method = detect_collection_methods
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options).merge(input_options.slice(:multiple, :include_blank, :disabled, :prompt))
template.select_tag(
attribute_name,
template.options_from_collection_for_select(collection, value_method, label_method, selected: input_options[:selected], disabled: input_options[:disabled]),
merged_input_options
)
end
end
# views/parts/new.html.haml
.form-group.col-md-8.col-md-offset-2.well
= f.input :title
= f.input :make_name, label: "Make"
= f.input :code, label: 'Part number'
= f.association :condition, label_method: :name, prompt: "-"
= f.input :description
= f.input :parent_category_id, as: :fake_select, collection: Category.roots, input_html: { id: 'first-dropdown' }
= f.input category_id, collection: [], input_html: { id: 'second-dropdown' }
.form-actions
= f.button :submit, class: "btn btn-primary btn-dark-blue"
由于 simple_form 依赖于使用模型,您需要为非模型字段(父类别)创建自定义输入。您只需要保存一个 category_id 到@part,父类别总是可以从中获取。 如果您需要的下拉菜单不止 2 个,只需再添加一个功能或(更好)更改它,这样您就可以将依赖的下拉菜单作为参数传递