Ruby On Rails TCPSocket - ruby-on-rails

I developed a server in C++ and I would like to develop an interface in Ruby On Rails.
So I started to read http://ruby.railstutorial.org/, meanwhile I start looking if I would be able to create a connection between my Ruby On Rails application and my server.
I find out I could use TCPSocket.
My question is : Could I open just 1 TCPSocket by session (and store it somewhere) ?
Or would I have to open a TCPSocket for every action in my controllers ?
Thanks in advance,

app/models/conn.rb:
class Conn
#connection = "foo" # Connect here
def self.get_connection
#connection
end
end
Rails console:
irb(main):002:0> Conn.get_connection
=> "foo"
But unless your server is single-threaded you will have more than one connection anyways.

Related

Mssql-2012 with Rails-2.3.18 what version of SQL adapter?

I am migrating my Ruby (1.8.7) Rails (2.3.18) application database into MSSQL-2012 Database.
I have followed all the configuration information and made. The Sql adapter I am using is activerecord-sqlserver-adapter (2.3.24).
When I load the application I got a error. The error says " The current version support only Mssql 2005,2008 " error.
How can I proceed, As of now I can't upgrade or downgrade my Ruby on Rails versions and MSSQL versions.
Is this any way is there to proceed with current set up and versions . Plz help me
Sounds like you just need to update your adapter. Looking at the Github page, it should support 2012
https://github.com/rails-sqlserver/activerecord-sqlserver-adapter
So, if you haven't figured out a way to fix this yet, you can create a new initializer file and drop the following code in it.
module ActiveRecord
module ConnectionAdapters
class SQLServerAdapter
alias :old_initialize :initialize
def initialize(logger, config)
begin
old_initialize(logger, config)
rescue NotImplementedError => e
unless e.message =~ /Currently, only #{SUPPORTED_VERSIONS.to_sentence} are supported./
raise e
end
end
end
def sqlserver_2012?
#database_year == 2012
end
end
end
end
Unfortunately there's no driver for SQL Server 2012 and rails 2.x
You need to upgrade to Rails 3.2, as this is the first version of the SQL Server gem that supports 2012.
You can take a look at the docs to check the different versions.

how to stop a Rinda ring server in ruby

i'm wondering how can i stop a Rinda ring server, besides killing its process.
i'v checked ring.rb shipped with my ruby 1.9.3, and found the RingServer lacks api to stop itself. It opens an UDPSocket in initialize(), but it dose not contain any code to close that socket.
anybody knows it? thanks ahead. :D
Rinda is part of Distributed Ruby (DRb), so if the goal were to just stop all Rinda and other DRb services, you could do:
DRb.stop_service
If you use that, then in your Rinda service code (the looping method), you need to rescue DRb::DRbConnError to avoid problems trying to write to the TupleSpace, according to: http://www.ruby-forum.com/topic/97023
Not a Rinda service, but here is a simple example I tested that stops a DRb service. It just uses DRb (no Rinda) in Ruby 1.9.3, modified slightly from the example here: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/drb/rdoc/DRb.html
server.rb
#!/usr/local/bin/ruby
require 'drb/drb'
URI="druby://localhost:8787"
class StopAndGiveTimeServer
def get_current_time
DRb.stop_service
return Time.now
end
end
FRONT_OBJECT=StopAndGiveTimeServer.new
$SAFE = 1 # disable eval() and friends
DRb.start_service(URI, FRONT_OBJECT)
DRb.thread.join
client.rb
#!/usr/local/bin/ruby
require 'drb/drb'
SERVER_URI="druby://localhost:8787"
DRb.start_service
timeserver = DRbObject.new_with_uri(SERVER_URI)
puts timeserver.get_current_time
Update: It sounds like you want to monkey patch the ring server to close the socket.
Just create a way to get the existing socket via monkey patch:
module Rinda
class RingServer
attr_accessor :soc
end
end
Then you can keep the instance of the ringserver in an instance variable, e.g. #ringserver, and use it to access the socket to close it, set a new socket, etc. e.g.
def bind_to_different_port(port)
begin
#ringserver.soc.close
rescue => e
puts "#{e.message}\n\t#{e.backtrace.join("\n\t")}"
end
#ringserver.soc=UDPSocket.open
#ringserver.soc.bind('', port)
end
Or skip the attr_accessor and just add a method to RingServer and call a method or two on the RingServer to close, open, bind the socket.
To see how it uses the socket in Ruby 1.9.3: https://github.com/ruby/ruby/blob/v1_9_3_374/lib/rinda/ring.rb

Trying to do something with ActiveRecord::Base.connection_pool.with_connection

So I know how that this works like this
ActiveRecord::Base.connection_pool.with_connection do |conn|
conn.execute(sql)
end
but I'm trying to use the connection with actual Activerecord models, so something like
conn.Url.first
is there a way to do something like that?
Found out this isn't possible, but within the with_connection block any ActiveRecord calls should use the connection that is checked out from the Rails connection pool
so in this example
ActiveRecord::Base.connection_pool.with_connection do |conn|
Url.first
end
It should check out a connection from the pool set aside for Rails in your database.yml :pool setting, let your active record call use it and then check it back in
However, this only works in rails 3+ ... you can see the code change that makes this possible here
Rails 2.3 (old way) http://apidock.com/rails/v2.3.8/ActiveRecord/ConnectionAdapters/ConnectionPool/with_connection
Rails 3 http://apidock.com/rails/v3.0.0/ActiveRecord/ConnectionAdapters/ConnectionPool/with_connection
This guy explains the patch in this blog post
http://coderrr.wordpress.com/2009/05/05/activerecords-with_connection-is-now-useful/

Why not use shared ActiveRecord connections for Rspec + Selenium?

It seems the most commonly accepted way to deal with Selenium and tests is to avoid using transactional fixtures and then using something like database_cleaner between tests/scenarios. I recently ran into the following article which suggested doing the following:
spec_helper.rb
class ActiveRecord::Base
mattr_accessor :shared_connection
##shared_connection = nil
def self.connection
##shared_connection || retrieve_connection
end
end
# Forces all threads to share the same connection. This works on
# Capybara because it starts the web server in a thread.
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
This seems loads better for performance than the alternatives. Does anyone have any reason why this shouldn't be used?
Actually there are issues with it. If you use the gem mysql2, for example, you'll start seeing some errors like:
Mysql2::Error This connection is still waiting for a result
Please use this instead. It was written by Mike Perham, all credits to him.
class ActiveRecord::Base
mattr_accessor :shared_connection
##shared_connection = nil
def self.connection
##shared_connection || ConnectionPool::Wrapper.new(:size => 1) { retrieve_connection }
end
end
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
You'll need to install gem connection_pool too.
This will spare you from many headaches.
This solution was written by Jose Valim - well respected in the Rails community and a member of the Rails core team. I doubt he would recommend using it if there were issues with it. I personally haven't had any issues.
Just be aware that if you use Spork this needs to be in the each_run block to work.
FWIW - I have had intermittent capybara test issues with the above patch on Postgres. The Mike Perham solution that #hsgubert has below appears to have solved those issues. I am now use that solution.
The DatabaseCleaner gem readme answers your "why not" question this way:
One common approach is to force all processes to use the same database connection (common ActiveRecord hack) however this approach has been reported to result in non-deterministic failures.
I have encountered a problem using the code you mentioned in my spec_helper.rb file.
What happens when your tests depend on using connections to multiple databases? I have two databases I need to connect to when I run my tests. I did a simple test to check what was happening to the database connections I establish.
class ActiveRecord::Base
mattr_accessor :shared_connection
##shared_connection = nil
def self.connection
##shared_connection || retrieve_connection
end
end
# Forces all threads to share the same connection. This works on
# Capybara because it starts the web server in a thread.
puts "First Record cxn: #{FirstDatabase::Record.connection}"
# => First Record cxn: #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xe59b524>
puts "AR Base cxn: #{ActiveRecord::Base.connection}"
# => AR Base cxn: #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xc52761c>
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
puts "First Record cxn: #{FirstDatabase::Record.connection}"
# => First Record cxn: #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xc52761c>
puts "AR Base cxn: #{ActiveRecord::Base.connection}"
# => AR Base cxn: #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xc52761c>
As you can see, before I call the shared connection method, I have two different database connections. After, the shared connection method call, I have only one.
So any test that requires going to the second database connection to retrieve information will fail. :(
I'm going to post this problem and see if anyone has arrived at a solution.
I was just doing a little reading on this myself. I discovered the snippet you shared here in this blog post:
http://blog.plataformatec.com.br/2011/12/three-tips-to-improve-the-performance-of-your-test-suite/
To answer your question directly, the database cleaner github page cautions that it can " result in non-deterministic failures". I'd go right ahead and use it, but if you start running into weird failures, maybe this is a good place to start looking.
There's a good thing at the end of this post. It may explain why I get a MALLOC error when I attempt to a very simple threading script.
http://apidock.com/rails/ActiveRecord/Base/connection
leente - March 15, 2011 0 thanks
Don't cache it!
Don’t store a connection in a variable, because another thread might try to use it when it’s already checked back in into the connection pool. See: ActiveRecord::ConnectionAdapters::ConnectionPool
connection = ActiveRecord::Base.connection
threads = (1..100).map do
Thread.new do
begin
10.times do
connection.execute("SELECT SLEEP(1)") # WRONG
ActiveRecord::Base.connection.execute("SELECT SLEEP(1)") # CORRECT
end
puts "success"
rescue => e
puts e.message
end
end
end
threads.each(&:join)

Authenticate User from within rails /lib module

I want to authenticate Users when they try to fire up a TCP connection in my Rails app. Here's the current code I have, it's very simplistic but should give you an idea of what I want to do.
TcpServer.rb
module TcpServer
def receive_data(data)
(#buf ||= '') << data
if line = #buf.slice!(/(.+)\r?\n/)
commands = data.split(";")
case commands[0]
when /start/i
if !User.authenticate(commands[1],commands[2])
close_connection
puts "Subscription invalid."
else
put "Subscription validated."
end
end
end
end
EventMachine::run do
host = "localhost"
port = "5587"
EventMachine::start_server host, port, TcpServer
puts "TcpServer started # #{host}:#{port}"
end
end
What do I need to require or include in order to access my User model from that module? Or is this just a completely incorrect way to do it? If so, what do you suggest?
The issue is I wasn't running it with Rails.
I was running it with:
ruby lib/TcpServer.rb
rather than:
script/runner lib/TcpServer.rb
No includes or requires needed, Rails did it automagically.
Dir.glob(Rails.root.join('app/models/*.rb')).each { |file| require file }
The above will get all models loaded if you need them (you can just add 'user.rb' to the statement if needed, in the comment above you may need to specify the path and not include the ".rb" part -> "require 'user'").
You should make a decision as to whether you think this type of integration server should be part of the running Rails app or potentially another "application" that is part of the same code base. You could keep the core internals here and start your EM server with a custom rake task and load the Rails env through that rake task.
namespace :tcp do
task :start, :needs => :environment do
# server load and start here
end
end
If I am going to open a new means of execution then I prefer to keep these running in separate processes to keep any errors from causing both to go down together. (I would look at Resque jobs/workers as a good example of how to keep code in the same Rails app without forcing them to run in the same process)

Resources