Рельсы 3: множественный выбор с имеет много сквозных ассоциаций
Я хочу получить возможность выбрать несколько категорий для одного сообщения с несколькими select.
у меня есть следующие модели: Post, Category и PostCategory.
class Post < ActiveRecord::Base
has_many :post_categories
has_many :categories, :through => :post_categories
end
class Category < ActiveRecord::Base
has_many :post_categories
has_many :posts, :through => :post_categories
end
class PostCategory < ActiveRecord::Base
has_one :post
has_one :category
belongs_to :post # foreign key - post_id
belongs_to :category # foreign key - category_id
end
в моем контроллере у меня есть что-то вроде @post = Post.новый. Я создал несколько категорий.
и в виду у меня:
<%= form_for @post do |f| %>
<%= f.text_field :title %>
<%= f.select :categories, :multiple => true %>
<%= f.submit %>
<% end %>
и... где мои категории? У меня есть только "несколько" в select options. Я думаю, что это что-то не так с моей формой.
5 ответов:
Извините, что воскрешаю мертвых, но я нашел гораздо более простое решение, которое позволяет использовать код действия контроллера по умолчанию и использовать логику ActiveModel setter для has_many. Да, это совершенно волшебно.
<%= f.select :category_ids, Category.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %>
в частности, используя :category_ids (или: your_collection_ids) имя param автоматически скажет Rails вызвать @post.category_ids = params[:post] [: category_ids] чтобы установить категории для этой записи соответственно, все без изменения контроллера по умолчанию / scaffold #создание и # обновление кода.
О, и он работает с has_many :something, через: :something_else, автоматически управляя моделью соединения. Чертовски круто.
поэтому из OP просто измените имя поля / param на: category_ids вместо: categories.
это также автоматически будет иметь выбранные категории модели заполнить поле выбора, как выделено, когда на форме редактирования.
ссылки:
С типа has_many API docs где я это нашел.
и предупреждение от формы helpers guide объясняет это "несоответствие типа", когда не используется правильное имя поля/параметра формы.
используя правильное имя form-field / param, вы можете высушить новые и редактировать формы и сохранить контроллеры тонкими, как это поощряется Rails.
примечание для рельсов 4 и сильных параметров:
def post_params params.require(:post).permit(:title, :body, category_ids: []) end
окончательное решение для организации категорий в ваших сообщениях, я надеюсь, что это будет полезно.
чтобы использовать несколько Нам нужно select_tag:
<%= select_tag "categories", options_from_collection_for_select(Categories.all, 'id', 'name'), :multiple => true %>
или F.выберите (большое спасибо Тигрейн и Брент!), это более элегантный способ:
<%= f.select :categories, Category.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %>
в создании действия нашего контроллера нам нужно:
def create @post = Post.new(params[:post]) if @post.save params[:categories].each do |categories| categories = PostCategory.new(:category_id => categories, :post_id => @post.id) if categories.valid? categories.save else @errors += categories.errors end end redirect_to root_url, :notice => "Bingo!" else render "new" end end
вам нужен список опций для выбора:
<%= f.select :category_id, Category.all.collect {|x| [x.name, x.id]}, :multiple => true %>