我正在创建一家服装店。我有类别有大小。女式衬衫(类别)可能有XS,S,M,Large。男式衬衫可以有XS,S,M,L。鞋子可以有4-16等等。
我创建了一个has_many through: association
,用Category
表和Sizes
表连接Cateogry_Sizes
表。
当管理员创建类别时,他们应该选择所有类别所需的大小。
如何在下方视图中选择尺寸?
当前代码不正确。在控制台中,当我转到category.sizes
时,我只得到一个空数组。
查看:
<div class="container">
<div class=“row”>
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-primary">
<div class="panel-body">
<%= simple_form_for(@category) do |f| %>
<div class="form-inputs">
<%= f.input :name %>
<%= f.select(:sizes, Size.all.map {|s| [s.title, s.id]}, :multiple => true) %>
<%= f.collection_select :parent_id, Category.order(:name), :id, :name, {prompt: "Select Parrent ID If Applicable"},include_blank: true %>
<div class="form-actions"><%= f.button :submit %></div>
</div>
<% end %>
</div>
</div>
</div>
</div>
</div>
类别模型:
class Category < ActiveRecord::Base
has_ancestry
has_many :items
validates :name, presence: true, length: { maximum: 20 }
has_many :category_sizes
has_many :sizes, through: :category_sizes
end
尺码型号:
class Size < ActiveRecord::Base
validates :title, presence: true, length: { maximum: 15 }
validates :title, uniqueness: true
has_many :category_sizes
has_many :categories, through: :category_sizes
end
Category_size模型:
class CategorySize < ActiveRecord::Base
belongs_to :category
belongs_to :size
end
架构:
ActiveRecord::Schema.define(version: 20150920013947) do
create_table "categories", force: :cascade do |t|
t.string "name"
t.string "ancestry"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "categories", ["ancestry"], name: "index_categories_on_ancestry"
create_table "category_sizes", force: :cascade do |t|
t.integer "category_id"
t.integer "size_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "category_sizes", ["category_id"], name: "index_category_sizes_on_category_id"
add_index "category_sizes", ["size_id"], name: "index_category_sizes_on_size_id"
create_table "items", force: :cascade do |t|
t.string "title"
t.decimal "price"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
t.integer "category_id"
end
add_index "items", ["user_id", "created_at"], name: "index_items_on_user_id_and_created_at"
add_index "items", ["user_id"], name: "index_items_on_user_id"
create_table "sizes", force: :cascade do |t|
t.text "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "taggings", force: :cascade do |t|
t.integer "tag_id"
t.integer "taggable_id"
t.string "taggable_type"
t.integer "tagger_id"
t.string "tagger_type"
t.string "context", limit: 128
t.datetime "created_at"
end
add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true
add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context"
create_table "tags", force: :cascade do |t|
t.string "name"
t.integer "taggings_count", default: 0
end
add_index "tags", ["name"], name: "index_tags_on_name", unique: true
create_table "users", force: :cascade do |t|
t.string "username"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "remember_digest"
t.boolean "admin", default: false
t.string "activation_digest"
t.boolean "activated", default: false
t.datetime "activated_at"
t.string "reset_digest"
t.string ">"
t.datetime "reset_sent_at"
t.string "avatar_file_name"
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
t.text "description"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
end
控制器:
class CategoriesController < ApplicationController
before_action :set_category, only: [:show]
before_action :admin_user, only: [:destroy, :index, :edit, :show]
def index
@categories = Category.all
end
def show
@tags = Item.where(category_id: @category.id).tag_counts_on(:tags)
if params[:tag]
@items = Item.tagged_with(params[:tag])
else
@items = Item.where(category_id: @category.id).order("created_at DESC")
end
end
def new
@category = Category.new
end
def edit
@category = Category.find(params[:id])
end
def create
@category = Category.new(category_params)
if @category.save
redirect_to @category
flash[:success] = "You have created a new category"
else
flash[:danger] = "Your category didn't save"
render "new"
end
end
def update
@Cateogry = Category.find(params[:id])
if @Cateogry.update(category_params)
redirect_to @Cateogry
flash[:success] = 'Category was successfully updated.'
else
render "edit"
end
end
def destroy
Category.find(params[:id]).destroy
flash[:success] = "Category deleted"
redirect_to categories_path
end
private
def set_category
@category = Category.find(params[:id])
end
def category_params
params.require(:category).permit(:name, :parent_id)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.try(:admin?)
end
end
以下是在控制台中发生的情况:
2.1.2 :026 > c = Category.last
Category Load (0.3ms) SELECT "categories".* FROM "categories" ORDER BY "categories"."id" DESC LIMIT 1
=> #<Category id: 57, name: "Test20", ancestry: "20", created_at: "2015-09-23 12:35:14", updated_at: "2015-09-23 12:35:14">
2.1.2 :027 > c.sizes
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" INNER JOIN "category_sizes" ON "sizes"."id" = "category_sizes"."size_id" WHERE "category_sizes"."category_id" = ? [["category_id", 57]]
以下是服务器日志中表单提交时发生的情况:
Started POST "/categories" for ::1 at 2015-09-23 22:37:28 +1000
Processing by CategoriesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"4pMZ9PUr5yTSCNRiQeATljZsOIDeQCwhQPy9djEbAmejntpb8/DkK20JrMUeZkStsB5UU6YhbtExGwDKs7tT2Q==", "category"=>{"name"=>"test21", "sizes"=>"6", "parent_id"=>"20"}, "commit"=>"Create Category"}
Unpermitted parameter: sizes
Category Load (0.1ms) SELECT "categories".* FROM "categories" WHERE "categories"."id" = ? LIMIT 1 [["id", 20]]
(0.1ms) begin transaction
SQL (0.3ms) INSERT INTO "categories" ("name", "ancestry", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "test21"], ["ancestry", "20"], ["created_at", "2015-09-23 12:37:28.927360"], ["updated_at", "2015-09-23 12:37:28.927360"]]
(1.0ms) commit transaction
Redirected to http://localhost:3000/categories/58
Completed 302 Found in 5ms (ActiveRecord: 1.5ms)
Started GET "/categories/58" for ::1 at 2015-09-23 22:37:28 +1000
Processing by CategoriesController#show as HTML
Parameters: {"id"=>"58"}
答案 0 :(得分:2)
您需要允许控制器的参数中的大小如下:
<%= f.select(:sizes, Size.all.map {|s| [s.title, s.id]}, :multiple => true) %>
在你的表格中你应该改变:
<%= f.association :sizes %>
到
{{1}}
然后简单的形式应该做的魔术。另请参阅:https://github.com/plataformatec/simple_form#associations了解更多信息。
答案 1 :(得分:1)
顺便说一句,我觉得有必要强调you may be able to use has_and_belongs_to_many
使这项工作以目前的形式进行。它与has_many :through
非常相似,只是它没有连接模型:
#app/models/category.rb
class Category < ActiveRecord::Base
has_and_belongs_to_many :sizes
end
#app/models/size.rb
class Size < ActiveRecord::Base
has_and_belongs_to_many :categories
end
这意味着您必须放弃category_sizes
表,并将categories_sizes
替换为category_id | size_id
列:
如果您不想在连接模型中包含任何其他信息,则建议仅 。例如,如果您想要包含库存水平或其他内容,has_many :through
的联接模型将至关重要;不是你现在拥有它。
它还允许您致电:
@category = Category.find params[:id]
@category.sizes #-> collection of sizes for category.
-
<强>表格强>
HABTM也会使形式更简单:
<%= simple_form_for(@category) do |f| %>
<%= f.input :name %>
<%= f.collection_select :sizes, Size.all, :id, :name, { multiple: true } %>
<%= f.collection_select :parent_id, Category.order(:name), :id, :name, {prompt: "Select Parent ID If Applicable"},include_blank: true %>
<%= f.submit %>
<% end %>
#app/controllers/categories_controller.rb
class CategoriesController < ApplicationController
def create
@category = Category.new category_params
end
private
def category_params
params.require(:category).permit(:etc, :etc, :sizes)
end
end