es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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!

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para poder crear objetos en la base de datos api_logs, es necesario eliminar la declaración self.abstract_class = true del modelo ApiLog. Esta declaración convierte a ApiLog 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étodo connects_to falle cuando se utiliza fuera de ActiveRecord::Base o de clases abstractas. Para solucionar esto, se puede hacer que ApiLog herede de ActiveRecord::Base.

    Por lo tanto, el archivo app/models/api_log.rb debería verse así:

    # frozen_string_literal: true
    
    class ApiLog < ActiveRecord::Base
      self.table_name = 'api_logs'
    
      connects_to database: { writing: :api_logs, reading: :api_logs }
    end
    

    Con esto, debería ser posible crear objetos ApiLog en la base de datos api_logs.

Comments are closed.