Использование before_create в Rails для нормализации таблицы многие ко многим - PullRequest
0 голосов
/ 29 декабря 2010

Я работаю над довольно стандартной реализацией тегов для таблицы рецептов.Между рецептами и тегами существует много-много взаимосвязей, поэтому таблица тегов будет нормализована.Вот мои модели:

class Recipe < ActiveRecord::Base
    has_many :tag_joins, :as => :parent
    has_many :tags, :through => :tag_joins
end

class TagJoin < ActiveRecord::Base
    belongs_to :parent, :polymorphic => true
    belongs_to :tag, :counter_cache => :usage_count
end

class Tag < ActiveRecord::Base
    has_many :tag_joins, :as => :parent
    has_many :recipes, :through => :tag_joins, :source => :parent
        , :source_type => 'Recipe'


    before_create :normalizeTable
    def normalizeTable
        t = Tag.find_by_name(self.name)
        if (t) 
            j = TagJoin.new
            j.parent_type = self.tag_joins.parent_type
            j.parent_id = self.tag_joins.parent_id
            j.tag_id = t.id
            return false
        end
    end
end

Последний бит, обратный вызов before_create, это то, что я пытаюсь заставить работать.Моя цель состоит в том, чтобы в случае попытки создать новый тег с тем же именем, что и имя в таблице, создается только одна строка в объединяемой таблице с использованием существующей строки в тегах.В настоящее время код умирает с:

undefined method `parent_type' for #<Class:0x102f5ce38>

Есть предложения?

Изменить

Вот и мои таблицы:

create_table "recipes", :force => true do |t|
    t.string   "name"
    t.text     "abstract",   :limit => 255
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
end

create_table "tag_joins", :force => true do |t|
    t.string   "parent_type"
    t.integer  "parent_id"
    t.integer  "tag_id"
    t.datetime "created_at"
    t.datetime "updated_at"
end

create_table "tags", :force => true do |t|
    t.string   "name"
    t.boolean  "is_featured"
    t.integer  "usage_count"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "category"
end

Ответы [ 2 ]

1 голос
/ 29 декабря 2010

Я не понимаю, как это может работать. Если вы добавите тег через связь, он будет создан перед строкой таблицы соединений. Кроме того, обратный вызов пытается получить parent_type коллекции, что не имеет смысла.

Полагаю, вы хотите что-то вроде этого:

r1 = Recipe.create
r1.tags.create("chili") # tag is created

r2 = Recipe.create
r2.tags.create("chili") # existing tag is used

Вы можете эмулировать это, определив метод в рецепте:

  def add_tag(tag_name)
    tags << Tag.find_or_create_by_name(tag_name)
  end

И вызывать его вместо .tags.create:

r1 = Recipe.create
r1.add_tag("chili") # tag is created

r2 = Recipe.create
r2.add_tag("chili") # existing tag is used
0 голосов
/ 29 декабря 2010

Должно ли это быть source_type вместо parent_type? Так как мы не знаем точно, какие столбцы вы указали в tag_joins, я предпочитаю. Похоже, Rails не думает, что столбец существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...