Rails has_many / has_one той же модели - PullRequest
2 голосов
/ 04 марта 2011

Итак, у меня есть две модели, Коллекция и Папка.

Внутри каждой Коллекции есть одна корневая папка.Все папки принадлежат Коллекции, но также могут быть вложены друг в друга.

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

class Folder < ActiveRecord::Base
  has_one :master_collection, :class_name => 'Collection', :foreign_key => :root_folder_id
  belongs_to :collection
  belongs_to :parent, :class_name => 'Folder'
  has_many :subfolders, :class_name => 'Folder', :foreign_key => :parent_id
  ...
end

class Collection < ActiveRecord::Base
  belongs_to :root_folder, :class_name => 'Folder'
  has_many :folders

  after_create :setup_root_folder

  private
  def setup_root_folder
    self.root_folder = Folder.create(:name => 'Collection Root', :collection => self )
  end
end

В папках у меня есть столбцы: parent_id, folder_id В коллекциях у меня есть столбец: root_folder_id

Кажется, что это должно работать, но я получаю странное поведение в консоли:

ruby-1.9.2-p0 :001 > c = Collection.create(:name=>"Example")
 => #<Collection id: 6, name: "Example", ...timestamps..., root_folder_id: 8> 
ruby-1.9.2-p0 :003 > f = c.root_folder
 => #<Folder id: 8, parent_id: nil, name: "Collection Root", ...timestamps..., collection_id: 6> 
ruby-1.9.2-p0 :004 > f.master_collection
 => nil 

Итак, очевидно, что ассоциация работает на стороне сбора, но корневая папка не может найтиколлекция, в которой он находится, хотя внешний ключ доступен, и ActiveRecord не вызывает никаких ошибок при использовании ассоциации ...

Есть идеи?

1 Ответ

2 голосов
/ 04 марта 2011

Я подозреваю, что это то, что происходит:

  1. Вы создаете коллекцию C
  2. C сохраняется в базе данных
  3. Rails вызывает C.after_create
  4. Вы создаете папку F
  5. F сохраняется в базе данных
  6. C root_folder_id имеет значение F id
  7. Это изменение НЕ сохраняетсяв базу данных
  8. Вы звоните F.master_collection
  9. F, запрашивает базу данных, ищет Коллекции с coleections.root_folder_id = folders.id
  10. , так как новый C root_folder_id не имеетбыл сохранен, F ничего не находит

Если вы хотите проверить это, наберите c.save в вашем примере кода, прежде чем вызывать f.master_collection - и вы должны получить коллекцию, как вы ожидаете(вам может понадобиться и f.reload).

Тем не менее, мне никогда не нравились двойные belongs_to s (Папка принадлежит_Коллекция + Коллекция принадлежит_Корневая_папка).Вместо этого я бы порекомендовал:

class Collection < ActiveRecord::Base
    has_one :root_folder, :class_name => 'Folder', :conditions => {:parent_id => nil}

    # ...other stuff...
end

Надеюсь, что это поможет!

PS: Ваше определение Folder.master_collection вернет вам коллекцию, только если вы позвонитеэто из корневой папки - все остальные папки будут просто возвращать ноль, так как ни одна коллекция не имеет root_folder_id s, которые указывают на них.Это то, что вы хотели?

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