2013-09-27 5 views
0

Я фактически создаю систему таксономии в своем приложении. Вот моя таблица схема:Лучшая практика 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 в моей форме. Это кажется грязным, и я хотел, чтобы ваша точка зрения не позволяла так взломать.

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

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

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

EDIT:
Вот моя форма

= 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" 

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

EDIT 3:
В мой контроллер, я добавил это:

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

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

no implicit conversion of Symbol into Integer 

Согласно этому сообщению Rails 4 nested form - no implicit conversion of Symbol into Integer, это потому, что я использую taxonomies_attributes в своих fields_for как:

= f.fields_for :taxonomies_attributes do |taxo| 

Однако, если удалить его:

= f.fields_for :taxonomies do |taxo| 

Блок не отображает ничего, кроме DIV оберточной его:

<div class="form-group"> 
    <!-- Should be display here but nothing --> 
</div> 

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

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

спасибо всем

+0

Что вы хотите сказать? – tyler

+0

Извините, если я не понял. Я хотел бы знать, есть ли лучший способ сохранить эту полиморфную ассоциацию? Спасибо – lkartono

ответ

2

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

Просто добавьте следующую строку в 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 - Я не уверен, что, поскольку вы не опубликовали код формы.

+0

Привет, спасибо за ваш ответ. Я думаю, что я близок к тому, чего хочу достичь. Тем не менее, я все еще запутался в 'fields_for'. Я редактировал свой пост, добавляя свою фактическую форму. Если бы вы могли объяснить более подробно, это было бы потрясающе. Спасибо – lkartono

+0

Извините, забыли добавить 'attr_accessible: taxonomies_attributes' раньше –

+0

Что делать, если я использую рельсы 4? мне нужно использовать камень для этого или есть трюк? thank – lkartono

Смежные вопросы