Last active
November 14, 2019 13:13
-
-
Save Yoshyn/f9424e3697a93cb01330572e12718cf2 to your computer and use it in GitHub Desktop.
Ruby & Rails : Set of snippet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Contains : | |
# * replace_task.rb | |
# * convert_date.rb | |
# * detect_leaks.rb | |
# * trace_point_logger.rb : Display all function path, parameter and return to a file (a logger) POC | |
# * profile_gem_on_boot.rb : Loading time per gem | |
# * crow_flies_sqlite.rb : An implementation of crow flies for sqlite & rails | |
# * openssl.rb : Asyn & sync encryption with openssl | |
# Convert from ipaddr to netaddr:cidr type | |
# https://stackoverflow.com/questions/19305586/convert-from-ipaddr-to-netaddrcidr-type/24259011#24259011 | |
# Profile memory & object use over a part of an application | |
# https://github.com/SamSaffron/memory_profiler | |
# Manage complex SQL query (mat. views) | |
# https://blog.castle.co/tech/10-06-2016/complex-sql-in-rails |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Modify the search hash parameter by transforming all date string in date format if the parameter key finish by '_date'. | |
# The purpose is to repare this kind of parameter to an sql request. | |
# Params : | |
# search (mandatory) : hash of params. They probably have been parsed in an index action ( something like : search = params[:search] || {}) | |
# format (optional) : The format of the date that we expect in the search hash. | |
# zone (optional) : The zone of the date | |
def convert_date(search, format: '%d/%m/%Y', zone: Time.zone) | |
search.each do |key, value| | |
next unless key.respond_to?(:end_with?) && key.end_with?('_date') | |
search[key] = DateTime.strptime(value, format).in_time_zone(zone) rescue nil | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#frozen_string_literal: true | |
# https://stackoverflow.com/questions/13939574/how-do-i-put-a-ruby-function-into-a-sqlite3-query | |
require "bundler/inline" | |
gemfile(true) do | |
source "https://rubygems.org" | |
git_source(:github) { |repo| "https://github.com/#{repo}.git" } | |
gem "rails", github: "rails/rails" | |
gem "sqlite3" | |
end | |
require "active_record" | |
require "minitest/autorun" | |
require "logger" | |
# This connection will do for database-independent bug reports. | |
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") | |
ActiveRecord::Base.logger = Logger.new(STDOUT) | |
module GeoForSQLite | |
RAD_PER_DEG = Math::PI / 180 | |
RM = 6371 # Earth radius in kmeters | |
def self.crow_flies_km(lat1, lon1, lat2, lon2) | |
lat1_rad, lat2_rad = lat1 * RAD_PER_DEG, lat2 * RAD_PER_DEG | |
lon1_rad, lon2_rad = lon1 * RAD_PER_DEG, lon2 * RAD_PER_DEG | |
a = Math.sin((lat2_rad - lat1_rad) / 2) ** 2 + Math.cos(lat1_rad) * Math.cos(lat2_rad) * Math.sin((lon2_rad - lon1_rad) / 2) ** 2 | |
c = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1 - a)) | |
RM * c # Delta in meters | |
end | |
def self.load!(sqlite_database) | |
%w(cos acos sin).each do |math_method| | |
sqlite_database.create_function math_method, 1 do |func, *args| | |
func.result = Math.__send__(math_method, *args) | |
end | |
end | |
sqlite_database.create_function 'pi', 0 do |func, *args| | |
func.result = Math::PI | |
end | |
sqlite_database.create_function 'crow_flies_km', 4 do |func, *args| | |
func.result = crow_flies_km(*args) | |
end | |
end | |
end | |
GeoForSQLite.load!(ActiveRecord::Base.connection.raw_connection) | |
class CrowFliesSQLTest < Minitest::Test | |
def test_crow_flies_km_sql_result | |
paris_lat, paris_lng = 48.8566, 2.3522 | |
rennes_lat, rennes_lng = 48.1135, -1.6757 | |
result = ActiveRecord::Base.connection.execute("SELECT CROW_FLIES_KM(#{paris_lat}, #{paris_lng}, #{rennes_lat}, #{rennes_lng}) AS CROW_FLIES_KM;") | |
assert_equal(308, result[0]["CROW_FLIES_KM"].to_i) | |
end | |
def test_crow_flies_km_full_sql_result | |
paris_lat, paris_lng = 48.8566, 2.3522 | |
rennes_lat, rennes_lng = 48.1135, -1.6757 | |
lat1, lon1, lat2, lon2 = paris_lat, paris_lng, rennes_lat, rennes_lng | |
query = "ACOS( SIN(#{lat1}*PI()/180)*SIN(#{lat2}*PI()/180) + COS(#{lat1}*PI()/180)*COS(#{lat2}*PI()/180)*COS(#{lon2}*PI()/180-#{lon1}*PI()/180) ) * 6371" | |
result = ActiveRecord::Base.connection.execute("SELECT #{query} AS CROW_FLIES_KM;") | |
assert_equal(308, result[0]["CROW_FLIES_KM"].to_i) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=begin | |
# Run this into irb | |
require 'objspace' | |
ObjectSpace.trace_object_allocations_start | |
def generate_report(name: nil) | |
GC.start() | |
output_file = File.open("#{Rails.root}/tmp/rubyheap_#{name}_#{Process.getpgrp}_#{Time.now.to_i}.json", 'w') | |
dump = ObjectSpace.dump_all(output: output_file) | |
dump.close | |
File.open("#{Rails.root}/tmp/rubyheap_#{name}_#{Process.getpgrp}_count_object", 'a') do |f| | |
f.write("\n==============#{Time.now.to_i}==============\n") | |
f.write(ObjectSpace.count_objects.to_s) | |
end | |
end | |
end | |
def launch_test(name) | |
my_process_here() | |
generate_report(name: name) | |
my_process_here() | |
generate_report(name: name) | |
my_process_here() | |
generate_report(name: name) | |
end | |
name = 'unknown' | |
launch_test(name) | |
`ruby #{File.join(Rails.root, 'script', 'detect_leaks.rb')} #{Dir[File.join(Rails.root, 'tmp', "rubyheap_#{name}_*.json")].sort.join(' ')} > #{File.join(Rails.root, 'tmp', "leaks.#{name}")}` | |
=end | |
#!/usr/bin/env ruby | |
require 'set' | |
require 'json' | |
if ARGV.length != 3 | |
puts "Usage: detect_leaks [FIRST.json] [SECOND.json] [THIRD.json]" | |
exit 1 | |
end | |
first_addrs = Set.new | |
third_addrs = Set.new | |
line_errors = 0 | |
# Get a list of memory addresses from the first dump | |
File.open(ARGV[0], "r").each_line do |line| | |
parsed = JSON.parse(line) rescue (line_errors+=1; nil) | |
first_addrs << parsed["address"] if parsed && parsed["address"] | |
end | |
# Get a list of memory addresses from the last dump | |
File.open(ARGV[2], "r").each_line do |line| | |
parsed = JSON.parse(line) rescue (line_errors+=1; nil) | |
third_addrs << parsed["address"] if parsed && parsed["address"] | |
end | |
diff = [] | |
# Get a list of all items present in both the second and | |
# third dumps but not in the first. | |
File.open(ARGV[1], "r").each_line do |line| | |
parsed = JSON.parse(line) rescue (line_errors+=1; nil) | |
if parsed && parsed["address"] | |
if !first_addrs.include?(parsed["address"]) && third_addrs.include?(parsed["address"]) | |
diff << parsed | |
end | |
end | |
end | |
# Group items | |
diff.group_by do |x| | |
[x["type"], x["file"], x["line"]] | |
end.map do |x,y| | |
# Collect memory size | |
[x, y.count, y.inject(0){|sum,i| sum + (i['bytesize'] || 0) }, y.inject(0){|sum,i| sum + (i['memsize'] || 0) }] | |
end.sort do |a,b| | |
b[1] <=> a[1] | |
end.each do |x,y,bytesize,memsize| | |
# Output information about each potential leak | |
puts "Leaked #{y} #{x[0]} objects of size #{bytesize}/#{memsize} at: #{x[1]}:#{x[2]}" | |
end | |
# Also output total memory usage, because why not? | |
memsize = diff.inject(0){|sum,i| sum + (i['memsize'] || 0) } | |
bytesize = diff.inject(0){|sum,i| sum + (i['bytesize'] || 0) } | |
puts "\n\nTotal Size: #{bytesize}/#{memsize}" | |
puts "\n\nWARNING : #{line_errors} can't be parsed. Maybe the heap are truncated" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def field_form_column(record, options) | |
new_field = Proc.new { | value = nil| | |
input_field = text_field_tag "record[field][]", value, :class => options[:class] | |
js_remove_onclick = "$(this).closest('.field_form_column').remove()" | |
remove_button = button_tag "Remove this required claim", onclick: js_remove_onclick, type: :button | |
content_tag(:div, input_field + remove_button, :class => "field_form_column") | |
} | |
existing_values = Array(record.public_send(:field)).reject(&:blank?) | |
inputs = existing_values.each_with_index.map do |value, index| | |
new_field.call(value, index) | |
end | |
js_add_onclick = "var div = document.createElement('div'); div.innerHTML='#{new_field.call}'; $('#add-required-claim')[0].before(div)" | |
add_button = button_tag "Add one required claim", onclick: js_add_onclick, type: :button, id: "add-required-claim" | |
(inputs.join + add_button).html_safe | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
text = "This is data" | |
# Encrypt data with Public key : | |
formated_cert = OneLogin::RubySaml::Utils.format_cert(Gaston.saml_security.certificate) | |
cert = OpenSSL::X509::Certificate.new(formated_cert) | |
public_key = cert.public_key # .to_pem | |
text_enc = Base64.encode64(public_key.public_encrypt(text, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)) | |
# Decrypt data with Private key : | |
formatted_private_key = OneLogin::RubySaml::Utils.format_private_key(Gaston.saml_security.private_key) | |
private_key = OpenSSL::PKey::RSA.new(formatted_private_key) | |
private_key.private_decrypt(Base64.decode64(text_enc), OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING) | |
# On Customer side (public) : verify signature | |
digest = OpenSSL::Digest::SHA256.new | |
signature = private_key.sign(digest, text) | |
public_key.verify digest, signature, text | |
#private_key.verify digest, signature, text | |
# Symetric encryptions : | |
---------------- | |
cipher = OpenSSL::Cipher::AES256.new :CBC | |
cipher.encrypt | |
cipher.key = "ThisPasswordIsReallyHardToGuess!" | |
cipher_text = cipher.update('This is a secret message') + cipher.final | |
---------------- | |
decipher = OpenSSL::Cipher::AES256.new :CBC | |
decipher.decrypt | |
decipher.key = "ThisPasswordIsReallyHardToGuess!" | |
decipher.update(cipher_text) + decipher.final | |
=> "This is a secret message" | |
# https://tomkadwill.com/message-signing-with-ruby-openssl-rsa | |
# https://gist.github.com/ericchen/3081968 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Profile rails on boot. | |
# http://mildlyinternet.com/code/profiling-rails-boot-time.html | |
# https://github.com/schneems/derailed_benchmarks | |
# Into config/boot.rb | |
require "benchmark" | |
def require(file_name) | |
result = nil | |
begin | |
time = Benchmark.realtime do | |
result = super | |
end | |
if time > 0.1 | |
puts "#{time} #{file_name}" | |
end | |
rescue StandardError => ex | |
puts "require(#{file_name} fails : #{ex} #{ex.backtrace}" | |
raise ex | |
end | |
result | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Rake::TaskManager.class_eval do | |
def replace_task(task_name, task_scope) | |
scope_backup = @scope | |
@scope = Rake::Scope.new(task_scope) | |
task_name_full = @scope.path_with_task_name(task_name) | |
@tasks[task_name_full].clear | |
@tasks[task_name_full] = yield | |
@scope = scope_backup | |
end | |
end | |
Rake.application.replace_task('prepare', 'db:test') do | |
task :prepare => %w(environment load_config) do | |
# Code here | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
begin | |
require "bundler/inline" | |
rescue LoadError => e | |
$stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler" | |
raise e | |
end | |
gemfile(true) do | |
source "https://rubygems.org" | |
end | |
require 'logger' | |
class TracePoint::Logger < Logger | |
def initialize(*args); @indent = 0; super(*args); end | |
def format_message(severity, timestamp, programe, msg) | |
"[#{severity}][#{timestamp}][#{programe}]" + (" " * @indent * 2) + "-> #{msg}\n" | |
end | |
def increment_indent!; @indent+=1; end | |
def decrement_indent!; @indent-=1; end | |
end | |
# logfile = File.open(RAILS_ROOT + '/log/trace_point_logger.log', 'a') #create log file | |
# logfile.sync = true #automatically flushes data to file | |
TracePointLogger = TracePoint::Logger.new(STDOUT) | |
class A | |
def foo(a,b = 0) | |
lv = 9 | |
"Hello" | |
end | |
end | |
class B | |
def self.foo(a) | |
lv = 6 | |
A.new.foo(a) | |
end | |
end | |
trace_c = TracePoint.new(:call) do |tp| | |
TracePointLogger.increment_indent! | |
parameters = tp.defined_class.instance_method(tp.method_id).parameters.inject({}) do |acc, (kind, var)| | |
acc[var] = { kind: kind , value: tp.binding.local_variable_get(var) } | |
acc | |
end | |
TracePointLogger.debug({ func: "#{tp.defined_class}#{tp.method_id}", parameters: parameters }.to_s) | |
end | |
trace_r = TracePoint.new(:return) do |tp| | |
TracePointLogger.debug({ func: "#{tp.defined_class}#{tp.method_id}", return: tp.return_value.to_s }.to_s) | |
TracePointLogger.decrement_indent! | |
end | |
trace_c.enable | |
trace_r.enable | |
A.new.foo(3) | |
B.foo(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment