2010-03-25 28 views
5

Tôi có một số hàm khởi tạo mà tôi sử dụng để thiết lập ghi nhật ký kiểm tra ở phía máy chủ DB (tức là không phải đường ray) trong PostgreSQL. Ít nhất một được cấp (thiết lập người dùng hiện tại) trước khi chèn dữ liệu vào hoặc cập nhật bất kỳ bảng được kiểm tra nào hoặc nếu không toàn bộ truy vấn sẽ thất bại một cách ngoạn mục.Làm cách nào để thực hiện truy vấn khi kết nối DB trong Rails?

Tôi có thể dễ dàng gọi chúng mỗi lần trước khi chạy bất kỳ thao tác nào trong mã, nhưng DRY khiến tôi nghĩ rằng tôi nên lặp lại mã ở ít nhất có thể, đặc biệt vì điều này phân tách rất nhiều từ lý tưởng về thuyết bất khả tri của cơ sở dữ liệu. Hiện tại tôi đang cố gắng ghi đè ActiveRecord :: Base.establish_connection trong trình khởi tạo để thiết lập để các truy vấn chạy ngay khi tôi kết nối tự động, nhưng nó không hoạt động như tôi mong đợi. Đây là mã trong initializer:

 
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', '[email protected]')") 
     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 

này không cho tôi bất kỳ lỗi nào, và tiếc là tôi không thể kiểm tra những gì phương pháp này trông giống như trong nội bộ (Tôi đã sử dụng ActiveRecord :: Base.method (: establish_connection), nhưng dường như tạo ra một đối tượng Method mới mỗi lần nó được gọi, điều này dường như vô giá trị vì tôi không thể kiểm tra object_id cho bất kỳ thông tin đáng giá nào và tôi cũng không thể đảo ngược quá trình biên dịch).

Tuy nhiên, mã không bao giờ có vẻ được gọi, bởi vì bất kỳ nỗ lực nào để chạy lưu hoặc cập nhật đối tượng cơ sở dữ liệu đều không thành công như tôi đã dự đoán trước đó. Nếu đây không phải là cách thích hợp để thực thi mã ngay lập tức khi kết nối với cơ sở dữ liệu, thì đó là gì?

Trả lời

3

Rails sử dụng kết nối tổng hợp, vì vậy đặt cược tốt nhất của bạn là sử dụng một alias_method_chain cho 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

tôi tin rằng alias_method_chain cần phải được chạy sau khi phương thức được khai báo. – Kevin

+0

alias_method_chain không cần phải được gọi sau khi phương thức được khai báo, nếu không nó sẽ không tìm thấy phương thức. Ngoài ra, phương pháp để chạy tắt của c được thực hiện, chứ không phải là exec (Tôi tin rằng lỗi nó đã cho tôi là exec đã được tư nhân). Nhưng nếu không, điều này giải quyết được vấn đề tôi đang gặp phải. Cảm ơn! – sycobuny

+0

Và cách nhận * người dùng hiện tại * trong ngữ cảnh này? – mlt

0

Bạn có biết rằng trình khởi tạo của bạn đang được gọi trước khi kết nối cơ sở dữ liệu được thiết lập không?

Nếu không có thông tin có thẩm quyền về những gì có thể sai, tôi sẽ tận dụng lợi thế của thực tế là nguồn tới ActiveRecord nằm trên ổ cứng của tôi.

Đào sâu vào lớp cơ sở và thực hiện một chút đặt gỡ lỗi để xem khi ActiveRecord setup_connection được gọi là liên quan đến thời điểm trình khởi tạo của bạn được gọi. Hoặc là hoặc chỉ cần bật gỡ lỗi thêm chi tiết.

0

Xét về viết code để treo ray cuộc gọi cơ sở dữ liệu và khởi tạo, có lẽ bạn muốn sử dụng mã từ db-charmer làm mẫu. Nó thể hiện một số cách thú vị để tương tác với ActiveRecord và một trong số chúng có thể sẽ làm những gì bạn muốn.

Các vấn đề liên quan