三个模型 Category, Tag, Product, Category 有多个 Tag,Tag 有多个 Product, 现在想编辑 Product 的时候, 选择 Category 的时候。让 Tag 随着改变。 这个应该怎么实现。这样表关联有什么问题的吗?
将关联数据渲染成嵌套的 json,每次更新选择之后取到新的 category 的 id,再通过 category 的 id 取到对应的 tags 集合,更新到下一级的select
控件。比如 controller 里边可以写:
# app/controllers/products_controller.rb
class ProductsController < ApplicationController
def edit
@multi_level_products_hash = {}
@categories = Category.all
@tags_options = {}
tags = @categories.map(&:tags).flatten
tags.each do |tag|
@tags_options[tag.id] = "<option value=#{tag.id}>#{tag.name}</option>"
end
@products_options = {}
tags.map(&:products).flatten.each do |product|
@products_options[product.id] = "<option value=#{product.id}>#{product.name}</option>"
end
@categories.each do |category|
@multi_level_products_hash[category.id] = {}
category.tags.each do |tag|
@multi_level_products_hash[category.id][tag.id] = tag.products.map(&:id)
end
end
end
view 层的代码片断
<!-- app/views/products/edit.html.erb -->
<%= collection_select :category, :name, @categories, :id, :name %>
<%= select_tag :tag %>
<%= select_tag :product %>
<%= javascript_tag do %>
var multiLevelProducts = <%= raw @multi_level_products_hash.to_json %>;
var tagsOptions = <%= raw @tags_options.to_json %>
var productsOptions = <%= raw @products_options.to_json %>
<% end %>
后边要做的事就是每次通过 category 的 idcategoryId
取到对应的 tags 的 id 的集合,也就是multiLevelProducts[categoryId]
的键集。tag 的处理跟 category 一致。
// app/assets/javascript/products.js
$.extend({
keys: function(obj) {
var a = [];
$.each(obj, function(k) {
a.push(k);
});
return a;
}
});
$(document).ready(function() {
$('#category_name').on('change', function() {
var categoryId = $(this).val();
var tagsKeys = $.keys(multiLevelProducts[categoryId]);
var options = [];
$.each(tagsKeys, function(key, value) {
options.push(tagsOptions[value]);
});
$('#tag').empty().append(options);
});
}