Using Ruby on Railswith legacy Oracle databases
Raimonds Simanovskis
Ruby => Oracle
Ruby application
ruby-oci8
require 'oci8'OCI8.new('scott', 'tiger').exec('select * from emp') do |r| puts r.join(',')end
Oracle Instant Client Oracle Database
SQL*Net
JRuby => Oracle
Ruby application
JRuby
require "java"sql = JavaSQL::DriverManager.getConnection(db, user, password)statement = sql.createStatementstatus = statement.execute "select * from parts;"rs = statement.getResultSet()
JDBC driver Oracle Database
SQL*Net
ActiveRecordOracle Enhanced
Adapter
Ruby on Rails 2.x => Oracle
gem install activerecord-oracle_enhanced-adapter
database.ymldevelopment: adapter: oracle_enhanced database: XE username: blogdemo password: blogdemo encoding: utf8
SQL bind variables
database.ymldevelopment: adapter: oracle_enhanced database: XE username: blogdemo password: blogdemo encoding: utf8 cursor_sharing: similar
Employee.find(1)
SELECT * FROM employees WHERE (employees.id = 1)
SELECT * FROM employees WHERE (employees.id = :SYS_B_0)
ActiveRecord
Oracle optimizer
Oracle Data TypesRuby Rails Oracle
Fixnum :integer NUMBERFloat :float NUMBER
BigDecimal :decimal NUMBER, DECIMALTime :datetime DATETime :time DATEDate :date DATEString :string VARCHAR2String :text CLOB
True/FalseClass :boolean NUMBER(1), CHAR(1)
WorkaroundsActiveRecord::ConnectionAdapters::OracleEnhancedAdapter. emulate_dates_by_column_name = truehire_date # Oracle DATE => Ruby Datehire_time # Oracle DATE => Ruby Time
set_date_columns :started_on, :finished_onset_datetime_columns :start_date_and_time, :end_date_and_time
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter. emulate_booleans_from_strings = trueactive_flag # Oracle CHAR(1) ‘Y’/’N’ => true/false
set_boolean_columns :some_boolean_column
ignore_table_columns :attribute1, :attribute2
Calling PL/SQL from Rubyrequire "oci8"conn = OCI8.new("hr","hr","xe")
cursor = conn.parse <<-EOSBEGIN :return := test_uppercase(:p_string);END;EOScursor.bind_param(':p_string',"xxx",String)cursor.bind_param(':return',nil,String,4000)cursor.execputs cursor[':return']cursor.close
ruby-plsql gem
gem install ruby-plsql
require "ruby-plsql"plsql.connection = OCI8.new("hr","hr","xe")
puts plsql.test_uppercase('xxx')
ruby-plsql gemplsql.connection = OCI8.new("hr","hr","xe")
plsql.test_uppercase('xxx') # => "XXX"plsql.test_uppercase(:p_string => 'xxx') # => "XXX"plsql.test_copy("abc", nil, nil) # => { :p_to => "abc", # :p_to_double => "abcabc" }plsql.test_copy(:p_from => "abc", :p_to => nil, :p_to_double => nil) # => { :p_to => "abc", # :p_to_double => "abcabc" }plsql.hr.test_uppercase('xxx') # => "XXX"plsql.test_package.test_uppercase('xxx') # => 'XXX'plsql.hr.test_package.test_uppercase('xxx') # => 'XXX'
plsql.logoff
Custom CUD
methods
class Employee < ActiveRecord::Base set_create_method do plsql.employees_pkg.create_employee( :p_first_name => first_name, :p_last_name => last_name, :p_employee_id => nil )[:p_employee_id] end set_update_method do plsql.employees_pkg.update_employee( :p_employee_id => id, :p_first_name => first_name, :p_last_name => last_name ) end set_delete_method do plsql.employees_pkg.delete_employee( :p_employee_id => id ) endend
Other features
• composite_primary_keys support
• NLS_DATE_FORMAT independent
• TIMESTAMP columns support
• Faster schema dump
DEMO
see code athttp://github.com/rsim/legacy_oracle_sample
Ruby on Rails on Oracle
EBS
Ruby on Rails application
Oracle E-Business Suite database
APPS schema XXX schema
XXX tablescustom views
for data access
custom or standard API packages
read data
update data
new schema for web application
synonym for views
synonym for packages
Model classes
(business logic)
View templates
(HTML, Javascript)
Controller classes
(incoming request
processing)
SQLselects
update datathrough API
Browser
HTTP request
HTML result
custom tables for web
application
SQL
Typical application
server processes
Application server
Apache
HAproxy balancer
HTTP
HTTPS
Mongrel Mongrel Mongrel...
HTTPHTTP HTTP
Oracle DB
Memcached
SQL SQL SQL
TCP TCP TCP
Thank You!
http://blog.rayapps.comhttp://github.com/rsim