在 Rails 应用程序的其他数据库中创建数据
Create data in additional databases in Rails application
在我的rails(版本 6.1.3.2)应用程序中,我有 2 个数据库:
- 主要,适用于大多数型号
- api_logs,对于
ApiLog
模型
我的 database.yml
看起来像:
development:
primary:
<<: *default
database: <%= ENV["DB_NAME"] || 'jspro_development' %>
host: <%= ENV["DB_HOST"] || 'localhost' %>
username: <%= ENV["DB_USERNAME"] || 'postgres' %>
password: <%= ENV["DB_PASSWORD"] || 'postgres' %>
port: <%= ENV["DB_PORT"] || '5432' %>
api_logs:
<<: *default
database: <%= ENV["API_LOGS_DB_NAME"] || 'api_logs_development' %>
host: <%= ENV["API_LOGS_DB_HOST"] || 'localhost' %>
username: <%= ENV["API_LOGS_DB_USERNAME"] || 'postgres' %>
password: <%= ENV["API_LOGS_DB_PASSWORD"] || 'postgres' %>
port: <%= ENV["API_LOGS_DB_PORT"] || '5432' %>
migrations_paths: db/api_logs
我的 ApiLog
模型有以下迁移:
class CreateApiLogs < ActiveRecord::Migration[6.1]
def change
create_table :api_logs do |t|
t.timestamps
t.string :method
t.string :path
t.string :query_string
t.json :headers, default: {}
t.json :request_body, default: {}
t.string :remote_address
t.string :http_origin
t.integer :response_status
t.string :http_user_agent
t.string :http_referer
t.integer :user_id
t.integer :account_id
t.string :membership_type
t.string :unique_id
end
end
end
数据库已成功创建和迁移。
在我的 app/models/api_log.rb
中,我有以下声明:
# frozen_string_literal: true
class ApiLog < ApplicationRecord
self.table_name = 'api_logs'
self.abstract_class = true
connects_to database: { writing: :api_logs, reading: :api_logs }
end
有了这个,我可以 运行 读取像这样的查询:
irb(main):002:0> ApiLog.first
ApiLog Load (1.6ms) SELECT "api_logs".* FROM "api_logs" ORDER BY "api_logs"."id" ASC LIMIT [["LIMIT", 1]]
=> nil
irb(main):003:0> ApiLog.count
(2.1ms) SELECT COUNT(*) FROM "api_logs"
=> 0
他们很好。
但是当我尝试创建一个时:
irb(main):003:0> ApiLog.count
(2.1ms) SELECT COUNT(*) FROM "api_logs"
=> 0
irb(main):004:0> ApiLog.create(method: 'POST', user_id: 61)
Traceback (most recent call last):
1: from (irb):4
NotImplementedError (ApiLog is an abstract class and cannot be instantiated.)
我知道错误是抱怨这是一个抽象 class 由于模型中的声明。但是,如果我删除 self.abstract_class=true
,即使 ApiLog.count
也不再有效:
irb(main):001:0> ApiLog.count
Traceback (most recent call last):
3: from (irb):1
2: from app/models/api_log.rb:3:in `<main>'
1: from app/models/api_log.rb:7:in `<class:ApiLog>'
NotImplementedError (`connects_to` can only be called on ActiveRecord::Base or abstract classes)
我已经按照 Rails guide 进行操作,但它似乎没有用,即使读取查询很好。
那么如何在新数据库中创建 api_logs
对象?
谢谢!
来自 Rails 指南:
您的问题是,您正试图让一个 class 既充当您的模型,又充当指南所称的 connection 模型。
It's important to connect to your database in a single model and then
inherit from that model for the tables rather than connect multiple
individual models to the same database.
我相信你只需要将你得到的东西分成两个模型:
class LogRecord < ApplicationRecord
self.table_name = 'api_logs'
self.abstract_class = true
connects_to database: { writing: :api_logs, reading: :api_logs }
end
class ApiLog < LogRecord
...
end
读取查询似乎以您所拥有的方式工作的唯一原因是您没有任何匹配的记录,因此结果是 nil
。如果存在现有记录,您会得到与创建相同的错误,因为此问题与 SQL 查询无关,而是与您的 class.
的结果实例化有关
在我的rails(版本 6.1.3.2)应用程序中,我有 2 个数据库:
- 主要,适用于大多数型号
- api_logs,对于
ApiLog
模型 我的database.yml
看起来像:
development:
primary:
<<: *default
database: <%= ENV["DB_NAME"] || 'jspro_development' %>
host: <%= ENV["DB_HOST"] || 'localhost' %>
username: <%= ENV["DB_USERNAME"] || 'postgres' %>
password: <%= ENV["DB_PASSWORD"] || 'postgres' %>
port: <%= ENV["DB_PORT"] || '5432' %>
api_logs:
<<: *default
database: <%= ENV["API_LOGS_DB_NAME"] || 'api_logs_development' %>
host: <%= ENV["API_LOGS_DB_HOST"] || 'localhost' %>
username: <%= ENV["API_LOGS_DB_USERNAME"] || 'postgres' %>
password: <%= ENV["API_LOGS_DB_PASSWORD"] || 'postgres' %>
port: <%= ENV["API_LOGS_DB_PORT"] || '5432' %>
migrations_paths: db/api_logs
我的 ApiLog
模型有以下迁移:
class CreateApiLogs < ActiveRecord::Migration[6.1]
def change
create_table :api_logs do |t|
t.timestamps
t.string :method
t.string :path
t.string :query_string
t.json :headers, default: {}
t.json :request_body, default: {}
t.string :remote_address
t.string :http_origin
t.integer :response_status
t.string :http_user_agent
t.string :http_referer
t.integer :user_id
t.integer :account_id
t.string :membership_type
t.string :unique_id
end
end
end
数据库已成功创建和迁移。
在我的 app/models/api_log.rb
中,我有以下声明:
# frozen_string_literal: true
class ApiLog < ApplicationRecord
self.table_name = 'api_logs'
self.abstract_class = true
connects_to database: { writing: :api_logs, reading: :api_logs }
end
有了这个,我可以 运行 读取像这样的查询:
irb(main):002:0> ApiLog.first
ApiLog Load (1.6ms) SELECT "api_logs".* FROM "api_logs" ORDER BY "api_logs"."id" ASC LIMIT [["LIMIT", 1]]
=> nil
irb(main):003:0> ApiLog.count
(2.1ms) SELECT COUNT(*) FROM "api_logs"
=> 0
他们很好。
但是当我尝试创建一个时:
irb(main):003:0> ApiLog.count
(2.1ms) SELECT COUNT(*) FROM "api_logs"
=> 0
irb(main):004:0> ApiLog.create(method: 'POST', user_id: 61)
Traceback (most recent call last):
1: from (irb):4
NotImplementedError (ApiLog is an abstract class and cannot be instantiated.)
我知道错误是抱怨这是一个抽象 class 由于模型中的声明。但是,如果我删除 self.abstract_class=true
,即使 ApiLog.count
也不再有效:
irb(main):001:0> ApiLog.count
Traceback (most recent call last):
3: from (irb):1
2: from app/models/api_log.rb:3:in `<main>'
1: from app/models/api_log.rb:7:in `<class:ApiLog>'
NotImplementedError (`connects_to` can only be called on ActiveRecord::Base or abstract classes)
我已经按照 Rails guide 进行操作,但它似乎没有用,即使读取查询很好。
那么如何在新数据库中创建 api_logs
对象?
谢谢!
来自 Rails 指南:
您的问题是,您正试图让一个 class 既充当您的模型,又充当指南所称的 connection 模型。
It's important to connect to your database in a single model and then inherit from that model for the tables rather than connect multiple individual models to the same database.
我相信你只需要将你得到的东西分成两个模型:
class LogRecord < ApplicationRecord
self.table_name = 'api_logs'
self.abstract_class = true
connects_to database: { writing: :api_logs, reading: :api_logs }
end
class ApiLog < LogRecord
...
end
读取查询似乎以您所拥有的方式工作的唯一原因是您没有任何匹配的记录,因此结果是 nil
。如果存在现有记录,您会得到与创建相同的错误,因为此问题与 SQL 查询无关,而是与您的 class.