[英]Rails 4 How to model a form with a collection of checkboxes with other text_field
首先讓我先說這也可能是一個建模問題,我對模型建議持開放態度。
使用案例:我有一個表單,我需要允許用戶選擇其帖子類別的復選框。 如果沒有適合其帖子檢查的類別,則其他類別將顯示用戶添加自定義類別的文本字段。 這應該用於創建和更新嵌套模塊
數據庫建模
class CreateCategories < ActiveRecord::Migration
def change
create_table :categories do |t|
t.string :name, null: false
t.timestamps null: false
end
reversible do |dir|
dir.up {
Category.create(name: 'Hats')
Category.create(name: 'Shirts')
Category.create(name: 'Pants')
Category.create(name: 'Shoes')
Category.create(name: 'Other')
}
end
create_table :categorizations, id: false do |t|
t.belongs_to :post, index: true, null: false
t.belongs_to :category, index: true, null: false
t.string :value
end
end
end
應用模型
class Post < ActiveRecord::Base
has_many :categorizations
accepts_nested_attributes_for :categorizations, allow_destroy: true
has_many :categories, through: :categorizations
accepts_nested_attributes_for :categories
end
class Category < ActiveRecord::Base
has_many :posts
end
控制器:
def update
if @post.update(post_params)
flash.now[:success] = 'success'
else
flash.now[:alert] = @post.errors.full_messages.to_sentence
end
render :edit
end
private
def set_post
@post = Post.find(params[:id])
(Category.all - @post.categories).each do |category|
@post.categorizations.build(category: category)
end
@post.categorizations.to_a.sort_by! {|x| x.category.id }
end
def post_params
params.require(:post).permit(:name, :description,
categorizations_attributes: [ :category_id, :value, :_destroy],
)
end
視圖:
= f.fields_for :categorizations do |ff|
= ff.check_box :_destroy, { checked: ff.object.persisted? }, '0', '1'
= ff.label :_destroy, ff.object.category.name
= ff.hidden_field :category_id
= ff.text_field :value if ff.object.category.other?
但是,通過上述解決方案,我在保存時繼續運行以復制記錄錯誤。 不知道為什么會這樣? 有一個更好的方法嗎?
我更喜歡這樣的東西:
楷模
post.rb
class Post < ActiveRecord::Base
has_many :categorizations
has_many :categories, through: :categorizations
accepts_nested_attributes_for :categorizations, allow_destroy: true
accepts_nested_attributes_for :categories
end
category.rb
class Category < ActiveRecord::Base
has_many :categorizations
has_many :posts, through: :categorizations
end
調節器
...
def update
if @post.update(post_params)
flash.now[:success] = 'success'
else
flash.now[:alert] = @post.errors.full_messages.to_sentence
end
render :edit
end
private
def set_post
@post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:name, :description, category_ids: [])
end
...
查看我總是preferer平原.erb
因此,與幫助simple_form 。
<%= simple_form_for(@post) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :content -%>
...
</div>
<div class="form-inputs">
<%= f.association :categories, as: :check_boxes -%>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
您可以通過這種方式檢查/取消選中狀態並輕松干凈地銷毀。 另外,你可以添加
<%= f.simple_fields_for :category do |category_fields| %>
<%= category_fields.input :name -%>
<% end %>
獲取關聯的嵌套字段,但不要忘記在執行此strong_params
時將相關的參數添加到strong_params
。
...
def post_params
params.require(:post).permit(:name, :description, category_attributes: [:name])
end
....
不要將另一個存放在您的模型中,也不要將其名稱存儲起來! 如果您在posts
使用form_for
,只需添加一個不相關的字段即可。
例如: f.text_field :other_name
到text_field_tag :other_name
手動將“ Other
選項添加到下拉列表集合中。
如果選擇了其他,則可以添加JS以隱藏和顯示隱藏文本字段。
在你的posts_controller中:
def create
...
if params[:other_name]
post.categories.create(name: param[:other_name])
end
...
end
您應該創建一個新的Category實例,而不是讓用戶選擇“其他”類別,然后將文本字段存儲在其他位置。 您使用accepts_nested_attributes_for
在正確的軌道上。
下一步將是:
# app/controllers/posts_controller.rb
def new
@post = Post.new
@post.build_category
end
private
# don't forget strong parameters!
def post_params
params.require(:post).permit(
...
category_attributes: [:name]
...
)
end
視圖(使用simple_form和nested_form gems)
# app/views/new.html.haml
= f.simple_nested_form_for @job do |f|
= f.simple_fields_for :category do |g|
= g.input :name
您也可以使用表單對象來更干凈。
編輯:如果您需要將其他類別的關注點與原始類別分開,則可以使用OO繼承來執行此操作。 Rails執行此操作的方法是單表繼承 。
# app/models/category.rb
class Category < ActiveRecord::Base
end
# app/models/other_category.rb
class OtherCategory < Category
end
# app/models/original_category.rb
class OriginalCategory < Category
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.