how to check mysql connexion - ruby

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)

Related

What condition do I check for to raise a custom error with Net::OpenTimeout execution expired error

Open-uri and nokogiri are slow to scrape the site I want hence the Net::OpenTimeout execution expired error. I attempted to code a custom error with rescue however I do not know what condition I can look for to raise that custom error.
I attempted to few if else statements however I really just guessed how to check if I was gonna get that error. I hard coded a condition that failed and thus rescued the error. I am very new to ruby and custom errors. In fact this is my first.
class Scrape
Base = 'http://www.wine.com'
##menu = []
##pages = []
def self.index
index_url = Base + "/list/wine/7155?sortBy=savings&pricemax=90"
#below is where I need to check for the condition to
raise the error
if doc = Nokogiri::HTML(open(index_url))
container = doc.css('.prodList')
wines = container.css('.prodItem')
wines.each do |wine|
##menu << {
:link => wine.css('.prodItemInfo_link').attribute('href').value,
:name => wine.css('.prodItemInfo_name').text,
:rating => (wine.css('.averageRating_average').text.to_i) > 0 ?
(wine.css('.averageRating_average').text) : 'no rating',
:price => wine.css('.productPrice_price-saleWhole').text.strip
}
end
##menu.each do |item|
Bottle.new.create(item)
end
else
begin
raise Custom_error
rescue Custom_error => error
puts error.message
end
end
end
def self.scrape_page(wine_obj)
wine_link = wine_obj.link
individual_page = Base + wine_link
docu = Nokogiri::HTML(open(individual_page))
y = docu.css('.viewMoreModule_text')
more = docu.css('.viewMoreModule_text')
##pages << {
:obj => wine_obj,
:name => docu.css('.pipName').text,
:alcohol_percent => y
x = docu.css('.mobileProdAttrs').css('.prodAlcoholPercent')
y = x.css('.prodAlcoholPercent_percent').text,
:price => docu.css('span.productPrice_price-saleWhole').text,
:origin => docu.css('span.prodItemInfo_originText a').text,
:winemaker_notes => docu.css('.viewMoreModule_text').first.text,
:more => y[2].text,
:rating => docu.css('span.averageRating_average').first.text
}
Page.create_find_by_name( ##pages.last )
end
def self.pages
##pages
end
end
class Cli
def run
puts 'loading from cyberspace'
Scrape.index
Bottle.make_list
controller
end
def controller
input = ''
response = ''
puts ' '
view
while input != 11
response = gets.chomp.to_i
input = "#{response}11".to_i
if input == 111
menu
elsif input == 11
exit
elsif input > 0 && input < 26
find_by_input(input)
elsif input != 0 && input != 111
error_1
end
end
end
def view
puts "welcome to the wine bar"
puts "================="
puts " W I N E "
puts " B A R "
puts "================="
puts " "
puts "type 1 for list of wine"
puts " "
puts "type 0 to exit "
end
def menu
wines = Bottle.list
second_input = ''
while second_input != 0
puts "<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>"
puts "type the corresponding number to view more wine info"
puts
"__________________________________________________________________"
wines.each do |wine|
puts "#{wine.index}) #{wine.name} #{wine.price}"
end
second_input = gets.chomp.to_i
if second_input > 0 && second_input < 26
find_by_input(second_input)
elsif second_input == 0
exit
second_input = 0
elsif second_input > 25 && second_input != 101
error_1
end
end
puts <<-DOC
the the wine number again
for winemaker notes
DOC
end
def find_by_input(input)
while input != 0
selection = Bottle.find_by_input(input)
puts "NAME: #{selection.name}"
puts "PRICE: $#{selection.price}"
puts "RATING: #{selection.rating}"
puts "________________________________________"
puts " type #{input} again "
puts " for more info "
puts " provided by the winemaker "
# reseting input and extending user control functionality
third_input = ''
third_input = gets.chomp.to_i
if third_input == selection.index
response = Scrape.scrape_page(selection)
view_2(response, third_input)
elsif input == 0
exit
end
end
end
def view_2(response, old_input)
next_input = ''
while next_input != 0
puts "Alcohol Percent: #{response.alcohol_percent}"
puts "Winemaker Notes: #{response.winemaker_notes}"
puts " "
puts "Type #{old_input} again for more!!"
next_input = gets.chomp.to_i
if next_input == old_input
input = 0
next_input = 0
# refacort as it puts out 88 again and should not. Also 0 is not
exiting with correct behavior
# refactor so looking for "#{input}"1 to prevent the recall of
input
more(response)
end
end
end
def more(response)
puts response.more
puts menu
end
def error_1
puts " WHOA coder "
puts "type a better number!"
end
def exit
puts <<-DOC
well that was fun
Thank you for checking out
my first cli program
DOC
end
end ```
```class Page
attr_accessor :alcohol_percent, :price, :name, :origin, :winemaker_notes,
:rating, :more, :obj
##web_pages = []
def self.create_find_by_name(hash)
if answer = ##web_pages.find{ |obj| obj.name == hash[:name]}
answer
else
self.new.create(hash)
end
end
def create(hash)
hash.each do |key, value|
self.send(("#{key}="), value)
end
save
view_more
end
def view_more
##web_pages.last
end
def save
##web_pages << self
end
end
attr_accessor :link, :name, :price, :rating, :index
##bottles = []
def create(hash)
hash.each do |key, words|
self.send(("#{key}="), words )
end
save
end
def save
##bottles << self
end
def self.make_list
##numbered_list = ##bottles.sort{ |x,y| x.price <=>
y.price}.map.with_index(1) do
|w,i| w.index = i
w
end
end
def self.list
##numbered_list
end
def self.find_by_input(input)
a = ##numbered_list.find{ |wine| wine.index == input}
# puts "#{a.name} $#{a.price} rating: #{a.rating}"
# puts "type #{input} again for winemaker notes"
# more = ''
# while more != 0
# more = gets.chomp.to_i
# (input == more) ? (Scrape.scrape_page(a.link)) : (self.list)
# end
end
end
class Scrape
Base = 'http://www.wine.com'
##menu = []
##pages = []
def self.index
index_url = Base + "/list/wine/7155?sortBy=savings&pricemax=90"
if doc = Nokogiri::HTML(open(index_url))
container = doc.css('.prodList')
wines = container.css('.prodItem')
wines.each do |wine|
##menu << {
:link => wine.css('.prodItemInfo_link').attribute('href').value,
:name => wine.css('.prodItemInfo_name').text,
:rating => (wine.css('.averageRating_average').text.to_i) > 0 ?
(wine.css('.averageRating_average').text) : 'no rating',
:price => wine.css('.productPrice_price-saleWhole').text.strip
}
end
##menu.each do |item|
Bottle.new.create(item)
end
else
begin
raise Custom_error
rescue Custom_error => error
puts error.message
end
end
end
def self.scrape_page(wine_obj)
wine_link = wine_obj.link
individual_page = Base + wine_link
docu = Nokogiri::HTML(open(individual_page))
y = docu.css('.viewMoreModule_text')
more = docu.css('.viewMoreModule_text')
##pages << {
:obj => wine_obj,
:name => docu.css('.pipName').text,
alcholo = docu.css('.mobileProdAttrs').css('.prodAlcoholPercent'),
:alcohol_percent => alcholo.css('.prodAlcoholPercent_percent').text,
:price => docu.css('span.productPrice_price-saleWhole').text,
:origin => docu.css('span.prodItemInfo_originText a').text,
:winemaker_notes => docu.css('.viewMoreModule_text').first.text,
:more => y[2].text,
:rating => docu.css('span.averageRating_average').first.text
}
Page.create_find_by_name( ##pages.last )
end
def self.pages
##pages
end
end
When the internet connection is down/too slow the custom error is raised.
When an exception is thrown, the program stops its normal flow. You need to surround the part of the code that can throw an exception with a begin..rescue clause, and attempt to handle it, re-raise it, or raise another exception instead.
In your example, that would be:
begin
Nokogiri::HTML(open(url))
rescue Net::OpenTimeoutError => e
# log the error message if needed, raise your CustomError instead
raise CustomError, e.message
end
You can omit the begin, and put a rescue clause at the end of the method, ruby will interpret this as if the entire method body was wrapped in a begin..rescue block, something like this:
def open_page(url)
return Nokogiri::HTML(open(url))
rescue Net::OpenTimeoutError => e
raise CustomError, e.message
end

How to use a variable from one method to other in a same class in Ruby?

I am new to Ruby. I have the below code in my controller.
Desired Behaviour:-
I want to display the validation error string on my views on edit page. So I am putting those errors in a variable. When validation fails then I want to use that variable in my edit method, so that I can display that on my edit page view.
Observed behavior:-
There is a variable #vpinerr in create method. I want to use that variable in edit method. I have tried to use the class variable (##vpinerr) and initialized it with an empty string (##vpinerr = "") then the value of this variable becomes empty in edit method.
require 'rho/rhocontroller'
require 'helpers/browser_helper'
class LeadController < Rho::RhoController
include BrowserHelper
# GET /Lead
def index
#leads = Lead.find(:all)
render :back => '/app'
end
# GET /Lead/new
def new
#lead = Lead.new
render :action => :new, :back => url_for(:action => :index)
end
def create
# Update
if Lead.find(#params['id'])
#lead = Lead.find(#params['id'])
# array of objects
#leadadd = LeadAddress.find(:all,
:conditions => {:parentKey => #lead.object}
)
#leadcon = LeadContact.find(:all,
:conditions => {:parentKey => #lead.object}
)
#hash of hashes
leadaddressArray = #params['leadaddress']
arr1 = #leadadd.count - 1
for i in 0..arr1
j=i.to_s
#leadaddHash = #leadadd[i]
leadaddressHash = leadaddressArray[j]
if leadaddressHash['removed'] == "1"
singleadd = LeadAddress.find(:first,
:conditions => {:object => leadaddressHash['object']}
)
singleadd.destroy if singleadd
else
#validation
vpin = leadaddressHash['pincode']
#validation check
if vpin =~ /^[[:digit:]]+$/
#leadaddHash.update_attributes(leadaddressHash) if #leadaddHash
else
err = 1
#vpinerr = "Pincode is invalid"
end
end
end
leadconArray = #params['leadcontact']
arr2 = #leadcon.count - 1
for k in 0..arr2
z=k.to_s
#leadconHash = #leadcon[k]
leadContact = leadconArray[z]
if leadContact['removed'] == "1"
singlecon = LeadContact.find(:first,
:conditions => {:object => leadContact['object']}
)
singlecon.destroy if singlecon
else
#leadconHash.update_attributes(leadContact) if #leadconHash
end
end
#lead.update_attributes(#params['lead']) if #lead
if err == 0
redirect :action => :index
else
redirect :action => :edit, :id => #lead.object, :vpin =>#vpinerr
end
else
# Create
err = 0
# validation
vlead = #params['lead']
vfirstname = vlead['firstname']
vlastname = vlead['lastname']
vage = vlead['age']
#validation check
if (vfirstname =~ /^[[:alpha:][:blank:]]+$/) and (vlastname =~ /^[[:alpha:][:blank:]]+$/) and (vage =~ /^[[:digit:]]+$/)
#lead = Lead.create(#params['lead'])
#key = #lead.object
else
err = 1
#basicerr = "Basic Details are invalid"
end
if #params['leadaddress']
leadaddressArray = #params['leadaddress']
arrcount = leadaddressArray.count
for i in 1..arrcount
j=(i-1).to_s
leadaddressHash = leadaddressArray[j]
#validation
vpin = leadaddressHash['pincode']
#validation check
if vpin =~ /^[[:digit:]]+$/
#leadAdd = LeadAddress.create(leadaddressHash)
#leadAdd.parentKey = #key
#leadAdd.save()
else
err = 1
#vpinerr = "Pincode is invalid"
end
end
end
if #params['leadcontact']
leadconArray = #params['leadcontact']
arrcount2 = leadconArray.count
for k in 1..arrcount2
h=(k-1).to_s
leadconHash = leadconArray[h]
#validation
vhome = leadconHash['home']
vmobile = leadconHash['mobile']
vemail = leadconHash['email']
#validation check
if (vhome =~ /^[[:digit:]]+$/) and (vmobile =~ /^[[:digit:]]+$/) and (vemail =~ /\A([\w+\-]\.?)+#[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i)
#leadcontact = LeadContact.create(leadconHash)
#leadcontact.parentKey = #key
#leadcontact.save()
else
err = 1
#contacterr = "Contact Details are invalid"
end
end
end
if err == 0
redirect :action => :index
else
redirect :action => :edit, :id => #lead.object
end
end
end
# GET /Lead/{1}
def show
#lead = Lead.find(#params['id'])
#leadadd = LeadAddress.find(:all,
:conditions => {:parentKey => #lead.object}
)
#leadcontact = LeadContact.find(:all,
:conditions => {:parentKey => #lead.object}
)
if #lead
render :action => :show, :back => url_for(:action => :index)
else
redirect :action => :index
end
end
# GET /Lead/{1}/edit
def edit
#lead = Lead.find(#params['id'])
#leadaddress = LeadAddress.find(:all,
:conditions => {:parentKey => #lead.object}
)
#leadcontact = LeadContact.find(:all,
:conditions => {:parentKey => #lead.object}
)
#vpinerr2 = #vpinerr
if #lead
render :action => :new, :back => url_for(:action => :index)
else
redirect :action => :index
end
end
end
Variables with a prepending # are considered as instance variables and are available in a class's instance. Your controller is a class and with every request, Rails instantiates a new controller instance. In that sense, when you make a request to the create action, a new instance is created and #vpinerr is set in the instance. When you redirect the user to the edit action, its a new request and a new controller instance is instantiated. Since the instances from create action and edit actions are different, you won't have the value of #vpinerr in the edit action.
You have alternatives.
Class-level variables.
Class-level variables are set on the class and are available in all instances. Any variable prepended with ## are class variables. Change to ##vpinerr everywhere instead of #vpinerr.
This would be wrong to use in your case because, you could want it to be different for each user but using class variable will keep the value for other users too until its changed. Read about class variables: http://www.railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby
Session variables.
Session variables are used to save variables within a session. They can be shared between controllers too. To set a session variable session[:vpinerr] = "Some error" and to use it, you can simple call session[:vpinerr].

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"

how to excute code on webrick server

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

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

Resources