Как выполнить запросы при подключении к БД в Rails? - PullRequest
6 голосов
/ 26 марта 2010

У меня есть определенные функции инициализации, которые я использую для настройки ведения журнала аудита на стороне сервера БД (т. Е. Не на рельсах) в PostgreSQL. По крайней мере один должен быть выдан (установка текущего пользователя) перед вставкой данных или обновлением какой-либо из проверенных таблиц, иначе весь запрос не получится впечатляющим образом.

Я могу легко вызывать их каждый раз перед выполнением любой операции сохранения в коде, но DRY заставляет меня думать, что я должен повторять код в как можно меньшем количестве мест, особенно потому, что это сильно отличается от идеала агностицизма базы данных. В настоящее время я пытаюсь переопределить ActiveRecord :: Base.establish_connection в инициализаторе, чтобы настроить его так, чтобы запросы выполнялись, как только я подключаюсь автоматически, но он не ведет себя так, как я ожидаю. Вот код в инициализаторе:

class ActiveRecord::Base
  # extend the class methods, not the instance methods
  class << self
    alias :old_establish_connection :establish_connection # hide the default

    def establish_connection(*args)
      ret = old_establish_connection(*args) # call the default

      # set up necessary session variables for audit logging
      # call these after calling default, to make sure conn is established 1st
      db = self.class.connection
      db.execute("SELECT SV.set('current_user', 'test@localhost')")
      db.execute("SELECT SV.set('audit_notes', NULL)") # end "empty variable" err

      ret # return the default's original value
    end
  end
end

puts "Loaded custom establish_connection into ActiveRecord::Base"
sycobuny:~/rails$ ruby script/server 
=> Booting WEBrick
=> Rails 2.3.5 application starting on http://0.0.0.0:3000
Loaded custom establish_connection into ActiveRecord::Base

Это не дает мне никаких ошибок, и, к сожалению, я не могу проверить, как метод выглядит внутренне (я использовал ActiveRecord :: Base.method (: create_connection), но очевидно, что каждый раз создается новый объект метода он называется, что, по-видимому, бесполезно, потому что я не могу проверить object_id для какой-либо полезной информации, и я также не могу отменить компиляцию).

Однако, кажется, что код никогда не вызывается, потому что любая попытка выполнить сохранение или обновление объекта базы данных терпит неудачу, как я предсказывал ранее. Если это неправильный способ немедленного выполнения кода при подключении к базе данных, тогда что это?

Ответы [ 3 ]

3 голосов
/ 26 марта 2010

Rails использует пул соединений, поэтому лучше всего использовать alias_method_chain для ActiveRecord :: ConnectionAdapters :: ConnectionPool # new_connection

module ActiveRecord
  Module ConnectionAdapters
    class ConnectionPool
      alias_method_chain :new_connection, :my_stuff
      private
      def new_connection_with_my_stuff
        c = new_connection_without_my_stuff
        # Do your stuff with 
        # c.exec(<your sql command>)
        c
      end
    end
  end
end
0 голосов
/ 30 марта 2010

С точки зрения написания кода для перехвата вызовов и инициализации базы данных рельсов, вы можете использовать код из db-charmer в качестве шаблона. Он демонстрирует ряд интересных способов взаимодействия с ActiveRecord, и один из них, вероятно, будет делать то, что вы хотите.

0 голосов
/ 26 марта 2010

Знаете ли вы, что ваш инициализатор вызывается до установления соединения с базой данных?

Без достоверной информации о том, что может быть не так, я бы воспользовался тем, что источник ActiveRecord находится на моем жестком диске.

Покопайтесь в базовом классе и сделайте небольшую отладку, чтобы увидеть, когда ActiveRecord вызывается create_connection относительно того, когда вызывается ваш инициализатор. Либо так, либо просто включите дополнительную многословную отладку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...