After a process why Memory continuously stay up in Ruby? - ruby-on-rails

I'm using Rails 4 with Ruby 2.1.0. I have a code which taking about 2 GB of memory to complete process, but problem is after finish process...why is memory usage still up?
I also assign nil to variable after used which save 300 MB but still large amount of memory using by Ruby process.
Here is sample code to reproduce the problem:
def download_data(params, options = {})
$file_name = ''
portfolio_names = Portfolio.get_names
building_names = Building.get_names
tenant_names = Tenant.get_names
meter_names = Meter.get_meter_names
#portfolio_info, #building_info, #tenant_info, #meter_id, #from_date, #to_date = params[:portfolio_name], params[:building_name], params[:tenant_name], params[:meter_id], params[:from_date], params[:to_date]
#from_date = DateTime.parse(#from_date).to_i
#to_date = DateTime.parse(#to_date).to_i
#building_f_name = building_names["#{#building_info}"]
unless params[:fields].nil?
#fields = params[:fields].split('_')
#columns = []
#fields.each do |f|
if f.length > 0
#columns << MeterData.new.show_real_value_of_meter_data_field_revert(f).to_sym
end
end
#columns << 'date_time'.to_sym
#columns << 'tenant'.to_sym
#columns << 'meter_id'.to_sym
else
#columns = [:id, :date_time, :w3pht, :whintvlrec, :w__3phmaxavgdmd, :tenant, :meter_id]
end
#### database fetch ###########
#meter_data = MeterData.find_by_sql("SELECT tenant, meter_id, SUM(van) as van, SUM(vbn) as vbn,
SUM(vcn) as vcn, SUM(ia) as ia, SUM(ib) as ib, SUM(ic) as ic,
SUM(w3pht) as w3pht, SUM(pf3pht) as pf3pht, SUM(f) as f,
SUM(whrec) as whrec, SUM(whtot) as whtot, SUM(varhrec) as varhrec,
SUM(varhtot) as varhtot, SUM(whintvlrec) as whintvlrec,
SUM(whintvldel) as whintvldel, SUM(w__phavg) as w__phavg,
SUM(var__3phavg) as var__3phavg, SUM(w_3phavg) as w_3phavg,
SUM(var_3phavg) as var_3phavg, SUM(phai) as phai, SUM(phbi) as phbi,
SUM(phci) as phci, SUM(w__3phmaxavgdmd) as w__3phmaxavgdmd,
MAX(w__3phmaxavgdmd) as w__3phmaxavgdmd_max, SUM(var__3phmaxavgdmd) as var__3phmaxavgdmd,
SUM(w_3phmaxavgdmd) as w_3phmaxavgdmd, SUM(var_3phmaxavgdmd) as var_3phmaxavgdmd,
date_time FROM `meter_data` WHERE (`date_time_i` >= #{#from_date} AND `date_time_i` <= #{#to_date}
AND building = '#{#building_info}') GROUP by tenant, meter_id, date_time
ORDER BY `meter_data`.`date_time_i` ASC")
sleep 0.5
#meter_sum = MeterData.find_by_sql("SELECT meter_id, SUM(van) as van, SUM(vbn) as vbn, SUM(vcn) as vcn,
SUM(ia) as ia, SUM(ib) as ib, SUM(ic) as ic, SUM(w3pht) as w3pht,
SUM(pf3pht) as pf3pht, SUM(f) as f, SUM(whrec) as whrec,
SUM(whtot) as whtot, SUM(varhrec) as varhrec, SUM(varhtot) as varhtot,
SUM(whintvlrec) as whintvlrec, SUM(whintvldel) as whintvldel,
SUM(w__phavg) as w__phavg, SUM(var__3phavg) as var__3phavg,
SUM(w_3phavg) as w_3phavg, SUM(var_3phavg) as var_3phavg,
SUM(phai) as phai, SUM(phbi) as phbi, SUM(phci) as phci,
SUM(w__3phmaxavgdmd) as w__3phmaxavgdmd, MAX(w__3phmaxavgdmd) as w__3phmaxavgdmd_max,
SUM(var__3phmaxavgdmd) as var__3phmaxavgdmd, SUM(w_3phmaxavgdmd) as w_3phmaxavgdmd,
SUM(var_3phmaxavgdmd) as var_3phmaxavgdmd, date_time FROM `meter_data`
WHERE (`date_time_i` >= #{#from_date} AND `date_time_i` <= #{#to_date} AND building = '#{#building_info}')
GROUP by meter_id ORDER BY `meter_data`.`date_time_i` ASC")
#meter_data_max = MeterData.find_by_sql("SELECT tenant, meter_id, MAX(w__3phmaxavgdmd) as w__3phmaxavgdmd,
date_time FROM `meter_data` WHERE (`date_time_i` >= #{#from_date} AND `date_time_i` <= #{#to_date}
AND building = '#{#building_info}') GROUP by tenant, meter_id
ORDER BY `meter_data`.`date_time_i` ASC")
sleep 0.5
#uniq_meter_id = MeterData.select(:meter_id).where("`date_time_i` >= #{#from_date} AND `date_time_i` <= #{#to_date} AND building = '#{#building_info}'").uniq(:meter_id)
#### database fetch ###########
p = Axlsx::Package.new
wb = p.workbook
wb.styles do |s|
styles_hash = AxlsxStylesHash.get s
wb.add_worksheet(:name => "Building data details") do |sheet|
$row_num = 0
meter_extra = MeterExtra.new
columns_ = []; #columns.each { |s| columns_ << "#{s}_".to_s }
sheet.add_row []
$row_num += 1
sheet.add_row ["Building report of #{#building_f_name} #{#from_date} to #{#to_date}"], :style => styles_hash[:heading_cell]
$row_num += 1
sheet.add_row []
$row_num += 1
sheet.add_row []
$row_num += 1
sheet.merge_cells("A2:Q2")
new_columns_ = []
new_columns_ << "Date & Time" if columns_.include?('date_time_')
new_columns_ << "Building" if columns_.include?('building_')
new_columns_ << "Tenant" if columns_.include?('tenant_')
new_columns_ << "Meter ID" if columns_.include?('meter_id_')
new_columns_ << "Meter Name" if columns_.include?('meter_id_')
new_columns_ << "van" if columns_.include?('van_')
new_columns_ << "vbn" if columns_.include?('vbn_')
new_columns_ << "vcn" if columns_.include?('vcn_')
new_columns_ << "ia" if columns_.include?('ia_')
new_columns_ << "ib" if columns_.include?('ib_')
new_columns_ << "ic" if columns_.include?('ic_')
new_columns_ << "w3pht" if columns_.include?('w3pht_')
new_columns_ << "pf3pht" if columns_.include?('pf3pht_')
new_columns_ << "f" if columns_.include?('f_')
new_columns_ << "whrec" if columns_.include?('whrec_')
new_columns_ << "whtot" if columns_.include?('whtot_')
new_columns_ << "varhrec" if columns_.include?('varhrec_')
new_columns_ << "varhtot" if columns_.include?('varhtot_')
new_columns_ << "whintvlrec" if columns_.include?('whintvlrec_')
new_columns_ << "whintvldel" if columns_.include?('whintvldel_')
new_columns_ << "w+phavg" if columns_.include?('w__phavg_')
new_columns_ << "var+3phavg" if columns_.include?('var__3phavg_')
new_columns_ << "w-3phavg" if columns_.include?('w_3phavg_')
new_columns_ << "var-3phavg" if columns_.include?('var_3phavg_')
new_columns_ << "phai" if columns_.include?('phai_')
new_columns_ << "phbi" if columns_.include?('phbi_')
new_columns_ << "phci" if columns_.include?('phci_')
new_columns_ << "w+3phmaxavgdmd" if columns_.include?('w__3phmaxavgdmd_')
new_columns_ << "var+3phmaxavgdmd" if columns_.include?('var__3phmaxavgdmd_')
new_columns_ << "w-3phmaxavgdmd" if columns_.include?('w_3phmaxavgdmd_')
new_columns_ << "var-3phmaxavgdmd" if columns_.include?('var_3phmaxavgdmd_')
sheet.add_row new_columns_, :style => styles_hash[:green_bold_border_cell]
$row_num += 1
t = 1; #meter_data.each do |m|
new_columns_data = []
if columns_.include?('date_time_')
m_date_time = m['date_time']
new_columns_data << ( m_date_time.nil? ? '--' : m_date_time)
end
if columns_.include?('building_')
m_building = m_building
new_columns_data << ( m_building.nil? ? '--' : building_names["#{m_building}"])
end
if columns_.include?('tenant_')
m_tenant = m['tenant']
new_columns_data << ( m_tenant.nil? ? '--' : tenant_names["#{m_tenant}"])
end
if columns_.include?('meter_id_')
m_meter_id = m['meter_id']
new_columns_data << ( m_meter_id.nil? ? '--' : m_meter_id)
end
if columns_.include?('meter_id_')
m_meter_id = m['meter_id']
new_columns_data << ( meter_extra.get_meter_name(m_meter_id.nil? ? '--' : m_meter_id) )
end
if columns_.include?('van_')
m_van = m.van
new_columns_data << ( m_van.nil? ? '--' : m_van )
end
if columns_.include?('vbn_')
m_vbn = m.vbn
new_columns_data << ( m_vbn.nil? ? '--' : m_vbn )
end
if columns_.include?('vcn_')
m_vcn = m.vcn
new_columns_data << ( m_vcn.nil? ? '--' : m_vcn )
end
if columns_.include?('ia_')
m_ia = m.ia
new_columns_data << ( m_ia.nil? ? '--' : m_ia )
end
if columns_.include?('ib_')
m_ib = m.ib
new_columns_data << ( m_ib.nil? ? '--' : m_ib )
end
if columns_.include?('ic_')
m_ic = m.ic
new_columns_data << ( m_ic.nil? ? '--' : m_ic )
end
if columns_.include?('w3pht_')
m_w3pht = m.w3pht
new_columns_data << ( m_w3pht.nil? ? '--' : m_w3pht )
end
if columns_.include?('pf3pht_')
m_pf3pht = m.pf3pht
new_columns_data << ( m_pf3pht.nil? ? '--' : m_pf3pht )
end
if columns_.include?('f_')
m_f = m.f
new_columns_data << ( m_f.nil? ? '--' : m_f )
end
if columns_.include?('whrec_')
m_whrec = m.whrec
new_columns_data << ( m_whrec.nil? ? '--' : m_whrec )
end
if columns_.include?('whtot_')
m_whtot = m.whtot
new_columns_data << ( m_whtot.nil? ? '--' : m_whtot )
end
if columns_.include?('varhrec_')
m_varhrec = m.varhrec
new_columns_data << ( m_varhrec.nil? ? '--' : m_varhrec )
end
if columns_.include?('varhtot_')
m_varhtot = m.varhtot
new_columns_data << ( m_varhtot.nil? ? '--' : m_varhtot )
end
if columns_.include?('whintvlrec_')
m_whintvlrec = m.whintvlrec
new_columns_data << ( m_whintvlrec.nil? ? '--' : m_whintvlrec )
end
if columns_.include?('whintvldel_')
m_whintvldel = m.whintvldel
new_columns_data << ( m_whintvldel.nil? ? '--' : m_whintvldel )
end
if columns_.include?('w__phavg_')
m_w__phavg = m.w__phavg
new_columns_data << ( m_w__phavg.nil? ? '--' : m_w__phavg )
end
if columns_.include?('var__3phavg_')
m_var__3phavg = m.var__3phavg
new_columns_data << ( m_var__3phavg.nil? ? '--' : m_var__3phavg )
end
if columns_.include?('w_3phavg_')
m_w_3phavg = m.w_3phavg
new_columns_data << ( m_w_3phavg.nil? ? '--' : m_w_3phavg )
end
if columns_.include?('var_3phavg_')
m_var_3phavg = m.var_3phavg
new_columns_data << ( m_var_3phavg.nil? ? '--' : m_var_3phavg )
end
if columns_.include?('phai_')
m_phai = m.phai
new_columns_data << ( m_phai.nil? ? '--' : m_phai )
end
if columns_.include?('phbi_')
m_phbi = m.phbi
new_columns_data << ( m_phbi.nil? ? '--' : m_phbi )
end
if columns_.include?('phci_')
m_phci = m.phci
new_columns_data << ( m_phci.nil? ? '--' : m_phci )
end
if columns_.include?('w__3phmaxavgdmd_')
m_w__3phmaxavgdmd = m.w__3phmaxavgdmd
new_columns_data << ( m_w__3phmaxavgdmd.nil? ? '--' : m_w__3phmaxavgdmd )
end
if columns_.include?('var__3phmaxavgdmd_')
m_var__3phmaxavgdmd = m.var__3phmaxavgdmd
new_columns_data << ( m_var__3phmaxavgdmd.nil? ? '--' : m_var__3phmaxavgdmd )
end
if columns_.include?('w_3phmaxavgdmd_')
m_w_3phmaxavgdmd = m.w_3phmaxavgdmd
new_columns_data << (m_w_3phmaxavgdmd.nil? ? '--' : m_w_3phmaxavgdmd )
end
if columns_.include?('var_3phmaxavgdmd_')
m_var_3phmaxavgdmd = m.var_3phmaxavgdmd
new_columns_data << ( m_var_3phmaxavgdmd.nil? ? '--' : m_var_3phmaxavgdmd )
end
if t == 1
sheet.add_row new_columns_data , :style => styles_hash[:simple_green_cell], :widths=>[20]
else
sheet.add_row new_columns_data, :style => styles_hash[:simple_white_cell], :widths=>[20]
end
$row_num += 1
t = 0 if t == 2
t += 1
puts $row_num
m = nil
end
#meter_data = nil
## logo ##
ReportBillLogo.put sheet, $row_num
sheet = nil;
end
## summary calculation ##
wb.add_worksheet(:name => "Summary") do |sheet|
$row_num = 0
sheet.add_row []
$row_num += 1
sheet.add_row ["Summary report of #{#building_f_name} #{#from_date} to #{#to_date}"], :style => styles_hash[:heading_cell]
$row_num += 1
sheet.add_row []
$row_num += 1
sheet.add_row []
$row_num += 1
sheet.merge_cells("A1:Q1")
columns_ = []; #columns.each { |s| columns_ << "#{s}_".to_s }
new_columns_ = []
new_columns_ << "Meter ID"
new_columns_ << "Meter Name"
new_columns_ << "Max KW"
sheet.add_row new_columns_, :style => styles_hash[:green_bold_border_cell]
$row_num += 1
t = 0
#meter_data_max.each do |m|
new_columns_data = []
new_columns_data << m.meter_id
new_columns_data << meter_names["#{m.meter_id}"]
new_columns_data << ( m.w__3phmaxavgdmd.nil? ? '' : m.w__3phmaxavgdmd )
if t == 1
sheet.add_row new_columns_data, :style => styles_hash[:simple_green_cell], :widths=>[25]
else
sheet.add_row new_columns_data, :style => styles_hash[:simple_white_cell], :widths=>[25]
end
$row_num += 1
t = 0 if t == 2
t += 1
m = nil;
end
## logo ##
ReportBillLogo.put sheet, $row_num
sheet = nil
end
## summary calculation ##
## summary calculation ##
wb.add_worksheet(:name => "Energy consumed") do |sheet|
$row_num = 0
sheet.add_row []
$row_num += 1
sheet.add_row ["Energy consumed report of #{#building_f_name} #{#from_date} to #{#to_date}"], :style => styles_hash[:heading_cell]
$row_num += 1
sheet.add_row []
$row_num += 1
sheet.add_row []
$row_num += 1
sheet.merge_cells("A2:Q2")
engery = []
#uniq_meter_id.each do |f|
start = MeterData.find_by_sql("select whtot from meter_data where `date_time_i` >= #{#from_date} AND meter_id = '#{f.meter_id}' ORDER BY date_time_i ASC limit 1")
eand = MeterData.find_by_sql("select whtot from meter_data where `date_time_i` <= #{#from_date} AND meter_id = '#{f.meter_id}' ORDER BY date_time_i DESC limit 1")
sleep 0.009
begin
engery << (eand.last.whtot.to_i - start.first.whtot.to_i)
rescue
engery << '--'
end
start = nil; eand = nil;
f = nil;
end
columns_ = []; #columns.each { |s| columns_ << "#{s}_".to_s }
new_columns_ = []
new_columns_ << "Meter ID"
new_columns_ << "Meter Name"
new_columns_ << "Subtraction result"
new_columns_ << "Aggregate result"
sheet.add_row new_columns_, :style => styles_hash[:green_bold_border_cell]
$row_num += 1
flage = 0
t = 0
#meter_sum.each do |m|
new_columns_data = []
new_columns_data << m.meter_id
new_columns_data << meter_names["#{m.meter_id}"]
new_columns_data << engery[flage]
new_columns_data << m.whintvlrec
if t == 1
sheet.add_row new_columns_data, :style => styles_hash[:simple_green_cell], :widths=>[25]
else
sheet.add_row new_columns_data, :style => styles_hash[:simple_white_cell], :widths=>[25]
end
$row_num += 1
flage += 1
t = 0 if t == 2
t += 1
m = nil
end
## logo ##
ReportBillLogo.put sheet, $row_num
sheet = nil;
end
end
$file_name = "tmp/#{#building_info} . #{#from_date} - #{#to_date} _ #{Time.new.to_i}.xlsx"
p.serialize($file_name)
p = nil; wb = nil;
#meter_data = nil; #meter_data_max = nil; #meter_sum = nil;
return $file_name
end
# total records = 5, 00, 000

When ruby process is running out of memory it access a huge bit of memory from the system called heap slab. This big chunk is then internally divided into many small bits, which holds your variables and your code. When you assign nil to some variable, garbage collector will mark this small bit as empty, but the whole slab is never returned to the system until process is terminated.

I'm not exactly sure if this is actually the problem that you're having, but there's a known issue with Ruby 2.1.x's generational garbage collection where allocated objects in memory that are supposed to be "short-lived" end up being accidentally promoted to "long-lived" instead, causing memory to bloat because the garbage collector doesn't run frequently enough to clean up these objects:
Koichi Sasada, the author of the generational GC in Ruby 2.1:
“Some ‘short-lived’ young objects will be promoted to ‘old-gen’ accidentally….if such ‘short-lived’ objects consume huge memory we need to free such objects.”
A current workaround that is being mentioned a lot right now in the Ruby community is to change a default Ruby setting in order to tell it to garbage collect more often:
Expect memory doubling with Ruby 2.1.1. Not happy with that? You have 2 options:
Tune it down by reducing RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR. At 1 your memory consumption will be on par with 2.0. It ships with the 2 default.
Option 2, wait for a future release of Ruby, this will be fixed in 2.2 maybe even patched a bit more in 2.1.2 . See:
https://bugs.ruby-lang.org/issues/9607 and
http://vimeo.com/89491942 and
https://speakerdeck.com/samsaffron/why-ruby-2-dot-1-excites-me

Related

how to keep old activerecord 2.3 associations.rb in updated rails3.1 app

I have some inherited code:
I have an Rails 2.3 app that I've updated to Rails 3.1
Main problem:
Inside this code I inherited is a file using these deprecated methods
alias_method_chain :association_join, :fix
and
alias_method_chain :construct_joins, :fix
association_join and construct_joins are deprecated and I don't know what should replace them. Does anyone know what I can refactor these to? I can't seem to find any info online at all. Or is there a gem that can fix this deprecation issue?
Inside the app there is a rails 2.3 "fix" file for the associations and it is now failing under the Rails 3.1 update...the general structure of the file is listed below for clarity.
"fix" file
module ActiveRecord
module Associations
module ClassMethods
class JoinDependency
class JoinAssociation
def association_join_with_fix
...
end
alias_method_chain :association_join, :fix
end
end
end
end
end
module ActiveRecord
module Associations
class HasManyThroughAssociation
def construct_joins_with_fix(custom_joins = nil)
...
end
alias_method_chain :construct_joins, :fix
end
end
end
.
.
.
Entire file listed below for the interested...
module ActiveRecord
module Associations
module ClassMethods
class JoinDependency
class JoinAssociation
def association_join_with_fix
connection = reflection.active_record.connection
join = case reflection.macro
when :has_and_belongs_to_many
" #{join_type} %s ON %s.%s = %s.%s " % [
table_alias_for(options[:join_table], aliased_join_table_name),
connection.quote_table_name(aliased_join_table_name),
options[:foreign_key] || reflection.active_record.to_s.foreign_key,
connection.quote_table_name(parent.aliased_table_name),
reflection.active_record.primary_key] +
" #{join_type} %s ON %s.%s = %s.%s " % [
table_name_and_alias,
connection.quote_table_name(aliased_table_name),
klass.primary_key,
connection.quote_table_name(aliased_join_table_name),
options[:association_foreign_key] || klass.to_s.foreign_key
]
when :has_many, :has_one
case
when reflection.options[:through]
through_conditions = through_reflection.options[:conditions] ? "AND #{interpolate_sql(sanitize_sql(through_reflection.options[:conditions]))}" : ''
jt_foreign_key = jt_as_extra = jt_source_extra = jt_sti_extra = nil
first_key = second_key = as_extra = nil
if through_reflection.options[:as] # has_many :through against a polymorphic join
jt_foreign_key = through_reflection.options[:as].to_s + '_id'
jt_as_extra = " AND %s.%s = %s" % [
connection.quote_table_name(aliased_join_table_name),
connection.quote_column_name(through_reflection.options[:as].to_s + '_type'),
klass.quote_value(parent.active_record.base_class.name)
]
else
jt_foreign_key = through_reflection.primary_key_name
end
case source_reflection.macro
when :has_many
if source_reflection.options[:as]
first_key = "#{source_reflection.options[:as]}_id"
second_key = options[:foreign_key] || primary_key
as_extra = " AND %s.%s = %s" % [
connection.quote_table_name(aliased_table_name),
connection.quote_column_name("#{source_reflection.options[:as]}_type"),
klass.quote_value(source_reflection.active_record.base_class.name)
]
else
first_key = source_reflection.association_foreign_key # through_reflection.klass.base_class.to_s.foreign_key
second_key = source_reflection.primary_key_name # options[:foreign_key] || primary_key
end
unless through_reflection.klass.descends_from_active_record?
jt_sti_extra = " AND %s.%s = %s" % [
connection.quote_table_name(aliased_join_table_name),
connection.quote_column_name(through_reflection.active_record.inheritance_column),
through_reflection.klass.quote_value(through_reflection.klass.sti_name)]
end
when :belongs_to
first_key = primary_key
if reflection.options[:source_type]
second_key = source_reflection.association_foreign_key
jt_source_extra = " AND %s.%s = %s" % [
connection.quote_table_name(aliased_join_table_name),
connection.quote_column_name(reflection.source_reflection.options[:foreign_type]),
klass.quote_value(reflection.options[:source_type])
]
else
second_key = source_reflection.primary_key_name
end
end
" #{join_type} %s ON (%s.%s = %s.%s%s%s%s) " % [
table_alias_for(through_reflection.klass.table_name, aliased_join_table_name),
connection.quote_table_name(aliased_join_table_name),
connection.quote_column_name(parent.primary_key),
connection.quote_table_name(parent.aliased_table_name),
connection.quote_column_name(jt_foreign_key),
jt_as_extra, jt_source_extra, jt_sti_extra
] +
" #{join_type} %s ON (%s.%s = %s.%s%s) " % [
table_name_and_alias,
connection.quote_table_name(aliased_table_name),
connection.quote_column_name(first_key),
connection.quote_table_name(aliased_join_table_name),
connection.quote_column_name(second_key),
as_extra
]
when reflection.options[:as] && [:has_many, :has_one].include?(reflection.macro)
" #{join_type} %s ON %s.%s = %s.%s AND %s.%s = %s" % [
table_name_and_alias,
connection.quote_table_name(aliased_table_name),
"#{reflection.options[:as]}_id",
connection.quote_table_name(parent.aliased_table_name),
parent.primary_key,
connection.quote_table_name(aliased_table_name),
"#{reflection.options[:as]}_type",
klass.quote_value(parent.active_record.base_class.name)
]
else
foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key
" #{join_type} %s ON %s.%s = %s.%s " % [
table_name_and_alias,
aliased_table_name,
foreign_key,
parent.aliased_table_name,
reflection.options[:primary_key] || parent.primary_key
]
end
when :belongs_to
" #{join_type} %s ON %s.%s = %s.%s " % [
table_name_and_alias,
connection.quote_table_name(aliased_table_name),
reflection.klass.primary_key,
connection.quote_table_name(parent.aliased_table_name),
options[:foreign_key] || reflection.primary_key_name
]
else
""
end || ''
join << %(AND %s) % [
klass.send(:type_condition, aliased_table_name)] unless klass.descends_from_active_record?
[through_reflection, reflection].each do |ref|
join << "AND #{interpolate_sql(sanitize_sql(ref.options[:conditions], aliased_table_name))} " if ref && ref.options[:conditions]
end
join
end
alias_method_chain :association_join, :fix
end
end
end
end
end
module ActiveRecord
module Associations
class HasManyThroughAssociation
def construct_joins_with_fix(custom_joins = nil)
polymorphic_join = nil
if #reflection.source_reflection.macro == :belongs_to
reflection_primary_key = #reflection.klass.primary_key
source_primary_key = #reflection.source_reflection.primary_key_name
if #reflection.options[:source_type]
polymorphic_join = "AND %s.%s = %s" % [
#reflection.through_reflection.quoted_table_name, "#{#reflection.source_reflection.options[:foreign_type]}",
#owner.class.quote_value(#reflection.options[:source_type])
]
end
else
reflection_primary_key = #reflection.source_reflection.primary_key_name
source_primary_key = #reflection.source_reflection.association_foreign_key
if #reflection.source_reflection.options[:as]
polymorphic_join = "AND %s.%s = %s" % [
#reflection.quoted_table_name, "#{#reflection.source_reflection.options[:as]}_type",
#owner.class.quote_value(#reflection.through_reflection.klass.name)
]
end
end
"INNER JOIN %s ON %s.%s = %s.%s %s #{#reflection.options[:joins]} #{custom_joins}" % [
#reflection.through_reflection.quoted_table_name,
#reflection.quoted_table_name, reflection_primary_key,
#reflection.through_reflection.quoted_table_name, source_primary_key,
polymorphic_join
]
end
alias_method_chain :construct_joins, :fix
end
end
end
module ActiveRecord
module Reflection
class AssociationReflection
def association_foreign_key_with_fix
#association_foreign_key ||= #options[:primary_key] || class_name.foreign_key
end
alias_method_chain :association_foreign_key, :fix
end
end
end
### EFFECTIVE DIFFERENCE ###
# --- /usr/lib/ruby/1.8/active_record/associations.rb.original 2012-02-25 10:58:08.000000000 -0800
# +++ /usr/lib/ruby/1.8/active_record/associations.rb 2012-02-25 12:19:49.000000000 -0800
# ## -2096,8 +2096,8 ##
# klass.quote_value(source_reflection.active_record.base_class.name)
# ]
# else
# - first_key = through_reflection.klass.base_class.to_s.foreign_key
# - second_key = options[:foreign_key] || primary_key
# + first_key = source_reflection.association_foreign_key # through_reflection.klass.base_class.to_s.foreign_key
# + second_key = source_reflection.primary_key_name # options[:foreign_key] || primary_key
# end
#
# unless through_reflection.klass.descends_from_active_record?
# ## -2122,9 +2122,9 ##
#
# " #{join_type} %s ON (%s.%s = %s.%s%s%s%s) " % [
# table_alias_for(through_reflection.klass.table_name, aliased_join_table_name),
# - connection.quote_table_name(parent.aliased_table_name),
# - connection.quote_column_name(parent.primary_key),
# connection.quote_table_name(aliased_join_table_name),
# + connection.quote_column_name(parent.primary_key),
# + connection.quote_table_name(parent.aliased_table_name),
# connection.quote_column_name(jt_foreign_key),
# jt_as_extra, jt_source_extra, jt_sti_extra
# ] +
# --- /usr/lib/ruby/1.8/active_record/associations/has_many_through_association.rb.original 2012-02-25 10:33:53.000000000 -0800
# +++ /usr/lib/ruby/1.8/active_record/associations/has_many_through_association.rb 2012-02-25 12:19:56.000000000 -0800
# ## -160,7 +160,7 ##
# end
# else
# reflection_primary_key = #reflection.source_reflection.primary_key_name
# - source_primary_key = #reflection.through_reflection.klass.primary_key
# + source_primary_key = #reflection.source_reflection.association_foreign_key
# if #reflection.source_reflection.options[:as]
# polymorphic_join = "AND %s.%s = %s" % [
# #reflection.quoted_table_name, "#{#reflection.source_reflection.options[:as]}_type",
# --- /usr/lib/ruby/1.8/active_record/reflection.rb.original 2012-02-25 10:33:47.000000000 -0800
# +++ /usr/lib/ruby/1.8/active_record/reflection.rb 2012-02-25 12:20:04.000000000 -0800
# ## -192,7 +192,7 ##
# end
#
# def association_foreign_key
# - #association_foreign_key ||= #options[:association_foreign_key] || class_name.foreign_key
# + #association_foreign_key ||= #options[:primary_key] || class_name.foreign_key
# end
#
# def counter_cache_column

How to have an ouput without symbols and quotations etc. in Ruby

In this particular code when the input[0] = "status", I want the output to remove the symbols "" [] and , but I can't seem to find the solution, I've tried using each but I think what I'm doing is wrong, and I'm new to Ruby please help. Thanks!
class Main
puts "Welcome to the automated Parking Lot"
start = true
parking_lot = []
allocated_slot = 0
slot_number = 0
plate_number = ""
color = ""
x = ""
while (start == true) do
parking = Array.new
input = gets.split(' ')
case input[0]
when input[0] = "create_parking_lot"
parking_lot.clear
allocated_slot = input[1]
puts "Created a parking lot with #{allocated_slot} slots."
when input[0] = "park"
plate_number = input[1]
color = input[2]
if parking_lot.length < allocated_slot.to_i
slot_number = slot_number + 1
parking = [slot_number, input[1], input[2]]
parking_lot.push(parking)
parking_lot.sort!
puts "Allocated slot number: #{slot_number}"
else
puts "Sorry, parking lot is full"
end
when input[0] = "leave"
slot_number = input[1].to_i
puts "Slot number #{slot_number} is now free."
slot_number = slot_number - 1
parking_lot.delete_at(slot_number)
parking_lot[slot_number]
#puts parking_lot
when input[0] = "quit"
break
when input[0] = "status"
if parking_lot.count == 0
puts "No cars are parked."
else
puts "Slot No. Registration No. Color"
parking.sort!
i = 0
y = ""
while i < allocated_slot.to_i do
x = parking_lot[i].to_s
y = x.split(' ')
puts "#{y[0]} #{y[1]} #{y[2]}" #
#y.each { |a| print a, " " }
i = i+1
end
end
when input[0] = "registration_numbers_for_cars_with_color"
puts "registration number for cars"
when input[0] = "slot_numbers_for_cars_with_color"
puts "slot number for cars with color"
when input[0] = "slot_number_for_registration_number"
puts "slot number for registration number"
when input[0] = "check"
puts parking_lot
else
puts "Command Error"
end
end
and the output goes like this:
[1, "HA-312424242", "Green"]
If you have an array being outputted that looks like this:
[1, "HA-312424242", "Green"]
Then you can call the join method on it like this:
[1, "HA-312424242", "Green"].join(' ')
and it will produce:
"1 HA-312424242 Green"

How to add column to existing row with axlsx gem?

I am trying to format my xlsx file, but i faced some problems. For example i need to add column to existing row. For example here is my code:
wb.add_worksheet(name: "Sums") do |sheet|
sheet.add_row ["1.", "Rodiklis"], :style=>[title]
sheet.add_row ["1.1", "Rekomendacijų vertė"]
#departaments.each do |departament|
sheet.add_row ["", departament.name]
end
#all_items.each do |summary|
tyfcb = 0
rgi = 0
rgo = 0
rgirgo = 0
total = 0
rgirgo_per_user = 0
meeting_1_2_1 = 0
meeting_1_2_1_per_user = 0
ceu = 0
ceu_per_user = 0
v = 0
v_per_user = 0
summary.departament.contacts.each do |c|
items = c.items.where(summary_id: summary)
tyfcb += c.item_x(items, 'tyfcb')
rgi += c.item_x(items, 'rgi')
rgo += c.item_x(items, 'rgo')
meeting_1_2_1 += c.item_x(items, '1_2_1')
total += 1
ceu += c.item_x(items, 'ceu')
v += c.item_x(items, 'v')
end
rgirgo = rgi + rgo
rgirgo_per_user = rgirgo.to_f / total.to_f
meeting_1_2_1_per_user = meeting_1_2_1.to_f / total.to_f
ceu_per_user = ceu.to_f / total.to_f
v_per_user = v.to_f / total.to_f
sheet.add_row [summary.departament.name,summary.id, tyfcb]
sheet.add_row [summary.departament.name,summary.id, rgirgo]
sheet.add_row [summary.departament.name,summary.id, sprintf('%.2f', rgirgo_per_user)]
sheet.add_row [summary.departament.name,summary.id, meeting_1_2_1]
sheet.add_row [summary.departament.name,summary.id, sprintf('%.2f', meeting_1_2_1_per_user)]
sheet.add_row [summary.departament.name,summary.id, ceu]
sheet.add_row [summary.departament.name,summary.id, sprintf('%.2f', ceu_per_user)]
sheet.add_row [summary.departament.name, summary.id, v]
sheet.add_row [summary.departament.name,summary.id, sprintf('%.2f', v_per_user)]
end
end
So from the code we can see that I generate lots of tyfcb, ceu and etc variables. All of them are printed in new row. I want to to print all tyfcb variables in one row, all ceu variables in one row and etc. How should I do with axlsx gem? Thanks for answers.
Use add_cell
add_cell(value = '', options = {}) ⇒ Cell
This adds a single cell to the row based on the data provided and updates the worksheet's autofit data.
http://www.rubydoc.info/github/randym/axlsx/Axlsx/Row
Just add a empty "" to the first cell of row or wherever you want a blank column.

I'd like to add to an array from a do block. How is this done?

Here is the array, do block and my attempts to write into the new arrays:
#event_class_array is dynamic, and does not always have the same arrays, but the format is consistant.
#rule_name = Array.new
#rule_count = Array.new
#event_class_array = [["WEB-APPLICATION-ATTACK", 1222], ["MISC-ACTIVITY", 6], ["ATTEMPTED-ADMIN", 6], ["POLICY-VIOLATION", 5]]
#event_class_array.each do |exploit,count| # I also tried .collect with the same results
#rule_name = [exploit]
#rule_count = [count]
end
I've also tried this, but it writes out "WEB-APPLICATION-ATTACK" 1222 times, as well as the others:
#rule_name += [exploit]
#rule_count += [count]
same result as:
#rule_name << [exploit]
#rule_count << [count]
I would like for #rule_name and #rule_count to end up like this:
#rule_name = [["WEB-APPLICATION-ATTACK"], ["MISC-ACTIVITY"], ["ATTEMPTED-ADMIN"], ["POLICY-VIOLATION"]]
#rule_count = [[1222], [6], [6], [5]]
How about:
#event_class_array = [["WEB-APPLICATION-ATTACK", 1222], ["MISC-ACTIVITY", 6], ["ATTEMPTED-ADMIN", 6], ["POLICY-VIOLATION", 5]]
#rule_name, #rule_count = #event_class_array.transpose
#foo = Array.new
#bar = Array.new
easy:
#foo_bar.each do |x|
#foo << x[0]
#bar << x[1]
end
to ensure the same index
#foo_bar.each_with_index { |x, i|
#foo[i] = x[0]
#bar[i] = x[1]
}
Use this:
#rule_name = Array.new
#rule_count = Array.new
#event_class_array.each do |exploit|
#rule_name << [exploit.first]
#rule_count << [exploit.last]
end
OR
#rule_name = Array.new
#rule_count = Array.new
#event_class_array.each do |exploit, count|
#rule_name << [exploit]
#rule_count << [count]
end

archiloque-rest-client: change content-type to multipart/related when posing a file

Using
http://github.com/archiloque/rest-client
When posting a file using this line, the content type is set as
Content-Type: multipart/form-data; boundary=301405
in the header, by default.
RestClient.post '/data', :myfile => File.new("/path/to/image.jpg", 'rb')
I tried this and it still sets the header multipart/form-data.
RestClient.post '/data', :myfile => File.new("/path/to/image.jpg", 'rb'), :content_type => 'multipart/related'
Has anybody tried setting multipart/related?
Or you can use rather new-ish multipart_body gem:
http://steve.dynedge.co.uk/2010/09/19/multipart-body-a-gem-for-working-with-multipart-data/
Ok. I could not find a better alternative, so ended up with the following app.
It is based on this code here.
http://stanislavvitvitskiy.blogspot.com/2008/12/multipart-post-in-ruby.html
Usage:
files = { File.new("myfile1","rb"), File.new("myfile2","rb")}
mpost = Mutipart("main", "<my xml main part content which refers to file names>",files )
mpost.post("our_url","post")
Note: This code is not production ready. It is just functional.
---------------- multipart.rb -------------
require 'net/http'
require 'uri'
require 'pp'
require 'mime/types'
class Multipart
def initialize( main_part_id, main_part_content, file_names )
#file_names = file_names
#main_part_id = main_part_id
#main_part_content = main_part_content
end
def post( to_url, method = :post )
boundary = "###-------#{Time.new}-----####"
parts = []
streams = []
# write main part first
parts << StringPart.new( "--" + boundary + "\r\n")
parts << StringPart.new("Content-Disposition: name=\"#{#main_part_id}\";\"\r\n" +
"Content-ID: #{#main_part_id}\r\n\r\n"+
"Content-Type: application/xml\r\n\r\n" +
#main_part_content + "\r\n\r\n")
parts << StringPart.new( "\r\n--" + boundary + "\r\n")
#file_names.each do |param_name, filestream|
raise 'mutlipartsend: empty file object' if filestream.blank?
filename= filestream.respond_to?(:original_path) ? filestream.original_path : filestream.path
ctype = filestream.respond_to?(:content_type) ? filestream.content_type: nil
fsize = filestream.respond_to?(:lstat) ? filestream.lstat.size : filestream.size
if !ctype
begin
pos = filename.rindex('/') # if filename is a path
fname = filename[pos + 1, filename.length - pos]
mm = MIME::Types.type_for(fname)
ctype = mm.first.content_type if !mm.blank?
rescue Exception => e
p e.message
end
end
if !ctype
ctype= 'application/binary'
p "mutlipartsend: failed to determine contenttype for #{filename}. using application/binary"
end
parts << StringPart.new("Content-Disposition: name=\"" + param_name.to_s + "\"; filename=\"" + filename + "\"\r\n" +
"Content-Type: #{ctype}\r\n\r\n")
#"Content-Type: application/binary\r\n\r\n")
begin
stream = File.open(filestream.path,"rb")
streams << stream
parts << StreamPart.new(stream, fsize)
parts << StringPart.new( "\r\n--" + boundary + "\r\n" )
rescue Exception => e
p 'failed to load filestream '+ filestream.path
p e.message
raise 'failed to load filestream ' + e.message
end
end
post_stream = MultipartStream.new( parts )
url = URI.parse( to_url )
req = method == :post ? Net::HTTP::Post.new(url.path) : Net::HTTP::Put.new(url.path)
req.content_length = post_stream.size
req.content_type = 'multipart/mixed; boundary=' + boundary
req["myheader1"] = 'header1'
req["myheader2"] = 'header2'
req.body_stream = post_stream
res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
streams.each do |stream|
stream.close();
end
res
end
end
class StreamPart
def initialize( stream, size )
#stream, #size = stream, size
end
def size
#size
end
def read( offset, how_much )
#stream.read( how_much )
end
end
class StringPart
def initialize ( str )
#str = str
end
def size
#str.length
end
def read ( offset, how_much )
#str[offset, how_much]
end
end
class MultipartStream
def initialize( parts )
#parts = parts
#part_no = 0;
#part_offset = 0;
end
def size
total = 0
#parts.each do |part|
total += part.size
end
total
end
def read ( how_much )
if #part_no >= #parts.size
return nil;
end
how_much_current_part = #parts[#part_no].size - #part_offset
how_much_current_part = if how_much_current_part > how_much
how_much
else
how_much_current_part
end
how_much_next_part = how_much - how_much_current_part
current_part = #parts[#part_no].read(#part_offset, how_much_current_part )
if how_much_next_part > 0
#part_no += 1
#part_changed=true
#part_offset = 0
next_part = read( how_much_next_part )
current_part + if next_part
next_part
else
''
end
else
#part_offset += how_much_current_part
current_part
end
end
end

Resources