Rails 3: множественный выбор с has_many через ассоциации
Я хочу получить возможность выбрать несколько категорий для одного сообщения с несколькими выборами.
У меня есть следующие модели: 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.new.
Я создал несколько категорий.
И у меня есть:
<%= form_for @post do |f| %>
<%= f.text_field :title %>
<%= f.select :categories, :multiple => true %>
<%= f.submit %>
<% end %>
И... где мои категории? У меня есть только "несколько" в некоторых опциях. Я думаю, что с моей формой что-то не так.
Ответы
Ответ 1
Извините, что воскресил мертвых, но я нашел гораздо более простое решение, позволяющее использовать код действия контроллера по умолчанию и использовать логику setMystel ActiveModel для has_many. Да, это совершенно волшебство.
<%= f.select :category_ids, Category.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %>
В частности, использование имени параметра category_ids (или: your_collection_ids) автоматически укажет Rails для вызова @post.category_ids = params [: post] [: category_ids], чтобы соответственно установить категории для этой публикации, без изменения значения по умолчанию контроллер /scaffold #create и #update код.
О, и он работает с has_many: что-то, через:: something_else, автоматически управляя моделью объединения. Освобождение от ужаса.
Итак, из OP просто измените имя поля /param на: category_ids вместо: categories.
Это также автоматически приведет к тому, что выбранные модели будут заполнять поле выбора, как выделено, когда на форме редактирования.
Литература:
Из документации has_many API, где я нашел это.
Также предупреждение из справочника справочника формы объясняет это "несоответствие типа", когда не используется правильное имя поля формы/параметра.
Используя правильное имя поля формы /param, вы можете вытереть новые и редактировать формы и не допустить, чтобы контроллеры были тонкими, что поощрялось способом Rails.
примечание для рельсов 4 и сильные параметры:
def post_params
params.require(:post).permit(:title, :body, category_ids: [])
end
Ответ 2
Окончательное решение по организации категорий в ваших сообщениях, надеюсь, это будет полезно.
Чтобы использовать несколько, нам нужно select_tag:
<%= select_tag "categories", options_from_collection_for_select(Categories.all, 'id', 'name'), :multiple => true %>
Или f.select(благодаря Tigraine и Brent!), это более элегантный способ:
<%= 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
Ответ 3
Что вам нужно, это список опций для выбора:
<%= f.select :category_id, Category.all.collect {|x| [x.name, x.id]}, :multiple => true %>
Ответ 4
Тигрень почти имела это, но вам нужно указать дополнительный пустой хеш:
<%= f.select :category_id, Category.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %>
Ответ 5
Поскольку @post не имеет идентификатора, он может не отображать категории, поскольку нет никакой связи. Вам нужно пройти, постройте на @post что-то вроде
@post = Post.new(:categories => Category.all)