通过关系访问 Ruby on Rails 中的表

发布于 2024-11-28 03:44:09 字数 5235 浏览 7 评论 0原文

我正在尝试为我们拥有的各种服务器和应用程序构建一个库存系统。我有以下表格/模型:

  • 应用程序(应用程序)
  • 服务器(服务器)
  • 环境(工作环境)

,然后我还有一个连接表,其中保存服务器和应用程序的信息,称为“AppServer”。

这是 ER 图的图片(抱歉,我是新人,所以还不能发布图片)

ER图

App->Environment和Server->Environment之间的虚线是间接连接,即经过AppServer。 不是最好的 ER 图,但我试图说清楚。

所以现在我创建的用于连接各个表的 ruby​​ 代码如下:

应用程序模型:

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

到目前为止一切似乎都很好,我可以从“应用程序”和“服务器”访问“应用程序服务器”模型' 通过在 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

I'm trying to build an inventory system for the various servers and apps we have. I have the following tables/Models:

  • App (Application)
  • Server (Server)
  • Environment (Working environment)

and then I also have a join table which holds the information for the server and apps, called "AppServer".

Here is a picture of the ER Diagram (Sorry, I'm new so I can't post pictures yet)

ER Diagram

The dotted lines between App->Environment and Server->Environment are indirect connections, i.e. going through AppServer.
Not the best ER Diagram but I tried to make it clear.

So now the ruby code I created to connect the various tables is as follows:

App Model:

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

Server Model:

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

Environment Model:

class Environment < ActiveRecord::Base
  belongs_to :app_server
end

AppServer Model:

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

Everything seems ok so far, I can access the 'AppServer' model from 'App' and from 'Server' by using this command in the ruby IRB console:

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>

The problem is that if I try to see a list of servers or apps for instance by doing

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

I get the following error

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>'

Same thing when I try out

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

Funny thing is, I already have a table called 'app_servers', not 'apps_servers', and even when I tried that out I got other errors.
Anyways, now trying out whether the relationship works, I'll let the code speak for itself:

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">

So that seems fine, however doing the following will give me a nil answer:

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

So trying to link it to an environment model called 'exampleEnvironment' which was instantiated, is also of no use, as the code will show

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>'

If you guys need any more info (Which I doubt from all this long text[Sorry (^^)]), let me know.

So my questions are, is my relationship wrong or is there something missing from my code?
All I want to be able to do is say

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

Your help is greatly appreciated, and apologies for this looooooong question.
Thanks in advance d(-_-)b

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

动听の歌 2024-12-05 03:44:09

我可能误解了您的 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_manyhas_one AppServer。

另一件需要注意的事情是 has_many :through 几乎总是优于 has_and_belongs_to_many。它允许您显式定义连接模型并使其像您希望的那样灵活。在本例中,您需要三个表的联接模型,因此两个表的 has_and_belongs_to_many 默认值无法满足您的需求。

I may have misinterpreted your ER diagram, but it seems that Applications, Servers, and Environments are all independent entities, and an AppServer is a unique combination of one each of the three. The following is based on that assumption.

In this case, AppServer is the join model for the other three models. This relationship in Rails is usually modeled like this:

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

This should allow you to do all the queries you mentioned in your question.

A good way to decide what kind of relationships to have between your models is to look at which tables will hold the foreign key. Since AppServer holds a app_id, for example, it belongs_to and App. An App therefore has_many or has_one AppServer.

Another thing to note is that has_many :through is almost always preferred to has_and_belongs_to_many. It allows you to explicitly define the join model and make it as flexible as you'd like. In this case, you needed a join model for three tables, so the has_and_belongs_to_many default of two tables wouldn't meet your needs.

女皇必胜 2024-12-05 03:44:09

这是针对第一个问题。

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

-您需要一个名为“apps_servers”的中间多对多表(名称按照约定)。

- 该表将包含两列,名称为“app_id”/整数、“server_id”/整数。这些列的值是应用程序行和要链接的服务器行的主键值。

请查找有关多对多关联 (HABTM) 的 Rails 指南。
http://api.rubyonrails.org/classes/ActiveRecord /Associations/ClassMethods.html#method-i-has_and_belongs_to_many

希望有帮助。

This is for the first problem.

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

-You need an intermediate many-to-may table called 'apps_servers' (name is by convention).

-The table will contain two columns with names 'app_id'/integer, 'server_id'/integer. The values of these columns are the primary key value of app row, and server row that is to be linked.

Please lookup Rails guide on many-to-many associations (HABTM).
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_and_belongs_to_many

Hope it helps.

乖乖 2024-12-05 03:44:09

检查完你的 ERD 后,我想我知道问题所在了。

Rails 更喜欢约定而不是配置。因此,当您告诉 Rails 您的应用程序模型

has_one :app_server

时,预计您的 app_server 表具有 app_id。在您的 ERD 中,我看到您将 appID 作为字段名称。

如果您尝试相应地更改所有表中的外键,并在必要时设置 app_idserver_idenvironment_id 等,我确信你会发现一切都很完美。

After checking your ERD, I think I know the problem.

Rails favors convention over configuration. So, when you tell Rails that your App model

has_one :app_server

,it is expected that your app_server table has app_id. In your ERD, I saw you had appID as the field name.

If you try changing the foreign keys in all the tables accordingly, setting, app_id, server_id, environment_id, etc. whenever necessary, I am sure that you will find everything working perfectly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文