2012-09-07 4 views
1

Я хотел бы создать функцию временной шкалы для существующей модели карты. На Карте уже есть примечания к заметкам и has_many. Я хотел бы быть в состоянии:Rails полиморфная ассоциация, представляющая существующие модели has_many

  • доступа заметка, приложение (и другие модели в конечном счете) в единой коллекции с хорошим методом, как: card.timeline
  • все еще быть в состоянии получить доступ к кардочесальному заметки и вложения, такие как: card.notes
  • все еще быть в состоянии получить доступ к материнской карты записку как: note.card
  • иметь возможность добавлять элементы на временную шкалу карты, с API, как: карты. временная шкала < < примечание

Я думаю, что у меня есть DB настроен правильно, это заявление ассоциации я не могу показаться, чтобы получить право. Вот моя схема:

create_table "cards", :force => true do |t| 
    t.string "name" 
    end 

    create_table "timeline_items", :force => true do |t| 
    t.integer "card_id", :null => false # FK from cards table 
    t.integer "item_id", :null => false # FK from notes or attachments table 
    t.string "item_type", :null => false # either 'Note' or 'Attachment' 
    end 

    create_table "notes", :force => true do |t| 
    t.text  "content" 
    end 

    create_table "attachments", :force => true do |t| 
    t.string "file_file_name" 
    end 

Кто-нибудь знает, как я могу достичь этого, используя ActiveRecord? Это подталкивает меня к мысли!

Отправной точкой является:

class Card < ActiveRecord::Base 
    has_many :timeline_items 
    has_many :notes,  :through => :timeline_items, :source => :item, :source_type => 'Note', :order => 'updated_at DESC' 
    has_many :attachments, :through => :timeline_items, :source => :item, :source_type => 'Attachment', :order => 'updated_at DESC' 
end 

class TimelineItem < ActiveRecord::Base 
    belongs_to :card 
    belongs_to :item, :polymorphic => true 
end 

class Note < ActiveRecord::Base 
    has_one  :card, :through => :timeline_items 
    has_one  :timeline_item, :as => :item 
end 

Заранее спасибо ~ Stu

ответ

0

Хорошо - после борьбы и выключать с этим, я взломать его в 10mins от размещения на StackOverflow! Типичный.

Чтобы спасти других от бьются головой о стену, вот что я имел неправильно:

Примечательным было:

class Note < ActiveRecord::Base 
    has_one  :card, :through => :timeline_item #not timeline_items 
    has_one  :timeline_item, :as => :item 
end 

И что это было! Я пытался использовать методы создания, используемые в this article, но на самом деле это не требуется.

Вот консольный вывод, показывающий, что SQL заявления все с помощью timeline_items таблицы:

1.9.2-p290 :009 > c = Card.find(547) 
    Card Load (0.3ms) SELECT `cards`.* FROM `cards` WHERE `cards`.`id` = 547 LIMIT 1 
=> #<Card id: 547, name: "Duplicates appearing"> 

1.9.2-p290 :010 > c.notes.count 
    (0.3ms) SELECT COUNT(*) FROM `notes` INNER JOIN `timeline_items` ON `notes`.`id` = `timeline_items`.`item_id` WHERE `timeline_items`.`card_id` = 547 AND `timeline_items`.`item_type` = 'Note' 
=> 4 

1.9.2-p290 :011 > c.notes.last.card 
    Note Load (2.7ms) SELECT `notes`.* FROM `notes` INNER JOIN `timeline_items` ON `notes`.`id` = `timeline_items`.`item_id` WHERE `timeline_items`.`card_id` = 547 AND `timeline_items`.`item_type` = 'Note' ORDER BY updated_at ASC LIMIT 1 
    Card Load (3.2ms) SELECT `cards`.* FROM `cards` INNER JOIN `timeline_items` ON `cards`.`id` = `timeline_items`.`card_id` WHERE `timeline_items`.`item_id` = 620 AND `timeline_items`.`item_type` = 'Note' LIMIT 1 
=> #<Card id: 547, name: "Duplicates appearing"> 

1.9.2-p290 :013 > c.notes << Note.new(:content => 'Holee Sheeet Dawg', :user_id => 1) 
    (0.2ms) BEGIN 
    SQL (0.6ms) INSERT INTO `notes` (`content`, `created_at`, `updated_at`, `user_id`) VALUES ('Holee Sheeet Dawg', '2012-09-07 11:38:55', '2012-09-07 11:38:55', 1) 
    (0.1ms) COMMIT 
    (0.1ms) BEGIN 
    SQL (0.3ms) INSERT INTO `timeline_items` (`card_id`, `created_at`, `item_id`, `item_type`, `updated_at`) VALUES (547, '2012-09-07 11:38:55', 625, 'Note', '2012-09-07 11:38:55') 
    (0.5ms) COMMIT 
    Note Load (1.8ms) SELECT `notes`.* FROM `notes` INNER JOIN `timeline_items` ON `notes`.`id` = `timeline_items`.`item_id` WHERE `timeline_items`.`card_id` = 547 AND `timeline_items`.`item_type` = 'Note' ORDER BY updated_at DESC 
=> [#<Note id: 625, content: "Holee Sheeet Dawg", user_id: 1, created_at: "2012-09-07 11:38:55", updated_at: "2012-09-07 11:38:55">, .....] 

1.9.2-p290 :014 > c.notes.count 
    (0.7ms) SELECT COUNT(*) FROM `notes` INNER JOIN `timeline_items` ON `notes`.`id` = `timeline_items`.`item_id` WHERE `timeline_items`.`card_id` = 547 AND `timeline_items`.`item_type` = 'Note' 
=> 5 

EDIT:

Я просто заметил, что мое требование иметь card.timeline WASN Еще нет. Поскольку соединение происходит из нескольких таблиц, я не смог заставить AR обрабатывать соединение для меня (в идеале * card.timeline_items.join (: notes,: attachments) * сделал бы трюк).

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

def timeline 
    (self.notes + self.attachments).sort { |a,b| a.updated_at <=> b.updated_at } 
    end 
+0

Я думаю, что я ответил на здесь :) Спасибо за размещение решение 90% моих собственных вопросов. –

+0

Нет проблем - если я что-то пропустил, дайте мне знать – Stu

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