2013-09-25 4 views
0

У меня проблемы с самореференциальной таблицей.self-referential has_many problem

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

я посмотреть на направляющие рельсы, но я coulnd получить его работу

Моя модель:

class Orb < ActiveRecord::Base 
    belongs_to :orb_type 
    has_and_belongs_to_many :books 

    belongs_to :orbit, :class_name => "Orb" 
    has_many :orbs, :class_name => "Orb", :foreign_key => "orb_id" 

    attr_accessible :descr, :nome, :orb_type_id, :book_ids, :orb_id 

    validates :nome, uniqueness: true, presence: true 
end 

Я думаю, что я использую имена плохих отношений (возможно, неправильным образом)

1.9.3-p448 :002 > earth = Orb.find(1) 
    Orb Load (0.2ms) SELECT "orbs".* FROM "orbs" WHERE "orbs"."id" = ? LIMIT 1 [["id", 1]] 
=> #<Orb id: 1, nome: "Terra", descr: "123123", orb_type_id: 1, created_at: "2013-09-25 14:53:35", updated_at: "2013-09-25 14:57:40", orb_id: nil> 
1.9.3-p448 :003 > moon = Orb.find(2) 
    Orb Load (0.2ms) SELECT "orbs".* FROM "orbs" WHERE "orbs"."id" = ? LIMIT 1 [["id", 2]] 
=> #<Orb id: 2, nome: "Lua", descr: "asd", orb_type_id: 2, created_at: "2013-09-25 14:53:46", updated_at: "2013-09-25 14:55:31", orb_id: nil> 
1.9.3-p448 :004 > sun = Orb.find(3) 
    Orb Load (0.2ms) SELECT "orbs".* FROM "orbs" WHERE "orbs"."id" = ? LIMIT 1 [["id", 3]] 
=> #<Orb id: 3, nome: "Sol", descr: "asd", orb_type_id: 3, created_at: "2013-09-25 14:53:55", updated_at: "2013-09-25 14:53:55", orb_id: nil> 
1.9.3-p448 :006 > moon.orbit=earth 
=> #<Orb id: 1, nome: "Terra", descr: "123123", orb_type_id: 1, created_at: "2013-09-25 14:53:35", updated_at: "2013-09-25 14:57:40", orb_id: nil> 
1.9.3-p448 :007 > earth.orbit=sun 
=> #<Orb id: 3, nome: "Sol", descr: "asd", orb_type_id: 3, created_at: "2013-09-25 14:53:55", updated_at: "2013-09-25 14:53:55", orb_id: nil> 
1.9.3-p448 :008 > earth 
=> #<Orb id: 1, nome: "Terra", descr: "123123", orb_type_id: 1, created_at: "2013-09-25 14:53:35", updated_at: "2013-09-25 14:57:40", orb_id: nil> 
1.9.3-p448 :009 > sun 
=> #<Orb id: 3, nome: "Sol", descr: "asd", orb_type_id: 3, created_at: "2013-09-25 14:53:55", updated_at: "2013-09-25 14:53:55", orb_id: nil> 
1.9.3-p448 :010 > moon 
=> #<Orb id: 2, nome: "Lua", descr: "asd", orb_type_id: 2, created_at: "2013-09-25 14:53:46", updated_at: "2013-09-25 14:55:31", orb_id: nil> 

В конце концов ничто не ассоциируется, FK все еще ниль.

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


EDIT:

Теперь все, даже странно. я изменить свою модель на:

class Orb < ActiveRecord::Base 
    belongs_to :orb_type 
    has_and_belongs_to_many :books 

    belongs_to :orbit, :class_name => "Orb" 
    has_many :orbits, :class_name => "Orb", :foreign_key => "orb_id" 

    attr_accessible :descr, :nome, :orb_type_id, :book_ids, :orb_id 

    validates :nome, uniqueness: true, presence: true 
end 

В рельсах консоли (рельсы с) я стараюсь:

1.9.3-p448 :008 > earth = Orb.find(1) 
    Orb Load (0.2ms) SELECT "orbs".* FROM "orbs" WHERE "orbs"."id" = ? LIMIT 1 [["id", 1]] 
=> #<Orb id: 1, nome: "Terra", descr: "", orb_type_id: 1, created_at: "2013-09-25 17:51:26", updated_at: "2013-09-25 18:16:58", orb_id: 3> 
1.9.3-p448 :009 > earth.orbit 
=> nil 
1.9.3-p448 :010 > earth.orbits 
    Orb Load (0.3ms) SELECT "orbs".* FROM "orbs" WHERE "orbs"."orb_id" = 1 
=> [#<Orb id: 2, nome: "Lua", descr: "", orb_type_id: 2, created_at: "2013-09-25 17:51:40", updated_at: "2013-09-25 18:17:31", orb_id: 1>] 
1.9.3-p448 :011 > 

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

1.9.3-p448 :004 > earth.orbits.nome 
NoMethodError: Orb Load (0.4ms) SELECT "orbs".* FROM "orbs" WHERE "orbs"."orb_id" = 1 
undefined method `nome' for #<ActiveRecord::Relation:0x00000003d593c0> 
     from /usr/local/rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.12/lib/active_record/relation/delegation.rb:45:in `method_missing' 
     from /usr/local/rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.2.12/lib/active_record/associations/collection_proxy.rb:100:in `method_missing' 
     from (irb):4 
     from /usr/local/rvm/gems/ruby-1.9.3-p448/gems/railties-3.2.12/lib/rails/commands/console.rb:47:in `start' 
     from /usr/local/rvm/gems/ruby-1.9.3-p448/gems/railties-3.2.12/lib/rails/commands/console.rb:8:in `start' 
     from /usr/local/rvm/gems/ruby-1.9.3-p448/gems/railties-3.2.12/lib/rails/commands.rb:41:in `<top (required)>' 
     from script/rails:6:in `require' 
     from script/rails:6:in `<main>' 

ответ

0

Я понимаю это. Я должен сделать ром в таблице лозы имя отношения (orbit_id) вместо того, чтобы делать это имя таблицы (orb_id)

Крепеж, что все начало работать красиво :)

has_many :orbters, class_name: "Orb", foreign_key: "orbit_id" 
belongs_to :orbit, class_name: "Orb" 
0

Технически, это не здорово, что у вас есть планеты, звезды и луны, все в пределах одной и той же модели. Все они ведут себя по-разному, и каждый должен оправдать свою собственную модель. Например. звезда никогда не будет вращаться вокруг планеты, и планета никогда не будет вращаться вокруг Луны (по определению). Структурируя свою базу данных так, как у вас есть, вы настраиваете себя на поврежденные данные, которые всегда будут выполняться, если вы разрешите это делать.

Если вы должны иметь их все в Orb модели, я бы рекомендовал 2 модели: 1 для Orbs (звезды, планеты, луны), и 1 для Orbits. Orbit класс должен быть по существу таблица так:

Orbit model: 

| id | orbited_id | orbiter_id | 
-------------------------------- 
| 0 | planet_id | moon_id | 
| 1 | star_id | planet_id | 
| 2 | planet_id | moon_id | 
| ...| etc  | etc  | 

И тогда вы можете создать ассоциацию в orb.rb:

has_and_belongs_to_many :orbits, 
         class_name: 'Orb', 
         join_table: :orbits, 
         foreign_key: :orbited_id, 
         association_foreign_key: :orbiter_id, 
         uniq: true 

Это позволит вам делать такие вещи, как

>> sun = Orb.find(1) 
>> sun.orbits 
=> [ <Orb mercury>, <Orb venus>, ..., <Orb pluto> ] 
+0

Я знаю, что я мог бы есть таблица для каждого типа типа, но у меня есть ассоциация orb_type, потому что мне нужно больше, чем только эти 3 типа (астероид подал так далее ...) Причина, по которой я хочу поставить ссылку на себя здесь, состоит в том, что эта таблица уже может содержать все данные, которые я хочу, и я не возражаю, если значение отношения может быть нечетным (например, звезда, вращающаяся вокруг луны) – Techmago

+0

Получил , Вы все равно должны использовать мое предложение и исключить модель «OrbType». Вместо этого вы можете отследить 'orb_type' как столбец в модели' Orb', а затем просто получить все астероиды, выполнив 'Orb.where (orb_type: 'asteroid')' и т. Д. – tyler

+0

Но тогда мне придется жестко задавать все типы при вставке новой orb; p – Techmago