JRuby Oracle connection failing - ruby-on-rails

I am following a tutorial to establish ojdbc connection in JRuby so that I can execute some SQL statements. But it is failing to connect to the database. Below are the steps:
Copied ojdbc6.jar under working directory where the ruby files reside.
Created oracle_connection.rb file
Create test_connection.rb file as the driver class
oracle_connection.rb
require 'java'
require 'ojdbc6.jar'
java_import 'oracle.jdbc.OracleDriver'
java_import 'java.sql.DriverManager'
class OracleConnection
#conn = nil
#user = nil
#pwd = nil
def initialize(user, pwd, url)
#user = user
#pwd = pwd
#url = url
#Load driver class
ora_driver = OracleDriver.new
DriverManager.registerDriver ora_driver
#conn = DriverManager.get_connection url, user, pwd
#conn.auto_commit = false
end
#Add getters and setters for all attributes we wish to expose
attr_reader :user, :pwd, :url, :connection
def close_connection()
#conn.close() unless #conn
end
def prepare_call(call)
#conn.prepare_call call
end
def create_statement()
#conn.create_statement
end
def prepare_statement(sql)
#conn.prepare_statement sql
end
def commit()
#conn.commit
end
def to_s
"OracleConnection [user=#{#user}, url=#{#url}]"
end
alias_method :to_string, :to_s
end
#test_connection.rb
require 'oracle_connection'
#Edit these for your database schema
user = "ABC"
pwd = "EFG"
url = "jdbc:oracle:thin:#host_name:1520/db_instance"
print "Run at #{Time.now} using JRuby #{RUBY_VERSION}\n\n"
begin
conn = OracleConnection.new.create(user, pwd, url)
puts conn, "\n"
end
print "\nEnded at #{Time.now}\n"
While running test_connection.rb, I see the below error:
ruby test_connection.rb
Run at 2013-09-16 10:11:05 -0700 using JRuby 1.9.2
NoMethodError: undefined method `create' for OracleConnection:Class
(root) at test_connection.rb:11
I don't know what is causing the problem. Guidance on this is really appreciated. Thanks!

In "test_connection.rb" I was calling "create" method whereas in OracleConnection class "create" method is not defined. Hence it was failing.
Replacing conn = OracleConnection.new.create(user, pwd, url) with conn = OracleConnection.new(user, pwd, url) fixes the issue.
Below I am re-writing the working test_connection.rb
#test_connection.rb
require 'oracle_connection'
#Edit these for your database schema
user = "ABC"
pwd = "EFG"
url = "jdbc:oracle:thin:#host_name:1520/db_instance"
print "Run at #{Time.now} using JRuby #{RUBY_VERSION}\n\n"
begin
conn = OracleConnection.new(user, pwd, url)
puts conn, "\n"
end
print "\nEnded at #{Time.now}\n"

Related

Rails 7 RestClient::Not found in find_each loop updating avatar from Microsoft Graph

I'm trying to attach all pictures from the Microsoft Graph to my new Rails application using active storage and the rest-client gem.
It works for a single user I do it like this:
User.find_by_email("user.email#domain.com).avatar.attach io:StringIO.open(image.to_blob), filename: "avatar.jpg", content_type: metadata["mimeType"], identify: false
But in a batch loop, it doesn't work.
class RestController < ApplicationController
require 'rest-client'
def sync_azure_picture
#token = RestController.get_azure_token
User.find_each do |currentUser|
request_url = 'https://graph.microsoft.com/v1.0/users/'+currentUser[:id_azure]+'/photo/$value'
puts request_url
resp = RestClient.get(request_url,'Authorization' => #token)
image = MiniMagick::Image.read(resp.body)
metadata = image.data
currentUser.avatar.attach io:StringIO.open(image.to_blob), filename: "avatar.jpg", content_type: metadata["mimeType"], identify: false
end
end
end`
The error i'm getting is
RestClient::NotFound
Probably not all users have attachments? You can log errors and then check these urls
User.find_each do |user|
# ...
rescue RestClient::NotFound => e
Rails.logger.error("#{request_url}:")
Rails.logger.error(e)
end

Rails Job loses reference to module randomly

EDIT: same things happens when I fork a process manually...
I'm getting some weird behavior with a Rails Job that calls a module of mine called RedisService.
I've added lib/modules to my autoload_paths but the TextService module that calls the RedisService one loses reference to it, sometimes immediately, sometimes 3 or 4 job calls in...
I've even required the module in my TextService to no avail, even added some puts to check that always show the module is defined and responds to the method I'm calling...!
Something escapes me...
Here's a gist to the backtrace
Repo: https://gitlab.com/thomasbromehead/snmp-simulator-ruby-manager.
ruby --version: 2.6.5
rails version: 6.1.3.1
My "service" objects:
Module that calls RedisService
require_relative 'redis_service'
module TextService
def self.write_to_file(dataObject, redis, path: "./")
begin
file_with_path = path + dataObject.filename
# Store all lines prior to the one being modified, File.read closes the file
f = File.read(file_with_path)
new_content = f.gsub(dataObject.old_set_value, dataObject.new_set_value)
# File.open closes the file when passed a block
File.open(file_with_path, "w") { |file| file.puts new_content }
puts "Redis is: #{redis}" ======> RedisService
puts "Redis responds to multi: #{redis.respond_to?(:multi)}" ======> true
redis.multi do
redis.zrem("#{dataObject.name}-sorted-set", dataObject.old_set_value)
redis.hset("#{dataObject.name}-offsets", "#{dataObject.start_index}:#{dataObject.oid}:#{dataObject.end_index}", dataObject.new_set_value)
redis.zadd("#{dataObject.name}-sorted-set", dataObject.start_index, dataObject.new_set_value)
end
rescue EOFError
end
end
Variation class called from VariateJob
require_relative '../../../lib/modules/redis_service'
module Snmp
class Variation
include ActiveModel::Model
attr_reader :oid, :type, :duration, :to, :from, :filename, :redis
def initialize(oid:nil, duration:nil, type:nil, to:nil, filename: nil, from:nil)
#to = to
#from = from
#oid = oid
#type = type
#filename = filename
#redis = RedisService
end
def run(data)
current_value, new_set_value, start_index, end_index = prepare_values(JSON.parse(data))
transferData = Snmp::TransferData.new({
filename: #filename,
old_set_value: current_value,
new_set_value: new_set_value,
start_index: start_index,
end_index: end_index,
name: #name,
oid: oid
})
TextService.write_to_file(transferData, #redis)
end
VariateJob
class VariateJob < ApplicationJob
queue_as :default
def perform(dumped_variation, data)
Marshal.load(dumped_variation).run(Marshal.load(data))
end
end
VariationsController
class VariationsController < ApplicationController
before_action :set_file_name, only: :start
def start
if params["linear"]
type = :linear
elsif params["random"]
type = :random
end
data = redis.hscan_each("##name-offsets", match: "*:#{params["snmp_variation"]["oid"]}*")
# data is an Enumerator, transform it to an array and dump to JSON
variation = Snmp::Variation.new(params_to_keywords(params["snmp_variation"]).merge({type: type}))
VariateJob.perform_later(Marshal.dump(variation), Marshal.dump(JSON.generate(data.to_a.first)))
end
RedisService
require 'redis'
module RedisService
include GlobalID::Identification
[...]
def self.multi(&block)
#redis.multi { block.call() }
end
[...]
end
You are not losing the reference to the RedisService, but to Redis in your RedisService. Probably because you use a server or worker that forks new processes and you don't initialize a new connection after the fork.
To fix this issue I would replace this method
def self.start(host,port)
#redis ||= Redis.new(host: host, port: port)
self
end
with
def self.redis
#redis ||= Redis.new(host: ::Snmpapp.redis_config[:host], port: ::Snmpapp.redis_config[:port])
end
And then I would replace all call to the #redis with a redis call to the new method.

Pivotal tracker story is not getting updated after code push

We had pivotal tracker integrated with GitHub and when we used to commit with story id, it used to update the story with a commit message update story status.
We recently migrated to Team Foundation Server from GitHub and that integration is not working anymore.
Looks like there is no integration App exists yet.
Is there a programmatic way of doing it?
Create file named pre-push (without any extension) and put it under ./.git/hooks/ folder inside your repo. This folder should already exist if it's a valid repo. Copy paste following code in the file. Don't forget to replace the API token value in the following code -
#!/usr/bin/env ruby
# encoding: UTF-8
require 'net/https'
require 'json'
class GitLogs
attr_accessor :raw_log, :commit_data, :commit, :author, :message, :refs
def initialize
self.commit = 'Commit: ' + `git log -1 --pretty=format:%h`.force_encoding('utf-8')
self.author = 'Author: ' + `git log -1 --pretty=format:%aN`.force_encoding('utf-8')
self.message = 'Message: ' + `git log -1 --pretty=format:%s`.force_encoding('utf-8')
self.refs = 'Refs: ' + `git log -1 --pretty=format:%d`.force_encoding('utf-8')
# Example git formatted log output:
#
# Commit: 8872e8fe03a10238d7be84d78813874d79ce0c3d
# Author: John Doe <john.doe#unknown.com>
# Message: [#90743834] test new v5 hook addition
# Refs: (HEAD, feature/hook-test)
parse!
self
end
def parse!
self.commit_data = GitLog.new(self.commit, self.author, self.message, self.refs)
end
def pivotal_sync!
Pivotal.new(commit_data).send! if commit_has_story_id?
end
def commit_has_story_id?
# somewhere between square brackets there has to be a hash followed by multiple digits
!commit_data.message.scan(/\[*+\#(\d+)\D?(.*)\]/).empty?
end
end
class GitLog
attr_accessor :hash, :author, :message, :refs
def initialize hash, author, message, refs
self.hash = hash
self.author = author
self.refs = refs
self.message = message
updated_message
end
def updated_message
return message
end
def to_json
{ source_commit:
{ commit_id: self.hash,
author: self.author,
message: self.message,
}
}.to_json
end
end
class Pivotal
attr_accessor :git_log, :tracker_token
BASE_URI = URI('https://www.pivotaltracker.com/')
def initialize git_log
self.git_log = git_log
self.tracker_token = get_token
end
def get_token
'YOUR APT TOKEN GOES HERE. CAN GET IT FROM https://www.pivotaltracker.com/profile'
end
def send!
https = Net::HTTP.start(BASE_URI.host, 443, {
use_ssl: true,
verify_mode: OpenSSL::SSL::VERIFY_NONE
})
request = Net::HTTP::Post.new('/services/v5/source_commits')
request['X-TrackerToken'] = tracker_token
request['Content-type'] = 'application/json'
request.body = git_log.to_json
response = https.request(request)
end
end
GitLogs.new().pivotal_sync!

How to use SOAP service with xml in Rails (EU VAT number check)

I'd like to add a method in my Rails application that checks the validity of a VAT number using the EU's VIES system: http://ec.europa.eu/taxation_customs/vies/technicalInformation.html
I'm already pretty new to programming in Rails and the instructions here use xml. So I have trouble figuring this out. How should I include the code mentioned on the mentioned website in my Rails application?
In other words, what should the validate_vat(country, vatnumber) method below look like and how to process the response received from the SOAP service?
def vatsubmission
#organization = Organization.find(params[:id])
#organization.update_attributes(vat_params)
#organization.validate_vat(#organization.country, #organization.vatnumber) if (#organization.vatnumber? && #organization.vatnumber?)
# Process response
if valid == false
#organization.update_attributes(valid_vat: false)
flash.now[:danger] = "False VAT number"
render ...
elsif valid == true
#organization.update_attributes(valid_vat: true)
flash.now[:success] = "VAT number validated"
render ...
else
flash.now[:danger] = "VAT number could not be validated"
render ...
end
end
def validate_vat(country, vatnumber)
??
end
Update: I've added gem 'savon', '2.11.1' to my gemfile. In my controller I have:
def update
#organization = Organization.find(params[:id])
if #organization.check_valid == true
#organization.update_attributes(validnr: true)
else
#organization.update_attributes(validnr: false)
end
end
And I have added the following model method:
require 'savon'
def check_valid
debugger
if ["DK", "CY", "etc"].include? self.country
client = Savon.client(wsdl: 'http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl')
resp = client.call :check_vat do
message country_code: self.country, vat_number: self.vatnr
end
data = resp.to_hash[:check_vat_response]
data[:valid]
end
end
Error: The line message country_code: self.country, vat_number: self.vatnr fails with the error message: wrong number of arguments (1 for 2). I checked with the debugger and self.country as well as self.varnr do have values. What am I doing wrong?
For working with SOAP from Ruby I used excelent Savon gem.
With Savon v2, working code looks like this:
require 'savon'
client = Savon.client(wsdl: 'http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl')
resp = client.call :check_vat do
message country_code: 'AT', vat_number: '123'
end
data = resp.to_hash[:check_vat_response]
data[:valid] #=> false :)
Note Savon v3 is still in preparation.
I've just started using the ValVat gem for this and it workd beautifully so far!

undefined method: connect_timeout

Browser error:
NoMethodError
undefined method `connect_timeout=' for #<Mysql2::Client:0x47f7570>
On my browser, an error comes up that connect_timeout is undefined. I'm pretty sure it has something to do with the client.rb file. I'll show you the file. I had to edit some of it to actually get Webrick up and running. When I started the server, an error always appeared on my command line unless I made the changes. I've commented on what I have edited. Sometimes edited random things and some of them worked but they produced different errors on my browser. I am using a windows 8 machine. Thank you for helping.
module Mysql2
class Client
attr_reader :query_options, :read_timeout
##default_query_options = {
:as => :hash, # the type of object you want each row back as; also supports :array (an array of values)
:async => false, # don't wait for a result after sending the query, you'll have to monitor the socket yourself then eventually call Mysql2::Client#async_result
:cast_booleans => false, # cast tinyint(1) fields as true/false in ruby
:symbolize_keys => false, # return field names as symbols instead of strings
:database_timezone => :local, # timezone Mysql2 will assume datetime objects are stored in
:application_timezone => nil, # timezone Mysql2 will convert to before handing the object back to the caller
:cache_rows => true, # tells Mysql2 to use it's internal row cache for results
#:connect_flags => REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION,
#I had to delete the line above because for some reason the command prompt said that each of the constants were undefined were not used in the right place or something
:cast => true,
:default_file => nil,
:default_group => nil
}
def initialize (opts = {})
opts = Mysql2::Util.key_hash_as_symbols( opts )
#read_timeout = nil
#query_options = ##default_query_options.dup
#query_options.merge! opts
#initialize_ext
# the chrome page said that the above variable is undefined :P
# Set default connect_timeout to avoid unlimited retries from signal interruption
opts[:connect_timeout] = 120 unless opts.key?(:connect_timeout)
[:reconnect, :connect_timeout, :local_infile, :read_timeout, :write_timeout, :default_file, :default_group, :secure_auth, :init_command].each do |key|
next unless opts.key?(key)
case key
when :reconnect, :local_infile, :secure_auth
send(:"#{key}=", !!opts[key])
when :connect_timeout, :read_timeout, :write_timeout
send(:"#{key}=", opts[key].to_i)
else
send(:"#{key}=", opts[key])
end
end
# force the encoding to utf8
self.charset_name = opts[:encoding] || 'utf8'
ssl_options = opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher)
ssl_set(*ssl_options) if ssl_options.any?
if [:user,:pass,:hostname,:dbname,:db,:sock].any?{|k| #query_options.has_key?(k) }
warn "============= WARNING FROM mysql2 ============="
warn "The options :user, :pass, :hostname, :dbname, :db, and :sock will be deprecated at some point in the future."
warn "Instead, please use :username, :password, :host, :port, :database, :socket, :flags for the options."
warn "============= END WARNING FROM mysql2 ========="
end
user = opts[:username] || opts[:user]
pass = opts[:password] || opts[:pass]
host = opts[:host] || opts[:hostname]
port = opts[:port]
database = opts[:database] || opts[:dbname] || opts[:db]
socket = opts[:socket] || opts[:sock]
flags = opts[:flags] ? opts[:flags] | #query_options[:connect_flags] : #query_options[:connect_flags]
# Correct the data types before passing these values down to the C level
user = user.to_s unless user.nil?
pass = pass.to_s unless pass.nil?
host = host.to_s unless host.nil?
port = port.to_i unless port.nil?
database = database.to_s unless database.nil?
socket = socket.to_s unless socket.nil?
connect user, pass, host, port, database, socket, flags
end
def self.default_query_options
##default_query_options
end
def query_info
info = query_info_string
return {} unless info
info_hash = {}
info.split.each_slice(2) { |s| info_hash[s[0].downcase.delete(':').to_sym] = s[1].to_i }
info_hash
end
private
def self.local_offset
::Time.local(2010).utc_offset.to_r / 86400
end
end
end
Mysql2::Client#initialize called connect_timeout= but there isn't such attr_writer in the client.
when :connect_timeout, :read_timeout, :write_timeout
send(:"#{key}=", opts[key].to_i)
else
If this client is written by yourself, add attr_accessor :connect_timeout in Mysql2::Client's definition and make proper use of the attribute. If it is from other library, check your load path. You may have missed some files that opened Mysql2::Client and monkey patched it.

Resources