Crear datos en bases de datos adicionales en una aplicación de Rails.
En mi aplicación de Rails (versión 6.1.3.2) tengo 2 bases de datos:
1. Primary, para la mayoría de modelos.
2. Api_logs, para el modelo ApiLog
.
Mi archivo database.yml
se ve así:
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
Además, mi modelo ApiLog
tiene la siguiente migración:
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
Ambas bases de datos fueron creadas y migradas exitosamente. Además, en mi app/models/api_log.rb
tengo la siguiente declaración:
“`class ApiLog < ApplicationRecord
self.table<em>name = 'api</em>logs'
self.abstract_class = true
connects_to database: { writing: :api_logs, reading: :api_logs }
end
<pre><code><br />Con esto puedo ejecutar consultas de lectura como:
</code></pre>
irb(main):002:0> ApiLog.first
ApiLog Load (1.6ms) SELECT "api<em>logs".* FROM "api</em>logs" ORDER BY "api<em>logs"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> nil
irb(main):003:0> ApiLog.count
(2.1ms) SELECT COUNT(*) FROM "api</em>logs"
=> 0
<pre><code><br />Pero cuando intento crear uno:
</code></pre>
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.)
<pre><code><br />Entiendo que el error se debe a que esto es una clase abstracta debido a la declaración en el modelo. Sin embargo, si elimino <code> self.abstract_class=true </code>, incluso <code> ApiLog.count </code> deja de funcionar:
</code></pre>
irb(main):001:0> ApiLog.count
Traceback (most recent call last):
3: from (irb):1
2: from app/models/api_log.rb:3:in <code><main>'
1: from app/models/api_log.rb:7:in</code><class:ApiLog>'
NotImplementedError (<code>connects_to</code> can only be called on ActiveRecord::Base or abstract classes)
“`
He seguido la guía de Rails y no parece funcionar, aunque las consultas de lectura están bien.
Entonces, ¿cómo creo objetos api_logs
en la nueva base de datos?
¡Gracias!
davy.ai
Para poder crear objetos en la base de datos
api_logs
, es necesario eliminar la declaraciónself.abstract_class = true
del modeloApiLog
. Esta declaración convierte aApiLog
en una clase abstracta y, por lo tanto, no se puede instanciar.Sin embargo, eliminar
self.abstract_class = true
también hace que el métodoconnects_to
falle cuando se utiliza fuera deActiveRecord::Base
o de clases abstractas. Para solucionar esto, se puede hacer queApiLog
herede deActiveRecord::Base
.Por lo tanto, el archivo
app/models/api_log.rb
debería verse así:Con esto, debería ser posible crear objetos
ApiLog
en la base de datosapi_logs
.