Доступ к таблице в Ruby on Rails через отношения - PullRequest
0 голосов
/ 05 августа 2011

Я пытаюсь создать систему инвентаризации для различных серверов и приложений, которые у нас есть.У меня есть следующие таблицы / Модели:

  • Приложение (Приложение)
  • Сервер (Сервер)
  • Среда (Рабочая среда)

а затем у меня также есть таблица соединения, которая содержит информацию для сервера и приложений, называемую «AppServer».

Вот изображение диаграммы ER (Извините, я новичок, поэтому не могупока что картинки пока нет)

Диаграмма ER

Пунктирные линии между App-> Environment и Server-> Environment являются косвенными связями, т.е. проходят через AppServer.Не самая лучшая диаграмма ER, но я попытался прояснить ее.

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

Модель приложения:

class App < ActiveRecord::Base
  has_and_belongs_to_many :servers
  has_one :app_server
  has_one :environment, :through => :app_servers
end

Модель сервера:

class Server < ActiveRecord::Base
  has_and_belongs_to_many :apps
  has_one :app_server
  has_one :environment, :through => :app_servers
end

Модель среды:

class Environment < ActiveRecord::Base
  belongs_to :app_server
end

Модель сервера приложений:

class AppServer < ActiveRecord::Base
  has_one :environment
  belongs_to :server
  belongs_to :app
end

Пока все в порядке, я могу получить доступ кМодель AppServer 'из' App 'и из' Server 'с помощью этой команды в консоли ruby ​​IRB:

exampleApp.app_server
exampleServer.app_server

irb(main):183:0> exampleApp.app_server
=> #<AppServer app_id: 1, server_id: 1, environment_id: nil>
irb(main):184:0> exampleServer.app_server
=> #<AppServer app_id: 1, server_id: 1, environment_id: nil>

Проблема заключается в том, что если я пытаюсь увидеть список серверов или приложений, например, выполнив

irb(main):188:0> exampleServer.apps

Я получаю следующую ошибку

irb(main):188:0> exampleServer.apps
ActiveRecord::StatementInvalid: Could not find table 'apps_servers'
    from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.0.9/lib/active_record/connection_adapters/sqlite_adapter
.rb:295:in `table_structure'
    from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.0.9/lib/active_record/connection_adapters/sqlite_adapter
.rb:186:in `columns'
    from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.0.9/lib/active_record/reflection.rb:230:in `columns'
    from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.0.9/lib/active_record/associations/has_and_belongs_to_ma
ny_association.rb:23:in `columns'
    from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.0.9/lib/active_record/associations/has_and_belongs_to_ma
ny_association.rb:9:in `initialize'
    from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.0.9/lib/active_record/associations.rb:1483:in `new'
    from C:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.0.9/lib/active_record/associations.rb:1483:in `block in
collection_reader_method'
    from (irb):188
    from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/commands/console.rb:44:in `start'
    from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/commands/console.rb:8:in `start'
    from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties3.0.9/lib/rails/commands.rb:23:in   `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

То же самое, когда я пробую

irb(main):189:0> exampleApp.servers

Забавно, у меня уже есть таблица с именем app_servers', не' apps_servers ', и даже когда я попробовал это, я получил другие ошибки.В любом случае, теперь, проверяя, работают ли эти отношения, я позволю коду говорить сам за себя:

irb(main):193:0> exampleServer.app_server.app
=> #<App id: 1, name: "Test App", description: "This is a test applicaiton", status: "Not deployed", created_at: "2011-0
8-05 09:47:53", updated_at: "2011-08-05 09:47:53">
irb(main):194:0> exampleServer.app_server.server
=> #<Server id: 1, name: "Test Server", locationID: nil, osID: nil, type: nil, comments: "This is just a testing server", 
costCentreID: nil, serverStartDate: nil, serverDecommissionDate: nil, created_at: "2011-08-05 09:50:40", updated_at: "
2011-08-05 09:50:40">

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

irb(main):192:0> exampleServer.app_server.environment
=> nil
irb(main):196:0> exampleApp.app_server.environment
=> nil

Поэтому попытка связать его с моделью среды с именем exampleEnvironment, которая была создана, также бесполезна, так как код покажет

irb(main):006:0> exampleApp.app_server.environment << exampleEnvironment
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.<<
        from (irb):6
        from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/commands/console.rb:44:in `start'
        from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/commands/console.rb:8:in `start'
        from C:/Ruby192/lib/ruby/gems/1.9.1/gems/railties-3.0.9/lib/rails/commands.rb:23:in `<top (required)>'
        from script/rails:6:in `require'
        from script/rails:6:in `<main>'

Если вам, ребята, нужна дополнительная информация (котораяЯ сомневаюсь из всего этого длинного текста [Извините (^^)]), дайте мне знать.

Итак, мои вопросы: мои отношения неправильные или в моем коде чего-то не хватает?Все, что я хочу сделать, это сказать:

exampleServer.apps #Answer will show the linked app
exampleApp.servers #Answer will show the linked server
exampleServer.environment #Answer will show the linked environment through app_server
or
exampleServer.app_Server.environment #Answer will show the linked environment

Ваша помощь очень ценится, и я прошу прощения за этот неоправданный вопрос.Заранее спасибо d (-_-) b

Ответы [ 3 ]

3 голосов
/ 05 августа 2011

Возможно, я неверно истолковал вашу диаграмму ER, но кажется, что Приложения, Серверы и Среды являются независимыми объектами, а AppServer представляет собой уникальную комбинацию одного из трех.Следующее основано на этом предположении.

В этом случае AppServer является моделью соединения для трех других моделей.Это отношение в Rails обычно моделируется следующим образом:

class App < ActiveRecord::Base
  has_many :app_servers
  has_many :servers, :through => :app_servers
  has_many :environments, :through => :app_servers
end

class Server < ActiveRecord::Base
  has_many :app_servers
  has_many :apps, :through => :app_servers
  has_many :environments, :through => :app_servers
end

class Environment < ActiveRecord::Base
  has_many :app_servers
  has_many :apps, :through => :app_servers
  has_many :servers, :through => :app_servers
end

class AppServer < ActiveRecord::Base
  belongs_to :app
  belongs_to :server
  belongs_to :environment
end

Это должно позволить вам выполнить все запросы, которые вы упомянули в своем вопросе.

Хороший способ решить, какие отношения кМежду вашими моделями стоит посмотреть, какие таблицы будут содержать внешний ключ.Так как AppServer содержит app_id, например, это belongs_to и App.Следовательно, приложение has_many или has_one AppServer.

Еще одна вещь, которую стоит отметить, это то, что has_many :through почти всегда предпочтительнее, чем has_and_belongs_to_many.Это позволяет вам явно определить модель соединения и сделать ее настолько гибкой, насколько вам нужно.В этом случае вам потребовалась модель соединения для трех таблиц, поэтому has_and_belongs_to_many значение по умолчанию для двух таблиц не будет соответствовать вашим потребностям.

0 голосов
/ 05 августа 2011

После проверки вашего ERD, я думаю, что знаю проблему.

Rails предпочитает соглашение по конфигурации. Итак, когда вы говорите Rails, что модель вашего приложения

has_one :app_server

, ожидается, что ваша таблица app_server имеет app_id . В вашем ERD я видел, что у вас appID в качестве имени поля.

Если вы попытаетесь соответствующим образом изменить внешние ключи во всех таблицах, при необходимости установите app_id , server_id , environment_id и т. Д. При необходимости, я уверен, что вы найдете все работает отлично.

0 голосов
/ 05 августа 2011

Это для первой проблемы.

irb(main):188:0> exampleServer.apps
ActiveRecord::StatementInvalid: Could not find table 'apps_servers'

- Вам нужна промежуточная таблица много-на-май, которая называется 'apps_servers' (имя условно).

- Таблица будет содержать два столбца с именами 'app_id' / integer, 'server_id' / integer.Значения этих столбцов - это значение первичного ключа строки приложения и строки сервера, которые должны быть связаны.

Ознакомьтесь с руководством Rails по ассоциациям многие-ко-многим (HABTM).http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_and_belongs_to_many

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

...