2015-06-10 6 views
0

У меня есть несколько вложенных классов, которые выглядят примерно так:Как получить атрибуты из has_one ассоциации без own_to?

class Presentation < ActiveRecord::Base 
    has_many :campaign_records, :as => :campaignable 

    def campaign_records_text(joiner) 
    return '' if self.campaign_records.blank? 
    self.campaign_records.map {|c| c.to_s}.join(joiner) 
    end 
end 

class CampaignRecord < ActiveRecord::Base 
    belongs_to :campaignable, :polymorphic => true 
    has_one :campaign 
    has_one :tier_one 
    has_one :tier_two 

    def to_s 
    "#{campaign.name} - #{tier_one.name} - #{tier_two.name}" 
    end 
end 

class Campaign < ActiveRecord::Base 
    has_many :tier_ones 

    attr_accessible :name 
end 

class TierOne < ActiveRecord::Base 
    has_many :tier_twos 
    belongs_to :campaign 

    attr_accessible :name 
end 

class TierTwo < ActiveRecord::Base 
    belongs_to :tier_one 

    attr_accessible :name 
end 

В резюме, имеется Campaign имеет много связано TierOne с и каждый TierOne имеет собственный набор TierTwo с. A Presentation имеет набор CampaignRecord s, который связывает Campaign, TierOne и TierTwo вместе. Обратите внимание, что Campaignне принадлежит_ a CampaignRecord, потому что многие CampaignRecord s могут ссылаться на него.

Так вот проблема: я хочу изменить метод CampaignRecord.to_s вернуть «campaign.name - tier_one.name - tier_two.name» (как показано выше), но делать это приводит к ошибке, когда я пытаюсь вызвать some_campaign_record.to_s:

ActionView::Template::Error (Mysql2::Error: Unknown column 'campaigns.campaign_record_id' in 'where clause': SELECT 'campaigns'.* FROM 'campaigns' WHERE 'campaigns'.'campaign_record_id' = # LIMIT 1)

Где я здесь ошибся? Я знаю, что rails auto генерирует много геттеров и сеттеров для меня, но метод to_s по умолчанию является обычным, так как я могу переопределить его в правильном режиме рельсов? Требуется ли has_onebelongs_to или есть belongs_to_many, где-то там, где я должен был использовать?

Любая помощь будет очень признательна! Заранее спасибо!

(Кроме того, я увидел, что мой вопрос очень похож на this unanswered question)

EDIT

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

Во-первых, только для того, чтобы быть ясным Campaign является очень отличается от CampaignRecord.

Think отношений кампании-TierOne-TierTwo как трехслойного списка:

  1. кампании 1
    • TierOne 1,1
      • TierTwo 1.1.1
      • TierTwo 1.1.2
      • ...
    • TierOne 1,2
      • TierTwo 1.2.1
      • TierTwo 1.2.2
      • ...
    • ...
  2. Кампания 2
    • TierOne 2,1
      • TierTwo 2.1.1
      • TierTwo 2.1.2
      • ...
    • TierOne 2,2
      • TierTwo 2.2.1
      • TierTwo 2.2.2
      • ...
    • ...
  3. кампании 3 ...

Модель CampaignRecord является представление кампании, TierOne, TierTwo. Когда он будет создан первым, вы выбираете кампанию. Затем выберите TierOne из набора TierOnes этой кампании. Затем TierTwo из набора TierOne от TierTwos. Другими словами, модель CampaignRecord - это путь, который пересекает дерево Campaign-TierOne-TierTwo.

Набор presentation.campaign_records представляет собой набор допустимых путей Campaign-TierOne-TierTwo, которые пользователь ранее связывал с этим экземпляром презентации. (Презентация будет иметь ноль или более из этих путей, связанных с ней.)

Важным компонентом функциональности является то, что презентация должна иметь набор связей Campaign-TierOne-TierTwo с переменным размером. Модифицируя любую презентацию, мне нужно иметь возможность изменять/добавлять/удалять ссылки Campaign-TierOne-TierTwo в/из презентации. Я решил представить те соединения Campaign-TierOne-TierTwo как CampaignRecords. Презентация может иметь кучу этих CampaignRecords, но ни одна из кампаний, TierOne или TierTwo никогда не будет belong_to a CampaignRecord.

Итак, мой вопрос становится: Почему моя модель Campaign выбрасывает ошибку «не могу найти указанный столбец», когда она никогда не должна была искать этот столбец в первую очередь?

@presentations = Presentations.all 
@presentations.each do |presentation| 
    presentation.campaign_records.each do |campaign_record| 
     print campaign_record.to_s # Campaign model throws error here 
    end 
end 
+0

я думаю, что '.to_s' это ваш метод и вы входом в инстанс называют это ом классе. –

+0

Итак, одна ошибка, которую я вижу (но, похоже, не относится к сообщению об ошибке, которое вы указали), заключается в том, что Кампания ожидает найти TierTwo с campaign_id. Можете ли вы подтвердить, что модель TierTwo имеет campaign_id? –

+0

@ LannyBose: Нет, модель TierTwo не имеет campaign_id. – ianking

ответ

0

На основании приведенных выше замечаний, одна ошибка я вижу следующее:

class CampaignRecord < ActiveRecord::Base 
    ... 
    has_one :tier_two 
    ... 
end 

Посмотрите на Rails Guide on Associations.. Кампания ожидает увидеть campaign_record_id в любой модели ActiveRecord, которая имеет has_ ​​что-то.

Лучше всего, чтобы вы захотели добавить эту колонку в базу данных TierTwo.

В качестве альтернативы, если каждый CampaignRecord TierTwo можно судить по его TierOne, вы можете также гипотетически сделать:

class CampaignRecord < ActiveRecord::Base 
    ... 
    has_many :tier_twos, through: :tier_one 
    ... 
end 

Однако, это не кажется правильным вариантом.Вы говорите, что у CampaignRecord есть только один TierTwo, и TierOne может иметь много TierTwos.

Дайте мне знать, если это поможет. Возможно, мне не хватает информации о вашей бизнес-логике, которая помогла бы прояснить мою рекомендацию.

+0

Проверьте изменения, которые я только что добавил. Я думаю, что я не совсем понял, как все работает вместе в моем оригинальном посте. Редакции, надеюсь, прояснят это. – ianking

+0

Ahhhh ... это делает его намного яснее, и теперь я лучше понимаю, какие модели нужно тщательно изучать. Благодаря! Итак, одна проблема в вашем редактировании заключается в том, что ДА, он должен искать этот столбец. Когда в вашей модели CampaignRecord вы вызываете campaign.to_s, отношение has_one означает, что оно просматривает кампанию. Можете ли вы показать мне свой schema.rb, чтобы подтвердить его присутствие? –

+0

Выяснил это. Я отправлю код позже, когда я нахожусь в офисе. Просто нужно было использовать 'belongs_to' в CampaignRecord вместо' has_one'. – ianking

0

Решение кажется довольно очевидным для меня сейчас, оглядываясь назад. Моя модель CampaignRecord имела поля для хранения идентификаторов других записей модели. Но has_one в CampaignRecord подразумевает, что другие модели должны хранить идентификатор CampaignRecord. Решение было изменить has_one с до belongs_to с, так что поиск идет в другом направлении:

class CampaignRecord < ActiveRecord::Base 
    belongs_to :campaignable, :polymorphic => true 
    belongs_to :campaign 
    belongs_to :tier_one 
    belongs_to :tier_two 

    def to_s 
    "#{campaign.name} - #{tier_one.name} - #{tier_two.name}" 
    end 
end