2012-05-25 31 views
20

Tôi có một đối tượng mà tôi muốn tạo một lần và có thể truy cập được ở một trong các kiểu máy của tôi. Tôi đưa anh ấy ở đâu? Tôi sợ nếu tôi đưa anh ta vào tập tin lớp mô hình anh ta sẽ được tạo ra mỗi khi tôi tạo một thể hiện mới của mô hình đó. Tôi chỉ muốn đối tượng này được tạo một lần khi khởi động. Dưới đây là các đối tượng:làm cách nào để tạo một đối tượng toàn cục đơn lẻ trong đường ray

require 'pubnub'  
publish_key = 'fdasfs' 
subscribe_key = 'sdfsdsf' 
secret_key = 'fsdfsd' 
ssl_on  = false 

pubnub_obj = Pubnub.new(publish_key, 
        subscribe_key, 
        secret_key, 
        ssl_on) 

tôi sử dụng nó như thế này trong các mô hình:

class Message < ActiveRecord::Base 

    def self.send_new_message_client(message) 
    message = { 'some_data' => message } 
    info = pubnub_obj.publish({ 
          'channel' => 'testing', 
          'message' => message 
          }) 
    puts(info) 
    end 

end 
+0

Tôi nghĩ rằng bạn có thể cũng sử dụng biến toàn cầu, xem ví dụ này tại đây: https://github.com/pubnub/ruby/blob/master/examples/pubnub_livestream/config/initializers/pubnub.rb –

Trả lời

31

Trong Rails, các đối tượng được tái tạo trên mỗi yêu cầu. Nếu đây là một loại dịch vụ, nó phải là một singleton trong phạm vi yêu cầu.

đối tượng Singleton nên được tạo ra với mixin ruby ​​singleton:

require 'singleton' 

class Pubnub 
    include Singleton 

    def initialize(publish_key, subscribe_key, secret_key, ssl_on) 
    # ... 
    end 

    def publish 
    # ... 
    end 
end 

Sau đó, bạn có thể gọi nó với instance phương pháp:

Pubnub.instance.publish 

Bằng cách này bạn hãy chắc chắn rằng đối tượng này sẽ thực sự được một singleton (chỉ một ví dụ sẽ tồn tại).

Bạn có thể đặt nó an toàn trong thư mục models, mặc dù tôi thường thích thư mục lib hoặc có thể tạo một thư mục mới cho các dịch vụ. Nó phụ thuộc vào tình hình.

Hy vọng điều đó sẽ hữu ích!

+0

Để ghi lại, câu lệnh đầu tiên chỉ đúng nếu config.cache_classes là đặt thành false. Đó là, theo mặc định, không đúng trong Sản xuất. Tôi không biết hành vi là gì với mixin Singleton. – Michael

+1

Có nguy cơ tiềm tàng trong cách tiếp cận này khi sử dụng một số máy chủ đa quy trình như Phusion Passenger. PP tạo ra một luồng cho mỗi yêu cầu và hơn thế nữa - các luồng này sẽ có khả năng tồn tại trong các tiến trình riêng biệt, vì vậy mỗi tiến trình sẽ có đối tượng singleton riêng của nó được chia sẻ bởi nhiều luồng của quá trình này. – Paul

+0

để mở rộng nhận xét của Paul ở trên, lưu ý rằng cũng có một vấn đề nếu bạn không muốn nó chia sẻ, trong đó mong muốn là có một singleton theo yêu cầu. http://stackoverflow.com/questions/24927928/singleton-in-scope-of-a-request-in-rails – futbolpal

2

Nếu bạn chỉ muốn một cá thể trong toàn bộ ứng dụng của mình, hãy sử dụng một singleton, nếu không thì hãy sử dụng biến lớp.

Để sử dụng đĩa đơn, hãy bao gồm mixin Singleton.

require 'singleton' 

class Pubnub 
    include Singleton 

    attr_writer :publish_key, :subscribe_key, :secret_key, :ssl_on 

    def publish 
    #... 
    end 
end 

và sau đó sử dụng nó như thế này:

require 'pubnub'  
class Message < ActiveRecord::Base 
    Pubnub.instance.publish_key = 'xyz' 
    Pubnub.instance.subscribe_key = 'xyz' 
    Pubnub.instance.secret_key = 'xyz' 
    Pubnub.instance.ssl_on = 'xyz' 

    def self.send_new_message_client(message) 
    message = { 'some_data' => message } 
    info = Pubnub.instance.publish({ 
          'channel' => 'testing', 
          'message' => message 
          }) 
    puts(info) 
    end 
end 

Bạn cũng có thể làm cho nó một biến lớp, để liên kết nó chặt chẽ hơn để một mô hình cụ thể:

require 'pubnub'  
class Message < ActiveRecord::Base 
    @@pubnub_obj = Pubnub.new('xyz', 'xyz', 'xyz', 'xyz') 

    def self.send_new_message_client(message) 
    message = { 'some_data' => message } 
    info = @@pubnub_obj.publish({ 
          'channel' => 'testing', 
          'message' => message 
          }) 
    puts(info) 
    end 

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