Pozwolę sobie zacząć od stwierdzenia, że może to być również problem z modelowaniem i jestem otwarty na propozycje modeli.Szyny 4 Jak modelować formularz z kolekcją pól wyboru z innym polem tekstowym
Przypadek użycia: Mam formularz i muszę zezwolić użytkownikowi na zaznaczenie pola wyboru w kategorii jego wpisu. Jeśli nie ma kategorii, która pasuje do ich sprawdzania postów, druga kategoria pokaże pole tekstowe, aby użytkownik mógł dodać kategorię niestandardową. Powinno to byłoby do tworzenia i aktualizacji modułów zagnieżdżonych
DB Modeling
Modelsclass 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
App
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
Kontroler:
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
Widok:
= 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?
Jednak przy powyższym rozwiązaniu kontynuuję uruchamianie, aby zduplikować błędy zapisu podczas zapisywania. Nie wiesz, dlaczego tak się dzieje? Czy jest lepszy sposób to zrobić?
Dzięki temu rozwiązaniu musiałbym śledzić typ kategorii w modelu, prawda? Wstawiłoby to również wiele kategorii, których nigdy bym nie pokazał. – Matt
Nie jestem w 100% pewien, co masz na myśli, jeśli chcesz śledzić typ kategorii. Jeśli chcesz, aby każda z kategorii "Inne" była traktowana inaczej niż "oryginalne" kategorie, możesz je podklasować (dziedziczenie pojedynczej tabeli). Ale tak, utworzyłoby to wiele kategorii, które nie byłyby wyświetlane. Nie jestem pewien, czy to jest prawdziwy problem. –