Heh--you're welcome.  But please don't let me bully you into dropping rails--I 
don't understand your goals as well as you do. ;-)  I'm just trying to explain 
options.  I frankly don't understand rails well enough to know when/how objects 
live beyond individual http requesst/response cycles.  My guess is that your 
socket server thingy needs to be independent of that in order to handle 
incoming connections reliably.

I can say that it is possible to add class *methods* to a descendant of 
AR::Base--frx, in the below find_by_fragment is a class method.

  class SpecificTherapeuticClass < ActiveRecord::Base
    has_many :ingredients
    belongs_to :general_therapeutic_class
    def self.find_by_fragment(frag)
      frag += "%"
      self.find(:all, :conditions => ["description like :frag", {:frag => 
frag}])
    end
  end

I'm not totally sure I follow your code below, but one thing jumps out--this 
line:

  cattr_accessor :connection, :cert_name, :cert

Defines *class* methods & vars for those attributes.  So you'd say, e.g. 
ConnectionManager.cert = "/bibbity/bobbity/boo.pem" and that bit of data is 
entirely independent of any particular instance of ConnectionManager.  But 
initialize is an *instance* method--it gets called in the context of a new 
instance of ConnectionManager.  So the line "cert = File.read..." in your 
initialize method is just setting a local var 'cert' which will die as soon as 
the initialize call is over.  If you want to define instance methods 
connection, cert_name & cert, you'd use the (native ruby) attr_accessor method 
(and you may want to call it as self.cert, just to make it totally clear to the 
interpreter that you intend to call a method rather than set a local var).

Maybe that helps?

Cheers,

-Roy

-----Original Message-----
From: [email protected] 
[mailto:[email protected]] On Behalf Of Steve Hull
Sent: Thursday, May 21, 2009 5:06 PM
To: [email protected]
Subject: [Rails] Re: How to keep persistent socket connections?


Roy --

Thank you for that example!!  I guess I'll give that a shot    :)

It still hurts my heart that this doesn't appear to be possible with Rails.  :(

One followup question, if I may:
Why is it that class variables don't behave as I expect them to?  So since it 
appears that adding class attributes (inheritable or not) to a descendent of 
ActiveRecord is unsupported, I added a new Class (inheriting from Object) and 
put it in /lib:

class ConnectionManager
  HOST = "the.host.com"
  PATH = '/'
  PORT = 2195

  PASSPHRASE = "foobar"
  CACERT = File.expand_path(File.dirname(__FILE__) +
"certs/ca.the.host.com.crt")
  USERAGENT = 'Mozilla/5.0 (ConnectionManager Ruby on Rails 0.1)'
  cattr_accessor :connection, :cert_name, :cert
  self.cert_name = "my_pem_file.pem"

  def initialize
    super
    cert = File.read("config/#{cert_name}") if
File.exists?("config/#{cert_name}")
    puts "cert = #{cert.inspect}"
    if connection.nil?
      puts "Connecting now!!"
      ctx = OpenSSL::SSL::SSLContext.new
      ctx.key = OpenSSL::PKey::RSA.new(cert, PASSPHRASE)
      ctx.cert = OpenSSL::X509::Certificate.new(cert)


      s = TCPSocket.new(HOST, PORT)
      connection = OpenSSL::SSL::SSLSocket.new(s, ctx)
      connection.sync = true
      connection.connect
    end
  end
end

But when I try to use this in my class that inherits from ActiveRecord,
like this:

  def send
    ssl = cm.class.connection
    logger.info "ssl = #{ssl.inspect}"
    ssl.write(self.message_for_sending)

  rescue SocketError => error
    raise "Error while sending: #{error}"
  end

First I got an error and I realized that my ConnectionManager's
initialize method wasn't being called.  So I added a line to get an
instance of ConnectionManager, just so that initialize would be called:

  def send_notification
    cm = ConnectionManager.new
    ssl = cm.class.connection
    logger.info "ssl = #{ssl.inspect}"
    ssl.write(self.message_for_sending)

  rescue SocketError => error
    raise "Error while sending notifications: #{error}"
  end

I could tell from my log ("Connecting Now!!" appeared) that initialize
had been called.  But I'm still getting an error:

You have a nil object when you didn't expect it! The error occurred
while evaluating nil.write

Clearly ConnectionManager.connection is returning null.  In Java, once
you've used a class, its static vars are instantiated and hold their
values.  It seems that in Ruby, the class's static vars are
instantiated/sandboxed in each .rb file.  Am I correct here, or no?

Thanks again for the example code Roy!

-Steve
--
Posted via http://www.ruby-forum.com/.



GHC Confidentiality Statement

This message and any attached files might contain confidential information 
protected by federal and state law. The information is intended only for the 
use of the individual(s) or entities originally named as addressees. The 
improper disclosure of such information may be subject to civil or criminal 
penalties. If this message reached you in error, please contact the sender and 
destroy this message. Disclosing, copying, forwarding, or distributing the 
information by unauthorized individuals or entities is strictly prohibited by 
law.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to