skip to Main Content

I have 2 read replicas configured in the database.yml and I want to avoid any write operation in the Ruby on Rails application.

When setting database_tasks: false the following exception was raised:

/.rvm/gems/ruby-3.2.2/gems/activerecord-7.1.1/lib/active_record/railtie.rb:151:in `block (3 levels) in <class:Railtie>': 
  undefined method `name' for nil:NilClass (NoMethodError)
  in db_config.name

Is database_task deprecated or has it some bug after version upgrade?

database.yml

service_read_replica_defaults: &service_read_replica_defaults
adapter: postgresql
username: root
password: <%= nil %>
host: localhost
port: <%= 5432 %>
database: <%= "service_#{Rails.env}") %>
database_tasks: false

patient_read_replica_defaults: &patient_read_replica_defaults
adapter: mysql2
username: root
password: <%= nil %>
host: <%= localhost %>
port: 3306
database: <%= "patient_#{Rails.env}") %>
database_tasks: false

production:
service_read_replica:
<<: *service_read_replica_defaults
patient_read_replica:
<<: *patient_read_replica_defaults

development:
service_read_replica:
<<: *service_read_replica_defaults
patient_read_replica:
<<: *patient_read_replica_defaults

test:
service_read_replica:
<<: *service_read_replica_defaults
patient_read_replica:
<<: *patient_read_replica_defaults

There are two external databases (postgresql and mysql) want to connect with read only access. And I want to use database_task: false to restrict write actions on external databases.

2

Answers


  1. The error message tells that the database’s name in the database’s configuration is nil.

    And I reckon that it issue is how database is configured in the database.yml. Currently, it looks like this

    database: <% ("service_#{Rails.env}") %>
    

    But ERB statements starting with <% only evaluate the code, but do not insert the response into the document after evaluation. You need to change this line to:

    database: <%= ("service_#{Rails.env}") %>    
    

    Note the <%= at the beginning of the ERB statement.

    Additionally, the database configuration is set in the default block, which means that it will be the same for all database configuration using those defaults.

    From your question, it is not entirely clear how you re-use those defaults. I would expect that at least the two replicas share the same defaults, but should have different database configurations to use different databases. Therefore, I suggest setting database explicitly for all replicas and not only once in the defaults. For example, like this:

    read_replica_defaults: &read_replica_defaults
      adapter: postgresql
      username: root
      password: password
      host: localhost
      port: 5432
      database_tasks: false
    
    production:
      service_read_replica:
        <<: *read_replica_defaults
        database: <%= "service_read_replica_#{Rails.env}" %>
      patient_read_replica:
        <<: *read_replica_defaults
        database: <%= "patient_read_replica_#{Rails.env}" %>
    
    Login or Signup to reply.
  2. This line is causing it to return false and hence db_config is returned as nil.
    As the database.yml file contains only replicas and has database: false in each config, in the end no config is loaded and returned as nil. Hence, the error.
    The solution we are looking for is that if there is any configuration that we are missing to add in our project or is this scenario missed by rails itself?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search