1

既存のカードモデルの「タイムライン」機能を作成したいと思います。カードにはすでにhas_manyNotesとhas_manyAttachmentsがあります。次のことができるようになりたい:

  • card.timelineのような優れた方法で、統合されたコレクション内のメモ、添付ファイル(および最終的には他のモデル)にアクセスします。
  • 引き続き、card.notesのようなカードのメモや添付ファイルにアクセスできます。
  • 引き続き、note.cardのようなメモの親カードにアクセスできます。
  • 次のようなAPIを使用して、カードのタイムラインにアイテムを追加できます。card.timeline << note

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

4

1 に答える 1

0

わかりました-これでオンとオフに苦労した後、stackoverflowに投稿してから10分以内にクラックします!典型的な。

他の人が壁に頭をぶつけないようにするために、私が間違っていたのは次のとおりです。

注は次のようになっているはずです。

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

そしてそれはそれでした!この記事で使用した作成方法を使用しようとしましたが、実際には必須ではありません。

これがコンソール出力で、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

編集:

card.timelineを持つという私の要件がまだ満たされていないことに気づきました。結合は複数のテーブルから行われているため、ARに結合を処理させることができませんでした(理想的には、* card.timeline_items.join(:notes、:attachments)*でうまくいくはずです)。

これを解決するために、カードクラスに次のメソッドを追加しました。

  def timeline
    (self.notes + self.attachments).sort { |a,b| a.updated_at <=> b.updated_at }
  end
于 2012-09-07T12:04:24.867 に答える