Лучшая практика Rails для использования полиморфной ассоциации

Я фактически создаю систему таксономии в своем приложении. Вот моя схема таблиц:

Taxonomies

class CreateTaxonomies < ActiveRecord::Migration def change create_table :taxonomies do |t| t.references :taxonomable, polymorphic: true t.integer :term_id end end
end

сроки

class CreateTerms < ActiveRecord::Migration def change create_table :terms do |t| t.string :name t.string :type t.integer :parent_id, default: 0 end end
end

и вот мои ассоциации:

class Taxonomy < ActiveRecord::Base belongs_to :taxonomable, polymorphic: true
end
class Term < ActiveRecord::Base self.inheritance_column = :_type_disabled // because I use type as table field has_many :taxonomies, as: :taxonomable
end

Чтобы сделать его более общим, я вызываю беспокойство:

module Taxonomable extend ActiveSupport::Concern included do has_many :taxonomies, as: :taxonomable end def get_associate_terms terms = self.taxonomies.map { |t| t.term_id } taxonomies = Term.find terms end
end

и я включаю его в свою модель:

class Post < ActiveRecord::Base include Taxonomable
end

Он отлично работает, и я могу получить связанные данные с помощью get_associate_terms. Моя проблема находится внутри моего контроллера и моей формы. Я фактически сохраняю это так:

# posts/_form.html.haml
= f.select :taxonomy_ids, @categories.map { |c| [c.name, c.id] }, {}, class: 'form-control'
# PostsController
def create @post = current_user.posts.new( post_params ) if @post.save @post.taxonomies.create( term_id: params[:post][:taxonomy_ids] ) redirect_to posts_path else render :new end
end

Этот метод создания правильно сохраняет данные, но если вы посмотрите на атрибут params, вы увидите, что taxonomies объектов ждут term_id но я могу использовать taxonomy_ids в моей форме. Это кажется грязным, и я хотел, чтобы ваша точка зрения не позволяла так взломать.

Кроме того, и я думаю, что эта проблема связана с той, что была выше, при редактировании моего элемента в поле выбора не проверяется, что фактическая соответствующая категория ассоциируется с текущим сообщением.

Любые мысли приветствуются.

большое спасибо

РЕДАКТИРОВАТЬ: Вот моя форма

= form_for @post, url: posts_path, html: { multipart: true } do |f| = f.select :taxonomy_ids, @categories.map { |c| [c.name, c.id] }, {}, class: 'form-control'

EDIT 2: Я добавил accepts_nested_attributes_for к моей заботе, так как он:

module Taxonomable include do has_many :taxonomies, as: :taxonomable, dependent: :destroy accepts_nested_attributes_for :taxonomies end
end

а затем использовать fields_for в моей форме:

= f.fields_for :taxonomies_attributes do |taxo| = taxo.label :term_id, 'Categories' = taxo.select :term_id, @categories.map { |c| [c.name, c.id] }, {}, class: 'form-control'

При отправке формы я получаю ее:

"post"=>{"type"=>"blog", "taxonomies_attributes"=>{"term_id"=>"2"}, "reference"=>"TGKHLKJ-567TYGJGK", "name"=>"My super post"

Однако, когда сообщение было успешно сохранено, ассоциации не являются. Есть идеи???

ИЗМЕНИТЬ 3: В моем контроллере я добавил следующее:

def post_params params.require(:post).permit( taxonomies_attributes: [:term_id] )
end

При отправке формы у меня появляется следующая ошибка:

no implicit conversion of Symbol into Integer

Согласно этой записи Rails 4 вложенной формы - не подразумевается преобразование символа в Integer, потому что я использую taxonomies_attributes в своих fields_for как:

= f.fields_for :taxonomies_attributes do |taxo|

Однако, если я удалю его:

= f.fields_for :taxonomies do |taxo|

Блок ничего не отображает, кроме обрезания div:

<div> <!-- Should be display here but nothing -->
</div>

EDIT 4: Наконец, это сработает. Тот факт, что окно выбора не показывалось, @post тем, что при создании нового ресурса мой @post не имеет таксономий. Выполнение следующего исправления, которое:

def new @product = current_user.products.new category = @product.taxonomies.build
end

Спасибо всем

1 ответ

Я не уверен, полностью ли я понимаю ваш вопрос, но одна вещь, которую я заметил, это то, что вам не нужно сохранять в два шага.

Просто добавьте следующую строку в модуль Taxonomable (Rails 3)

attr_accessible :taxonomies_attributes
accepts_nested_attributes_for :taxonomies

Если вы используете Rails 4, добавьте только accepts_nested_attributes_for в ваш модуль Taxonomable и каждый из контроллеров, убедитесь, что атрибуты таксономий разрешены. Например, в вашем PostsController добавьте следующее к вашему

def post_params params.require(:post).permit(:name, taxonomies_attributes: [:name]) end

Ваше создание изменится на:

def create @post = current_user.posts.new( post_params ) if @post.save redirect_to posts_path else render :new end
end

Это предполагает, что ваша форма использует правильное вложение через fields_for Я не уверен в этом, поскольку вы не опубликовали код формы.

licensed under cc by-sa 3.0 with attribution.