Como criar Webservice RESTful com RubyOnRails 3 / 4 + Oracle 10g (Legacy Schema)

O objetivo deste post é mostrar como criar um webservice utilizando o Rails conectado ao Banco de dados Oracle. Não é algo difícil mas exige um pouco de atenção aos detalhes. Nesse post não entrarei em detalhes sobre a história, razão ou motivos do porque as coisas são assim, isso a gente vê na faculdade ou pesquisando por aqui mesmo na web. Seguiremos a risca a missão do blog, ser um “Help”.

Não existe coisa mais irritante do que buscar ajuda pelos post’s da vida e só termos a resposta pela metade, ou então alguém falando que resolveu mas sem muitas explicações, com isso me refiro a parte prática. Creio que se você chegou até aqui com certeza já conhece um pouco sobre o Oracle e RubyOnRails.

Encontrar um tutorial que ensine como criar um webservice com Rails é fácil, difícil é encontrar um que mostre como fazer isso com um banco de dados legado (existente).

Onde nós estamos

Todo mundo que trabalha com Rails, sabe que ele funciona muito bem quando cria seu próprio banco de dados e suas tabelas, um exemplo disso é o comando ‘scaffold’, que como a palavra diz, serve como um andaime para a aplicação. Este comando gera os arquivos seguindo a arquitetura Rails, ou seja, ele cria um MVC, modelo, controlador, helper e as views. Veja abaixo:

Imagem

1
$>rails generate scaffold Contato nome:string telefone:string

O comando acima ira criar um MVC da tabela contato, já com todas as “telas” para criar, editar ou excluir contatos. Mas e se nós já temos um banco de dados? Aí as coisas mudam e o Rails já não é tão interessante quanto, porque nesse caso você terá que fazer tudo no braço e seguindo todo o protocolo que uma aplicação Rails exige. Isso será quase um parto se você realmente precisar chegar a tanto!

O Problema

Se nosso objetivo fosse criar um CRUD, então teríamos um problema, mas nosso foco é um webservice e para isso não é necessário nenhuma view.

Detalhes importantes

Para que esse processo funcione, será necessário:

Ruby 1.9.x
Rails 3.2.13

A gem ‘activerecord-oracle_enhanced-adapter’ não é compatível com o Rails 4. (Então se essa for a sua versão você não terá sucesso ao tentar criar um webservice com Rails e um Banco de Dados Oracle Legado.

OBS: Logo após ter escrito este post o pessoal que mantém o activerecord-oracle_enhanced-adapter liberou uma versão beta da gem compatível com Rails 4. Na seção abaixo, no item 11º altere a versão do activerecord-oracle_enhanced-adapter de … ‘~> 1.4.3‘  para … ‘~>1.5.0.beta1‘  (aspas simples)

Solução

1º Ter a última versão do Ruby 1.9.3 instalado em sua máquina (ou na máquina servidor)
2º fazer download instantclient-basic-win32-10.2.0.5.zip
3º Após o download do InstantClient fazer a extração onde achar melhor e copiar todos os *.dll para pasta bin do ruby “C:\Ruby193\bin”
4º Fazer download do Devkitvars e extrair todos os arquivos para dentro do diretório “C:\Ruby193\”
5º Acessar o diretório anterior via prompt de comando e executar o comando devkitvars: Exemplo C:\Ruby193> devkitvars
6º Se você estiver em uma rede com proxy deve fazer um SET do proxy antes de continuar. Ainda com o prompt aberto execute o comando SET HTTP_PROXY=http://usuario:senha@ip_proxy:porta Exemplo: C:\Ruby193>SET HTTP_PROXY=http://usuario:senha@ip_proxy:porta (substitua pelos valores reais do seu proxy)
7º Executar linha de comando: gem install rails -v 3.2.13 (aguardar, pois o processo pode demorar um pouco. Esse comando irá instalar a versão do Rails compatível com o adapter para Oracle. Exemplo C:\Ruby193> gem install rails -v 3.2.13
8º Para resolver problemas de acento com ruby e oracle execute o comando SQL no banco: select USERENV(‘LANGUAGE’) FROM DUAL;
Resultado do comando sql em minha máquina: BRAZILIAN PORTUGUESE_BRAZIL.WE8ISO8859P1
Depois acrescente ele depois do =, ficando assim: set NLS_LANG=BRAZILIAN PORTUGUESE_BRAZIL.WE8ISO8859P1
Execute esse comando no prompt da mesma forma que foi feito com o proxy.
9º Fazer a instalação das seguintes gem’s:

gem install bundler –pre
gem install rdoc
gem update –system (dar um update)
gem install ruby-oci8
gem install dbi
gem install ruby-plsql
gem install activerecord-oracle_enhanced-adapter

10º Agora pode criar sua api: C:\sites> rails new oracle_api -d=oracle
11º Acessar o diretorio oracle_api e editar o arquivo Gemfile:

Para Rails 3.2.x

# Use oracle as the database for Active Record
gem ‘ruby-oci8’, ‘~> 2.1.5’  (Editar essa linha pois já estará em seu arquivo)
gem ‘activerecord-oracle_enhanced-adapter’, ‘~> 1.4.3‘ (Acrescentar logo abaixo do ruby-oci8)

Para Rails 4

# Use oracle as the database for Active Record
gem ‘ruby-oci8’, ‘~> 2.1.0’  (Editar essa linha pois já estará em seu arquivo)
gem ‘activerecord-oracle_enhanced-adapter’, ‘~> 1.5.0.beta1‘ (Acrescentar logo abaixo do ruby-oci8)

12º Executar no console ainda dentro do diretório oracle_api: C:\sites\oracle_api> bundle install
13º Configurar o database.yml, pode deixar tudo como está, mexa apenas no development

development:
adapter: oracle_enhanced
database: //ip_servidor:1521/nome_sid ou seja //host:[port][/service name]
username: USUARIO
password: SENHA

14º Execute um rails server, se o Rails for carregado no navegador então deu tudo certo.

Finalmente (O pulo do gato)

O Segredo para tudo dar certo está em dois diretórios, models e controllers. Será necessário criar um arquivo dentro da pasta models, ele será o responsável pelo mapeamento da sua tabela. Mais uma coisa que deve ser esclarecida é a questão da nomenclatura. Nesse quesito de Banco Legado, pouco importa para o Rails o nome de suas tabelas, desde que seja seguido seus padrões. Vejamos:

Tabela AMOSTRAS:

amo_seq number(4)
amo_desc varchar2(100)
amo_ativo varchar2(1) ‘N’

Você precisará criar dois aquivos:

amostra.rb (..oracle_api\app\models)
amostras_controller.rb (..oracle_api\app\controllers)

Veja que o aquivo que será salvo na pasta models está no singular e o outro no plural com um _controller no final, essa padrão dever ser utilizado para qualquer projeto. Esse é um padrão do Rails ele faz isso de forma “automágica”, aqui temos que fazer na mão, pois estamos nos conectando a um banco existente.

Veja agora como ficaria o conteúdo do seu aquivo amostra.rb .:

class Amostra < ActiveRecord::Base
 self.table_name = 'amostras'
 self.primary_key = 'amo_seq'
before_save :increment
attr_accessible :amo_seq, :amo_desc, :amo_ativo
 def increment
  self[:amo_seq] = Amostra.select(:amo_seq).order('amo_seq desc').first.amo_seq.to_i + 1
 end
end

Com esse simples exemplo será possível a você mesmo avançar em seus estudos e desbravar todas as possibilidades relacionadas ao ActiveRecord, lembre-se de utilizar self. para setar o nome da tabela e o nome da chave primária, mais informações aqui:  ActiveRecord::ModelSchema::ClassMethods, before_save é um callback do Rails, são ganchos que permitem acionar algum tipo de lógica antes ou depois de uma alteração no objeto. Veja lista completa aqui: Active Record Callbacks. Sobre o attr_accessible veja esse post: http://simplesideias.com.br/recebendo-dados-do-usuario-attr_accessible-e-attr_protected e por fim o def increment é um método ruby que define como o incremento será feito, você pode ter quantos métodos quiser e chamá-los via callbacks.

Veja agora como ficaria o conteúdo do seu aquivo amostras_controller.rb .:
Veja que temos apenas dois métodos inicialmente, o index e o show.

class AmostrasController < ApplicationController
 # GET /amostras
 # GET /amostras.json
   def index
      @amostras = Amostra.all
      respond_to do |format|
         format.html #index.html.erb
         format.xml { render xml: @amostras}
         format.json { render json: @amostras}
     end
 end
 # GET /amostras/1
 # GET /amostras/1.json
   def show
       @amostra = Amostra.find(params[:id])
       respond_to do |format|
          format.html #show.html.erb
          format.xml { render xml: @amostra}
          format.json { render json: @amostra}
       end
 end
# GET /amostras/new
 def new
 end
# GET /amostras/1/edit
 def edit
 end
 # POST /amostras
 # POST /amostras.json
 def create
 end
 # PATCH/PUT /amostras/1
 # PATCH/PUT /amostras/1.json
 def update
 end
 # DELETE /amostras/1
 # DELETE /amostras/1.json
 def destroy
 end
end

Atenção ao nome das classes!

—————————————————

O nome do arquivo é amostra.rb, mas dentro dele o nome da classe é “class Amostra”.
O nome do arquivo é amostras_controller.rb, mas dentro dele o nome da classe é “class AmostrasController”, ou seja, sem underline e em camel case.

—————————————————

No método def index temos a variável @amostras e em def show @amostra no singular, isso tem lógica, no método show exibiremos uma amostra de cada vez.

Observe o método index:

@amostras = Amostra.all (Esse Amostra.all é o nome do seu arquivo amostra.rb que está na pasta models)
respond_to do |format|
  format.html #show.html.erb
  format.xml { render xml: @amostra}
  format.json { render json: @amostra}
end

No respond_to definimos como essas amostras serão renderizadas, como não temos nenhuma view foi colocado uma # logo após o format.html aí já ficou obvio né?

A única diferença do método index para o método show é que temos que setar um parâmetro para ele funcione.

Após iniciar sua aplicação com o comando rails server abra o navegador e digite:

http://localhost:3000/amostras.xml -> Lembra do @amostras, se você pensou que a palavra amostras está ali na url por causa dele está enganado, você coloca após a barra o nome do seu resource e a extensão desejada, ou seja, amostras.xml ou amostras.json. Para exibir apenas uma amostra faça assim: http://localhost:3000/amostras/1.xml, então é isso você põe o “nome_do_resource/id_da_amostra.extensão_desejada”.

Se você não configurar o resource nada disso será executado no navegador, estou falando do arquivo routes.rb:

O que conecta uma consulta de HTTP para uma URL específica para uma ação de um controlador ? Este é o trabalho do router Ruby on Rails, que correlaciona URLs com ações e garante que tudo vai para o lugar certo. Há um monte de coisas que você pode fazer com um roteador, mas pelo menos você precisa dizer a ele sobre recursos . Em Ruby on Rails, um recurso é muito menos de uma coisa, e muito mais de uma interface para uma coisa. O recurso não é a coisa em si, ou os dados que ele está acessando, mas é o conjunto de URLs que são mapeados para a coisa. http://ruby.about.com/od/rails3tutorial/ss/Router-Basics.htm

Você pode encontrar esse arquivo em ..oracle_api\config\routes.rb edite-o acrescentando a seguinte linha: “resources :amostras” sem as aspas ele ficará como abaixo:

OracleApi::Application.routes.draw do
   resources :amostras
 # Comentário foram suprimidos...

end

Mas como é que eu sei qual o nome do meu resource? Lembra do seu arquivo amostras_controller.rb então vem de lá, só que sem o _controller. Essa foi boa hein?

Conclusão

Você dever criar um model para cada tabela.
Você deve criar um _controller para cada model.
Você deve adicionar um resource no seu aquivo routes.rb para cada controller.

Se sua tabela tem underlines não tem problema, desde que você não os utilize “_”.

Exemplo:

tabela PESSOA_FISICA

Model = pessoafisica.rb
Controller = pessoafisicas_controller.rb

Nome da classe

Model = class PessoaFisica < ActiveRecord::Base
Controller = class PessoaFisicasController < ApplicationController

Em nosso exemplo esse webservice serviria apenas para expor os dados, pois não implementamos o POST, DELETE e o PUT, mas acredito que já deu para tirar você do sufoco de ter que começar do nada!

Anúncios

Carregar um combo box LIST ITEM Dinamicamente no Forms6i

Crie um gatilho do tipo PRÉ-FORM  e edite os dados abaixo para se ajustarem a sua tabela;

pre_FORM
É importante criar um campo Item_List ou Lista de Itens campo e definir o primeiro item da pop list, nas configurações do campo. Essas configurações são acessadas pela tecla de atalho F4.

propriedades_do_campo

— Carrega o combo box de Faixas Etárias dinamicamente

declare

list_id Item;
sql_query varchar2(500);
rg_id RecordGroup;
rg_name varchar2(15) := ‘faixa_etaria’;
errorcode number;

begin

rg_id := Find_Group(rg_name);

— Se o record group não existe, cria um

if Id_Null(rg_id) then sql_query := ‘select id_desc id_desc, id_seq from v_faixas_etarias where id_seq in(1,2)
union
select ”Todas as Faixas”,”0” from dual order by 2’;

rg_id := CREATE_GROUP_FROM_QUERY(rg_name, sql_query);
errorcode := POPULATE_GROUP(rg_id);

— Limpa o combobox e popula com
— os valores do select

list_id := FIND_ITEM(‘faixa_etaria’);
clear_list(list_id);
POPULATE_LIST(list_id, rg_id);

:faixa_etaria := ‘0’;

   end if;

end;

Vaja o campo tipo Lista de Item no canvas.

campo_em_tela

Connectar SQLplus no OracleXE 11g

 

Tentei de tudo para conectar no prompt sqlplus do Oracle XE 11g, mas sem sucesso.

C:\>C:\oraclexe\app\oracle\product\11.2.0\server\bin\sqlplus.exe /nolog

SQL*Plus: Release 11.2.0.2.0 Production on Ter Mai 7 03:05:15 2013

Copyright (c) 1982, 2010, Oracle. All rights reserved.

SQL> conn as sysdba
Informe o nome do usußrio: system
Informe a senha:
ERROR:
ORA-01031: insufficient privileges
SQL> CONN / AS SYSDBA
ERROR:
ORA-01031: insufficient privileges
SQL> sqlplus sys/system as sysdba
SP2-0734: inÝcio de comando desconhecido “sqlplus sy…” – restante da linha ign
orado.
SQL> conn sys/system as sysdba — Aqui está a solução, removi a palavra sqlplus do inicio do comando e conectei com sucesso.
Conectado.
SQL>

por Ecio Ferreira Postado em Oracle

Alterar Botão Ajuda no DEFAULT&SMARTBAR Forms 6i

 

É possível alterar o menu Help ou ajuda do DEFAULT&SMARTBAR do Forms 6i para chamar alguma url e abrir no navegador?

consegui resolver criando um Gatilho tipo KEY-HELP no forms que estava trabalhando. Após criar o gatilho configurei para chamar a url desejada.

Vejam o que escrevi dentro do bloco:

declare
v_url VARCHAR2(100);
curform VARCHAR2(40);
begin
v_url := http://minha_url; //minha url aqui
curform := :System.Current_Form; // com esse parametro eu pego o nome do form que estou trabalhando, pois o resultado final deve ser                    http://minha_url/nomeFormAtual;
— Colocar link para abrir url
HOST(‘CMD /C start ‘||v_url||curform);
null;
end;

Existem vários gatilhos tipo KEY no Forms6i, use sua criatividade!

Forms 6i conexão com Banco 11G 64 bits

 

 

1º Depois de instalar o Dev6 seguindo um tutorial encontrado no próprio forum, instalei o patch17 + patch18.
Copiei os arquivos sqlnet.ora, tnsnames.ora e listener.ora da pasta oraclexe para seus lugarem equivalentes na pasta orant.

2º ALTERAR O NLS_CHARACTERSET DO BANCO PARA UTF8

— SELECT PARA VER O ATUAL
SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER = ‘NLS_CHARACTERSET’;
— COMANDOS PARA EXECUTAR COMO SYSDBA
SHUTDOWN IMMEDIATE;
STARTUP RESTRICT;
alter database character set internal_use UTF8;
SHUTDOWN IMMEDIATE;
STARTUP;

3º DESATIVAR CASE SENSITIVE ORACLE 11G
— PARA VER A DEFINIÇÃO ATUAL
SHOW PARAMETER SEC_CASE_SENSITIVE_LOGON;
— PARA FAZER A ALTERAÇÃO
ALTER SYSTEM SET SEC_CASE_SENSITIVE_LOGON = FALSE;

4º ALTERAR O SQLNET.ORA PARA (NONE)
— AQUI ESTÁ O SEGREDO DE TODO O SUCESSO.
SQLNET.AUTHENTICATION_SERVICES = (NONE)

No último passo, fiz a alteração tanto na pasta C:\oraclexe\app\oracle\product\11.2.0\server\network\ADMIN assim como C:\orant\NET80\ADMIN. Lembrando que primeiro instalei banco de dados, depois instalei o Dev6 e copiei os arquivos sqlnet.ora, tnsnames.ora e listener.ora do primeiro caminho para o segundo. Sendo que o arquivo tnsnames deve estar na pasta ADMIN e na pasta TNSAPI do diretorio “orant” e o arquivo listener.ora deve estar apenas em TNSAPI.