how to excute code on webrick server - ruby

I start a webrick server like this:
dell#dev:/var/www/ruby$ ruby -run -httpd. -p 5000
and have this code in abc.rb:
require 'webrick'
root = File.path '/tmp/public_html'
server = WEBrick::HTTPServer.new :Port => 5000, :DocumentRoot => root
trap 'INT' do server.shutdown end
server.start
ary = { "0"=>"fred", "1"=>10, "2"=>3.14, "3"=>"This is a string", "4"=>"last element", }
ary.each do |key, value|
puts "#{key} #{value}"
end
When I run this code it shows me the same code on browser
http://localhost:5000/abc.rb
How can I view the output this code, I have already asked this question and did not get any correct answer :(
Is it the right code? I want to know this, where this code place
require 'webrick'
root = File.path '/tmp/public_html'
server = WEBrick::HTTPServer.new :Port => 5000, :DocumentRoot => root
trap 'INT' do server.shutdown end
server.start
if any one give me step by step ans to run this code i am very thankful.. I don't understand the ans :( how to do this

From the documentation:
The easiest way to have a server perform custom operations is through
WEBrick::HTTPServer#mount_proc. The block given will be called with a
WEBrick::HTTPRequest with request info and a WEBrick::HTTPResponse
which must be filled in appropriately:
server.mount_proc '/' do |req, res|
res.body = 'Hello, world!'
end
Remember that server.mount_proc must server.start.
So:
require 'webrick'
root = File.path '/tmp/public_html'
server = WEBrick::HTTPServer.new :Port => 5000, :DocumentRoot => root
server.mount_proc '/abc.rb' do |req, res|
ary = { "0"=>"fred", "1"=>10, "2"=>3.14, "3"=>"This is a string", "4"=>"last element" }
res.body = ary.map do |key, value|
"#{key} #{value}"
end.join("\n")
end
trap 'INT' do server.shutdown end
server.start
Also, I believe the correct way to start your WebBrick is by running:
ruby abc.rb

Related

how to check mysql connexion

I would want to check if there is a connection with the database before execute the query .
But when I write if mysql_connection ... then it passes twice on mysql_connection:
def mysql_connection
puts "mysql_connection 1"
read_config_file
#connexion = Mysql2::Client.new(:host => #conf['host'], :username => #conf['user'], :password => #conf['password'], :database=> #conf['base'], :port => #conf['port'])
end
# USER QUERY MYSQL
def mysql_select_user(value)
puts "select"
# if mysql_connection then
p = mysql_connection.query("select #{value} from User")
p.each do |f|
puts "value : #{f}"
mysql_close
end
# else
# end
end
Use Mysql2::Client#ping method (from docs: http://www.rubydoc.info/gems/mysql2/0.3.13/Mysql2/Client#ping-instance_method)

Why do I have a worse performance of redis from ruby?

I've installed redis on a local virtual machine and run this code on my host. So I try to insert rows from a csv file to redis db. The CSV file includes 11000 rows and needs 20 seconds and I don't know why.
My code is:
require "redis"
require "csv"
CSV_FILE = "./data/SB_HI_OESL.CSV"
$redis = Redis.new(:host => "127.0.0.1", :port => 6379, :db => 0)
def insert_parent_child(parent, child)
start = Time.now
$redis.set("H:P:%s:%s" % [child[0], child[1]], "%s:%s" % [parent[4], parent[5]])
finish = Time.now
p (finish-start).inspect
end
CSV.foreach(CSV_FILE, { :col_sep => ';' }) do |row|
if $. != 1
insert_parent_child(row[-2..-1], row[0..1])
end
end
Output is:
"0.006501"
"0.003001"
"0.0005"
"0.011502"
"0.012002"
"0.004001"
"0.010502"
"0.011002"
I changed it to:
start = Time.now
$redis.pipelined {
CSV.foreach(CSV_FILE, { :col_sep => ';' }) do |row|
if $. != 1
insert_parent_child(row[-2..-1], row[0..1])
end
end
}
finish = Time.now
p (finish-start).inspect
Now output is "0.7315"

Migrating Sinatra Webrick RACK:SSLEnforcer based HTTPS to Thin

I have been running Sinatra with Webrick and SSL using Rack::SSLenforcer in a development environment for a long while without any issues (based on https://github.com/tobmatth/rack-ssl-enforcer#readme ), i am trying to migrate to Thin in order to add websockets support but have issues getting my current app (without websockets) to run with Thin and SSL.
The basic code that i currently have on websockets is the following:
begin
pkey = OpenSSL::PKey::RSA.new(File.open("private_key.pem").read)
cert = OpenSSL::X509::Certificate.new(File.open("certificate.pem").read)
end
webrick_options = {
:Port => 8447,
:Logger => WEBrick::Log::new($stderr, WEBrick::Log::DEBUG),
:DocumentRoot => "/ruby/htdocs",
:SSLEnable => true,
:SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
:SSLCertificate => cert,
:SSLPrivateKey => pkey,
:SSLCertName => [ [ "CN",WEBrick::Utils::getservername ] ],
:app => MyWebRTCServer
}
Rack::Server.start webrick_options
Then in my app i have the following:
configure do
# require SSL - https://github.com/tobmatth/rack-ssl-enforcer#readme
use Rack::SslEnforcer
set :session_secret, 'asdfa2342923422f1adc05c837fa234230e3594b93824b00e930ab0fb94b'
use Rack::Session::Cookie, :key => '_rack_session',
:path => '/',
:expire_after => 2592000, # In seconds
:secret => session_secret
# load password file -
begin
##config = YAML.load_file(File.join(Dir.pwd, 'config', 'users.yml'))
rescue ArgumentError => e
puts "Could not parse YAML: #{e.message}"
end
# puts "config: " + ##config.to_s
use Rack::Auth::Basic, "Restricted Area" do |u, p|
$LOG.info "Use Rack::Auth::Basic"
if (!##config[:users][u])
puts "Bad username"
false
else
# initialize the BCrypt with the password
tPassword = BCrypt::Password.new(##config[:users][u][:password].to_s)
# puts "From BCrypt: " + tPassword
if (tPassword == p)
# puts "Validated password"
# check whether the user is already logged in or not
if (!##user_table_cache[u.to_sym])
# puts "User already logged in or session has not expired"
userHash = Hash.new
userHash[:name] = u
userHash[:privilege] = ##config[:users][u][:privilege]
# add the user hash to the cache
##user_table_cache[u.to_sym] = userHash
end
end
true
end
end
end
All of this works on webrick with Sinatra. I have tried the following on Thin (based on Can I enable SSL in Sinatra with Thin?)
class MyApp < Sinatra::Base
# ...
get '/' do
puts "got request"
end
end
MyApp.run! do |server|
ssl_options = {
:cert_chain_file => './certificate.pem',
:private_key_file => './private_key.pem',
:verify_peer => false
}
server.ssl = true
server.ssl_options = ssl_options
end
However, I get the following error, when i try to access it from the browser.
C:\Software\Ruby Projects\Utils\sandbox\thintest>thistest
== Sinatra/1.4.5 has taken the stage on 4567 for development with backup from Th
in
Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on localhost:4567, CTRL+C to stop
terminate called after throwing an instance of 'std::runtime_error'
what(): Encryption not available on this event-machine
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
any thoughts would be greatly appreciated.

forward email with attachments

I would like to do this without downloading the attachments and then re/attaching to the new email.
This is what i have tried:
$emailslist.each do |e|
Mail.deliver do
from fromstr
to "mailman#somedomain.com"
subject "[Events] #{subjectstr}"
if e.attachments.length>0
e.attachments.each do |a|
add_file a
end
end
end
end
#error in 'e.attachments.each'=>undefined method `attachments' for
#<TypeError: can't convert nil into String>
EDIT
I have been using this code for months and it worked fine.
The new stuff i have introduced now is the code above.
Anyways I'm pasting the whole code upon request.
require 'mail'
$subscribers=[]
File.new("C:/Users/j.de_miguel/Desktop/mailman.forma/subscribers2.txt",'r').each do |line|
line=line.sub("\n","")
$subscribers.push(line) if line =~ /#/
end
puts $subscribers
$errorfile=File.new("C:/Users/j.de_miguel/Desktop/mailman.forma/error_log2.txt",'a+')
$errorfile.write("#{Time.now}\n")
$errorfile.flush
def deleteSubjectRecursion(subjstr)
if subjstr =~ /(.\[FORMA 2013\])+/
subjstr.gsub!(/.\[FORMA 2013\]/,"")
end
if subjstr =~ /((?i)Re: ){2,}/
subjstr.gsub!(/((?i)Re: ){2,}/,"Re: ")
end
return subjstr
end
def UserIsRegistered(mailaddr)
registered = false
$subscribers.each{|s| registered = true if mailaddr==s}
if registered == false
$errorfile.write("#{Time.now} : user #{mailaddr} attempted to mailman\n")
$errorfile.flush
end
return registered
end
Mail.defaults do
retriever_method :imap, { :address => "imap.1and1.es",
:port => 143,
:user_name => "mailman#somedomain.com",
:password => "xxxxxxxx",
:enable_ssl => false }
delivery_method :smtp, { :address => "smtp.1and1.es",
:port => 587,
:domain => '1and1.es',
:user_name => 'mailman#somaedomain.com',
:password => 'xxxxxxxxxxxx',
:authentication => 'plain',
:enable_starttls_auto => true }
end
#$emailslist=Mail.find(keys: ['NOT','SEEN'])
$emailslist=[Mail.last]
$emailslist.each do |e|
eplain_part = e.text_part ? e.text_part.body.decoded : nil
ehtml_part = e.html_part ? e.html_part.body.decoded : nil
type=e.charset
type_plain=eplain_part ? e.text_part.charset.to_s : nil
type_html=ehtml_part ? e.html_part.charset.to_s : nil
bodystr= type ? e.body.decoded.to_s.force_encoding(type) : nil
type=type ? type.to_s : type_plain
puts type.inspect
subjectstr=e.subject.to_s.encode(type)
fromstr=e.from.first.to_s.encode(type)
puts fromstr
bodystr_plain=eplain_part ? eplain_part.force_encoding(type_plain) : nil
bodystr_html=ehtml_part ? ehtml_part.force_encoding(type_html) : nil
$subscribers.each do |tostr|
puts tostr.inspect
if (not subjectstr =~ /^\[FORMA 2013\]/ ) && (UserIsRegistered(fromstr) == true)
subjectstr=deleteSubjectRecursion(subjectstr)
begin
Mail.deliver do
from fromstr
to "mailman#somedomain.com"
bcc tostr
subject "[FORMA 2013] #{subjectstr}"
if ehtml_part != nil
html_part do
content_type("text/html; charset=# {type_html}")
#content_transfer_encoding("7bit")
body "# {bodystr_html}\nmailman#forma.culturadigital.cc para darte de baja escribe \"baja\" a info#culturadigital.cc"
end
end
if eplain_part != nil
text_part do
content_type("text/plain; charset=# {type_plain}")
#content_transfer_encoding("7bit")
body "#{bodystr_plain}\nmailman#forma.culturadigital.cc para darte de baja escribe \"baja\" a info#culturadigital.cc"
end
end
if eplain_part == nil && ehtml_part == nil
body "#{bodystr}\nmailman#forma.culturadigital.cc para darte de baja escribe \"baja\" a info#culturadigital.cc"
charset=type
end
#puts e.attachments.inspect
if e.attachments.length>0
e.attachments.each do |a|
add_file a.encoded
end
end
end
puts "1 email sent"
rescue => e
puts "error: #{e}"
$errorfile.write("#{Time.now}\nerror sending to #{tostr}: #{e},\nemail subject: #{subjectstr}\n\n")
$errorfile.flush()
end
end
end
end
$errorfile.close()
This is untested, and isn't really an attempt to find or fix the bug. It's to show how your code should look, written in more idiomatic Ruby code. And, as a result, it might fix the problem you're seeing. If not, at least you'll have a better idea how you should be writing your code:
require 'mail'
Define some constants for literal strings that get reused. Do this at the top so you don't have to search through the code to change things in multiple places, making it likely you'll miss one of them.
PATH_TO_FILES = "C:/Users/j.de_miguel/Desktop/mailman.forma"
BODY_BOILERPLATE_FORMAT = "%s\nmailman#forma.culturadigital.cc para darte de baja escribe \"baja\" a info#culturadigital.cc"
Group your methods toward the top of the file, after constants.
We open using 'a', not 'a+'. We don't need read/write, we only need write.
This opens and closes the file as necessary.
Closing the file automatically does a flush.
If you're calling the log method often then there are better ways to do this, but this isn't a heavyweight script.
I'm using File.join to build the filename based on the path. File.join is aware of the path separators and does the right thing automatically.
String.% makes it easy to create a standard output format.
def log(text)
File.open(File.join(PATH_TO_FILES, "error_log2.txt"), 'a') do |log_file|
log_file.puts "%s : %s" % [Time.now, text]
end
end
Method names in Ruby are snake_case, not CamelCase.
There's no reason to have multiple gsub! nor are the conditional tests necessary. If the sub-string you want to purge exists in the string gsub will do it, otherwise it moves on. Chaining the gsub methods reduces the code to one line.
gsub could/should probably be sub unless you know there could be multiple hits to be substituted in the string.
return is redundant so we don't use it unless we're explicitly returning a value to leave a block prematurely.
def delete_subject_recursion(subjstr)
subjstr.gsub(/.\[FORMA 2013\]/,"").gsub(/((?i)Re: ){2,}/, "Re: ")
end
Since registered is supposed to be a boolean, use any? to do the test. If any matches are found any? bails out and returns true.
def user_is_registered(mailaddr)
registered = subscribers.any?{ |s| mailaddr == s }
log("user #{ mailaddr } attempted to mailman") unless registered
registered
end
Use foreach to iterate over the lines of a file.
subscribers = []
File.foreach(File.join(PATH_TO_FILES, "subscribers2.txt")) do |line|
subscribers << line.chomp if line['#']
end
puts subscribers
log('')
Mail.defaults do
retriever_method(
:imap,
{
:address => "imap.1and1.es",
:port => 143,
:user_name => "mailman#somedomain.com",
:password => "xxxxxxxx",
:enable_ssl => false
}
)
delivery_method(
:smtp,
{
:address => "smtp.1and1.es",
:port => 587,
:domain => '1and1.es',
:user_name => 'mailman#somaedomain.com',
:password => 'xxxxxxxxxxxx',
:authentication => 'plain',
:enable_starttls_auto => true
}
)
end
#emailslist=Mail.find(keys: ['NOT','SEEN'])
emailslist = [Mail.last]
emailslist.each do |e|
This use of ternary statements here is probably not desirable but I left it.
Formatting into columns makes it easier to read.
Organize your assignments and uses so they're not strewn all through the file.
eplain_part = e.text_part ? e.text_part.body.decoded : nil
type_plain = eplain_part ? e.text_part.charset.to_s : nil
ehtml_part = e.html_part ? e.html_part.body.decoded : nil
type_html = ehtml_part ? e.html_part.charset.to_s : nil
e_charset = e.charset
body_str = e_charset ? e.body.decoded.to_s.force_encoding(e_charset) : nil
e_charset = e_charset ? e_charset.to_s : type_plain
puts e_charset.inspect
subjectstr = e.subject.to_s.encode(e_charset)
fromstr = e.from.first.to_s.encode(e_charset)
puts fromstr
bodystr_plain = eplain_part ? eplain_part.force_encoding(type_plain) : nil
bodystr_html = ehtml_part ? ehtml_part.force_encoding(type_html) : nil
subscribers.each do |subscriber|
puts subscriber.inspect
if !subjectstr[/^\[FORMA 2013\]/] && user_is_registered(fromstr)
subjectstr = delete_subject_recursion(subjectstr)
begin
Mail.deliver do
from fromstr
to "mailman#somedomain.com"
bcc subscriber
subject "[FORMA 2013] #{ subjectstr }"
if ehtml_part
html_part do
content_type("text/html; charset=#{ type_html }")
#content_transfer_encoding("7bit")
body BODY_BOILERPLATE_FORMAT % bodystr_html
end
end
if eplain_part
text_part do
content_type("text/plain; charset=#{ type_plain }")
#content_transfer_encoding("7bit")
body BODY_BOILERPLATE_FORMAT % bodystr_plain
end
end
if !eplain_part && !ehtml_part
body BODY_BOILERPLATE_FORMAT % body_str
charset = e_charset
end
#puts e.attachments.inspect
e.attachments.each { |a| add_file a.encoded } if e.attachments.length > 0
end
puts "1 email sent"
rescue => e
puts "error: #{ e }"
log("error sending to #{ subscriber }: #{ e },\nemail subject: #{ subjectstr }")
end
end
end
end
if e.attachments.length>0
e.attachments.each do |a|
add_file a
end
end
That can be refactored into a simple, single-line using a trailing conditional if test:
e.attachments.each { |a| add_file a.encoded } if e.attachments.length > 0
Using a single line like this is OK when you're doing something simple. Don't use them for more complex code because you'll induce visual noise, which makes it hard to understand and read your code.
But let's look at what the code above is actually doing. e.attachments in this context appears to be returning an array, or some sort of enumerable collection, otherwise each wouldn't work. length will tell us how many elements exist in the "array" (or whatever it is) that is returned by attachments.
If length is zero, then we don't want to do anything, so we could say:
e.attachments.each { |a| add_file a.encoded } unless e.attachments.empty?
(Assuming attachments implements an empty? method.)
That's kind of redundant too though. If e.attachments is empty already, what will each do? It would check to see if attachments returned an array containing any elements and if it's empty it'd skip its block entirely, effectively acting just like the trailing if condition was triggered. SOOOooo, we can use this instead:
e.attachments.each { |a| add_file a.encoded }
Ruby Style guides:
https://github.com/bbatsov/ruby-style-guide
https://github.com/styleguide/ruby
The second is based on the first.
The Tin Mans answer mostly works. I change how attachments were added since his version was not working for me.
e.attachments.each { |a| attachments[a.filename] = a.decoded } if e.attachments.length > 0

Ruby Tweetstream MongoDB Error

I keep getting the following error when running the following ruby script. If anyone can help me fix this it would be greatly appreciated. I've removed any sensitive data such as API keys.
Code:
#!/usr/bin/env ruby
require "tweetstream"
require "mongo"
require "time"
TweetStream.configure do |config|
config.consumer_key = 'KEY'
config.consumer_secret = 'SECRET'
config.oauth_token = 'TOKEN'
config.oauth_token_secret = 'TOKEN_SECRET'
config.auth_method = :oauth
end
db = Mongo::Connection.new("ds045037.mongolab.com", 45037).db("tweets")
auth = db.authenticate("DB_USERNAME", "DB_PASSWORD")
tweets = db.collection("tweetdata")
TweetStream::Daemon.new("TWITTER_USERNAME", "TWITTER_PASSWORD").track("TERM") do |status|
# Do things when nothing's wrong
data = {"created_at" => Time.parse(status.created_at), "text" => status.text, "geo" => status.geo, "coordinates" => status.coordinates, "id" => status.id, "id_str" => status.id_str}
tweets.insert({"data" => data});
end
Command to start the script:
ruby tweetscrape.rb
Ruby version:
ruby 1.9.3p429 (2013-05-15 revision 40747) [x86_64-linux]
ruby -c tweetscrape.rb produces:
Syntax OK
Error Message:
/usr/local/rvm/gems/ruby-1.9.3-p429/gems/daemons-1.1.9/lib/daemons.rb:184:in `[]=': can't convert Symbol into Integer (TypeError)
from /usr/local/rvm/gems/ruby-1.9.3-p429/gems/daemons-1.1.9/lib/daemons.rb:184:in `run_proc'
from /usr/local/rvm/gems/ruby-1.9.3-p429/gems/tweetstream-2.5.0/lib/tweetstream/daemon.rb:48:in `start'
from /usr/local/rvm/gems/ruby-1.9.3-p429/gems/tweetstream-2.5.0/lib/tweetstream/client.rb:131:in `filter'
from /usr/local/rvm/gems/ruby-1.9.3-p429/gems/tweetstream-2.5.0/lib/tweetstream/client.rb:98:in `track'
from tweetscrape.rb:19:in `<main>'
EDIT: I now have no errors using the below but nothing is entered in to the mongodb:
#!/usr/bin/env ruby
require "tweetstream"
require "mongo"
require "time"
TweetStream.configure do |config|
config.consumer_key = 'gfdsgfdsgfdsgfdsgfdsgfds'
config.consumer_secret = 'gfsdgfdsgfdsgfdsgfsdgfd'
config.oauth_token = 'gfdgfdsgfsdgfdsgfsdgf'
config.oauth_token_secret = 'hsgfsdgfsdgfsdgfds'
config.auth_method = :oauth
end
db = Mongo::Connection.new("ds045037.mongolab.com", 45037).db("tweets")
auth = db.authenticate("gfsdgfdsgfsd", "gfdsgfdsgfdsgfsd")
tweets = db.collection("tweetdata")
TweetStream::Client.new.track('TERM') do |status|
puts status.text
data = {"created_at" => Time.parse(status.created_at), "text" => status.text, "geo" => status.geo, "coordinates" => status.coordinates, "id" => status.id, "id_str" => status.id_str}
tweets.insert({"data" => data})
end
Tweets show on screen through puts though...
The initial error you were getting with the Daemon class is because you're not passing the correct parameters to the constructor. The contructor takes a string and a hash.
Moving on from that , the insert failed because:
parsing status.datetime throws an exception (its already a Time object).
status.coordinate throws an exception if there's no coordinate.
The following code works for me (note : I added growl so you can see the tweets):
#!/usr/bin/env ruby
require "tweetstream"
require "mongo"
require "time"
require 'growl'
DESIRED = %w{created_at text geo coordinates id id_str}
host= ENV["MONGO_HOST"] || 'localhost'
port = ENV["MONGO_PORT"] || 27017
username = ENV["MONGO_USERNAME"]
password = ENV["MONGO_PASSWORD"]
term = ARGV[1] || 'TERM'
begin
TweetStream.configure do |config|
config.consumer_key = ENV["TWEET_CONSUMER_KEY"]
config.consumer_secret = ENV["TWEET_CONSUMER_SECRET"]
config.oauth_token = ENV["TWEET_OAUTH_TOKEN"]
config.oauth_token_secret = ENV["TWEET_OAUTH_TOKEN_SECRET"]
config.auth_method = :oauth
end
db = Mongo::Connection.new(host, port).db("tweets")
db.authenticate(username, password)
tweets = db.collection("tweetdata")
puts "about to start tracking term #{term}"
TweetStream::Daemon.new('tracker').track(term) do |status|
Growl.notify status.text, :title => status.user.screen_name
#
# filter out nil values
# filter out all keys not in the desired array
#
data = status.attrs.select{|k,v| !v.nil? && DESIRED.include?(k.to_s)}
tweets.insert({"data" => data});
end
rescue Mongo::ConnectionFailure
puts "Connection Error : #{$!}"
rescue Mongo::AuthenticationError
puts "Auth Error : #{$!}"
rescue Mongo::MongoDBError
puts "Unexpected Error : #{$!}"
end
You'll need to setup your environment with the following correct values :
export MONGO_USERNAME="..."
export MONGO_PASSWORD="..."
export TWEET_CONSUMER_KEY="..."
export TWEET_CONSUMER_SECRET="..."
export TWEET_OAUTH_TOKEN="..."
export TWEET_OAUTH_TOKEN_SECRET="..."
Then you can start the daemon with something like (in this case we'll search for yankees):
ruby tweetscrape.rb start yankees

Resources