레이블이 Development인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Development인 게시물을 표시합니다. 모든 게시물 표시

2016년 8월 2일 화요일

[Forms] Web Forms에서 사용 가능한 유용한 자바 샘플 소스

formsUitl.java


package formsUtil;
import java.net.InetAddress;import java.net.NetworkInterface;
import oracle.forms.ui.VBean;import oracle.forms.handler.IHandler;import oracle.forms.properties.ID;

/* *  * In Forms: BL.INFOS := Get_Custom_Property('CONTROL.BEAN', 1, 'GET_IP_ADDRESS' ) ; */
@SuppressWarnings("serial")public class formsUitl extends VBean {
/* * Define variables */ private static final ID MACHINE_NAME = ID.registerProperty("GET_MACHINE_NAME"); private static final ID IP_ADDRESS = ID.registerProperty("GET_IP_ADDRESS"); private static final ID MAC_ADDRESS = ID.registerProperty("GET_MAC_ADDRESS"); private static final ID OS_NAME = ID.registerProperty("GET_OS_NAME"); private static final ID ARCHITECTURE = ID.registerProperty("GET_ARCHITECTURE"); private static final ID OS_VERSION = ID.registerProperty("GET_OS_VERSION"); private static final ID USER_NAME = ID.registerProperty("GET_USER_NAME"); private static final ID USER_HOME = ID.registerProperty("GET_USER_HOME");
/* * Initialize forms handler */ public void init(IHandler handler) { super.init(handler);     }
/* * Get property */    public Object getProperty(ID pId) {       if (pId != null) {      return getMachineInfo(pId);       } else {      return super.getProperty(pId);       }    }        /* * getMachineInfo() */ private final static String getMachineInfo(ID pId) {    try {        InetAddress ip = InetAddress.getLocalHost();        NetworkInterface network = NetworkInterface.getByInetAddress(ip);        byte[] mac = network.getHardwareAddress();        StringBuilder sb = new StringBuilder();
if (pId == MACHINE_NAME) {         return ip.getHostName();        } else if (pId == IP_ADDRESS) {         return ip.getHostAddress();        } else if (pId == MAC_ADDRESS) { for (int i = 0; i < mac.length; i++) { sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : "")); } return sb.toString();        } else if (pId == OS_NAME) {         return System.getProperty("os.name");        } else if (pId == ARCHITECTURE) {         return System.getProperty("os.arch");        } else if (pId == OS_VERSION) {         return System.getProperty("os.version");        } else if (pId == USER_NAME) {         return System.getProperty("user.name");        } else if (pId == USER_HOME) {         return System.getProperty("user.home");        } else {         return null;        }    } catch (Exception e) {        e.printStackTrace();        return null;    } }
/* * Main method for Test */ public static void main(String[] args) {    try {        System.out.println("Host Name: " + getMachineInfo(MACHINE_NAME));        System.out.println("IP Address: " + getMachineInfo(IP_ADDRESS));        System.out.println("MAC Address: " + getMachineInfo(MAC_ADDRESS));        System.out.println("OS Name: " + getMachineInfo(OS_NAME));        System.out.println("Architecture: " + getMachineInfo(ARCHITECTURE));        System.out.println("OS Version: " + getMachineInfo(OS_VERSION));        System.out.println("User Name: " + getMachineInfo(USER_NAME));        System.out.println("User Home: " + getMachineInfo(USER_HOME));    } catch (Exception e) {        e.printStackTrace();    } }}

[Forms] Web Forms에서 한/영 자동 변환 자바 소스



// Note 438648.1



ChangeInputMethodOnFocus.java

package formsUI;
import java.awt.Component;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.im.InputContext;
import java.util.Locale;
public class ChangeInputMethodOnFocus extends FocusAdapter {
Locale _locale;
Locale defLocale;
public ChangeInputMethodOnFocus(Locale locale) {
_locale = locale;
}
public void focusGained(FocusEvent fe) {
Component c = fe.getComponent();
InputContext inputContext = c.getInputContext();
defLocale = inputContext.getLocale();
inputContext.selectInputMethod(_locale);
// Added by swan
if (_locale != null) {
if (_locale == Locale.KOREAN) {
Character.Subset[] subset = { Character.UnicodeBlock.HANGUL_SYLLABLES };
inputContext.setCharacterSubsets(subset);
} else {
Character.Subset[] subset = null;
inputContext.setCharacterSubsets(subset);
}
}
}
public void focusLost(FocusEvent fe) {
Component c = fe.getComponent();
InputContext inputContext = c.getInputContext();
inputContext.selectInputMethod(defLocale);
}
}

VTextFieldKor.java
package formsUI;
import java.util.Locale; import oracle.forms.handler.IHandler; import oracle.forms.ui.VTextField;
@SuppressWarnings("serial")public class extends VTextField {  public void init(IHandler ih) {  super.init(ih);  //ChangeInputMethodOnFocus focusAdapter = new ChangeInputMethodOnFocus (new Locale("ko","KR"));  ChangeInputMethodOnFocus focusAdapter = new ChangeInputMethodOnFocus (Locale.KOREAN);  this.addFocusListener(focusAdapter);  }

VTextFieldEng.java

package formsUI;
import java.util.Locale; import oracle.forms.handler.IHandler; import oracle.forms.ui.VTextField;
@SuppressWarnings("serial")public class VTextFieldEng extends VTextField {  public void init(IHandler ih) {  super.init(ih);  //ChangeInputMethodOnFocus focusAdapter = new ChangeInputMethodOnFocus (new Locale("en","US"));  ChangeInputMethodOnFocus focusAdapter = new ChangeInputMethodOnFocus (Locale.ENGLISH);  this.addFocusListener(focusAdapter);  }


VTextAreaKor.java
package formsUI;
import java.util.Locale; import oracle.forms.handler.IHandler; import oracle.forms.ui.VTextArea;
@SuppressWarnings("serial")public class VTextAreaKor extends VTextArea {  public void init(IHandler ih) {  super.init(ih);  //ChangeInputMethodOnFocus focusAdapter = new ChangeInputMethodOnFocus (new Locale("ko","KR"));  ChangeInputMethodOnFocus focusAdapter = new ChangeInputMethodOnFocus (Locale.KOREAN);  this.addFocusListener(focusAdapter);  }

VTextAreaEng.java
package formsUI;
import java.util.Locale; import oracle.forms.handler.IHandler; import oracle.forms.ui.VTextArea;
@SuppressWarnings("serial")public class VTextAreaEng extends VTextArea {  public void init(IHandler ih) {  super.init(ih);  //ChangeInputMethodOnFocus focusAdapter = new ChangeInputMethodOnFocus (new Locale("en","US"));  ChangeInputMethodOnFocus focusAdapter = new ChangeInputMethodOnFocus (Locale.ENGLISH);  this.addFocusListener(focusAdapter);  }


[Forms] Developer 10g Capture All CHANGED Item Values

https://community.oracle.com/thread/2325970?tstart=0

Developer 10g Capture All CHANGED Item Values
---------------------------------------------

My successful POST-UPDATE trigger at the form level ended up like:

<<
p_html := 'Catalog item ' || :ITEMS.MANUFACTURER || ' - ' || :ITEMS.MODEL_DESC || ' ' || :ITEMS.MODEL || ' has been modified and the results are as follows: <br> '; 

v_item := 'ITEMS' || '.' || get_block_property('ITEMS',first_item); 


<<item_loop>> 

loop 
exit when v_item = 'ITEMS' || '.' || null; 
v_dbvalue := GET_ITEM_PROPERTY(v_item,DATABASE_VALUE); 
v_itemname := GET_ITEM_PROPERTY(v_item,ITEM_NAME); 
v_block := 'ITEMS'; 
v_name := v_block || '.' || v_itemname; 
v_frmvalue := NAME_IN(v_name); 
IF v_dbvalue <> v_frmvalue THEN 
p_html := p_html || 'OLD VALUE WAS: ' || v_dbvalue || '<br>AND NEW VALUE IS: ' || v_frmvalue || '<br>'; 
END IF; 
v_item := 'ITEMS' || '.' || get_item_property(v_item,nextitem ); 
>>

The p_html variable is the string that I send to the email package to send out via our mail service.

2016년 8월 1일 월요일

[Ruby] 오라클 데이터베이스를 Ruby로 치장하십시오.

오라클 데이터베이스를 Ruby로 치장하십시오.


저자 - Dustin Marx

우아함, 단순성, 다양한 라이브러리, 강력한 OO(object-oriented) 기능을 지원하는 Ruby는 일반 애플리케이션뿐 아니라 스크립트 개발을 위한 강력한 언어 환경을 제공합니다.

게시일: 2007년 2월
강 력한 기능과 신속한 개발을 지원하는 다이내믹 스크립팅 언어의 인기가 치솟고 있습니다. Ruby on Rails가 각광 받으면서, Ruby가 소프트웨어 개발 커뮤니티의 첨병으로 자리잡고 있습니다. 하지만 Ruby는 단순한 웹 개발을 위한 언어가 아닙니다. Ruby는 데이터베이스 전문가들을 위한 강력하고, 우아하고, 유연한 스크립팅 언어로도 활용됩니다. 본 문서는 Ruby의 일부 기능에 대해 자세히 살펴보고, 이 기능을 오라클 데이터베이스에서 활용하는 방법에 대해 설명하고 있습니다.

Ruby: 소프트웨어 개발 환경의 "보석"

최근 들어 Ruby on Rails 웹 개발 프레임워크가 인기를 끌면서 Ruby에 대한 관심이 높아진 것은 사실이지만, Ruby가 실제로 사용되기 시작한 것은 이미 십여 년 전의 일입니다. Ruby는 다양한 빌트-인 기능과, 풍부한 라이브러리, 검증된 환경을 제공하는 오브젝트 지향형 다이내믹 스크립팅 언어입니다.
Ruby는 정규 표현식의 지원, 변수/메소드의 다이내믹 생성 등 Perl, Python과 같은 다른 다이내믹 스크립팅 언어가 제공하는 장점을 공유하고 있습니다. Java, C++, C# 등의 정적 언어를 주로 사용해온 개발자라면 Ruby가 다이내믹 언어에 입문하기 위한 좋은 방편이 될 수 있습니다. Ruby는 Perl에 비해 작성 및 해독이 훨씬 용이합니다.
필자의 동료 카메론 헨드릭스는 "Perl은 프로그래밍 언어의 라스베가스다"라고 말합니다. 다이내믹 언어는 런타임에 우리를 놀라게 하는 특성을 보이곤 합니다. 때로는 이러한 놀라움이 긍정적인 방향으로 나타나서 우리를 마치 잭팟을 터뜨린 것 같은 기쁨에 사로잡히게 합니다. 또 경우에 따라서는 런타임 다이내믹 언어가 경악할 만한 문제를 일으키기도 하며, 이러한 문제들은 디버그 하기도 쉽지 않습니다. Ruby는 Perl의 단점들을 피해 가면서도 Perl의 장점은 그대로 제공하는 특성을 보입니다. 필자에게 있어 Ruby는 보다 예측 가능한 언어이며, 코드 개발 과정에서의 도박을 피할 수 있게 합니다.
본 문서에서는 Ruby를 인터액티브한 방식으로 사용하고, 미리 작성된 스크립트를 이용하여 일상적인 데이터베이스 관련 작업을 수행하는 방법을 설명하고 있습니다. 본 문서에서 사용되는 예제들을 통해 오라클 데이터베이스 관련 Ruby 스크립트를 쉽게 작성할 수 있을 뿐 아니라, 간단하면서도 강력한 Ruby의 기능을 활용할 수 있음을 예시하고자 합니다.
Ruby 설치. Ruby는 특히 마이크로소프트 윈도우즈 환경에서 다운로드 및 설치가 용이합니다. RubyGems는 업데이트, 익스텐션 및 추가적인 Ruby 라이브러리의 설치를 위한 툴로 활용됩니다.
Ruby의 실행. 다운로드/설치한 Ruby를 실행하는 방법은 크게 두 가지가 있습니다. 첫 번째 방법은 .rb 익스텐션을 갖는 스크립트 파일을 작성하여 ruby 커맨드를 통해 실행하는 것입니다. 두 번째 방법으로, Interactive Ruby(irb 커맨드)를 사용하여 커맨드 라인에서 인터액티브한 방식으로 Ruby 커맨드를 실행할 수 있습니다.
Ruby를 설치하지 않은 상태에서 기본적인 Ruby 사용법을 확인하고 싶으시다면, 인터액티브 환경을 제공하는 Ruby 홈 페이지를 참고하시기 바랍니다. 본 문서에서 제공되는 데이터베이스 관련 예제들을 실행할 수는 없겠지만, 기본적인 Ruby의 빌트인 기능과 문법을 테스트하실 수 있습니다.

Hello, Ruby!

막 설치를 끝낸 Ruby에서 Interactive Ruby(irb)를 실행하여 그림 1처럼 멋진 계산기로 활용하실 수 있습니다. 그림 1과 그림 2는 Interactive Ruby가 지원하는 두 가지 프롬프트 스타일(default와 simple)을 보여 주고 있습니다. 그림 1은 Ruby의 산술 연산자를 이용하는 방법을, 그림 2는 문자열 연산자와 문자열/숫자 포맷 간 변환 기능을 예시하고 있습니다. Ruby 홈 페이지에서도 그림 1과 그림 2에서 사용된 irb 기능을 테스트해 보실 수 있습니다.
Figure 1
그림 1 Ruby 인터프리터와 Ruby 수학 연산자
Figure 2
그림 2 Ruby 인터프리터와 Ruby 문자열 연산자
Ruby 는 스크립트의 작성/유지보수에 매우 유용한 글로벌 상수들을 제공합니다. 그림 3은 사전 정의된 글로벌 상수의 활용 예를 보여 주고 있습니다. 이 세 가지 글로벌 상수들은 Ruby 인터프리터의 플랫폼, 버전, 출시일 정보를 표시하고 있습니다. 그림에는 예시되지 않았지만, 글로벌 상수 ENV를 사용해서 운영 체제의 환경 변수를 확인할 수도 있습니다. 문서의 뒷부분에서 ENV의 해쉬 버전을 사용하는 방법을 설명하겠습니다.
Figure 3
그림 3 유용한 Ruby 상수
그 림 4는 Interactive Ruby의 또 다른 유용한 기능을 보여 주고 있습니다. (그림에서는 TAB 버튼을 클릭하는 모습을 직접 보여 드릴 수 없었지만) IRB 프롬프트에서 "0."을 입력한 이후 TAB 버튼을 두 번 클릭하면, 0 또는 다른 숫자 값에 대한 메소드가 그림과 같이 표시됩니다. 이 기능을 JDeveloper와 같은 Java 통합 개발 환경에서 제공하는 메소드 네임의 자동 완성 기능과 유사한 것으로 생각하시면 되겠습니다. 그림에서 숫자를 위한 ceiling (ceil), floor, round 메소드 그리고 to_s (to string), to_a (to array)와 같은 변환 메소드가 제공되고 있음을 확인할 수 있습니다.
Figure 4
그림 4 Ruby IRB ? 탭을 이용한 자동 완성 기능

Ruby와 오라클 데이터베이스의 인터액션

본 문서에서는 Ruby와 오라클 데이터베이스의 커뮤니케이션을 위해 Ruby/OCI8을 사용하고 있습니다. Ruby/OCI8은 http://rubyforge.org/projects/ruby-oci8/에 서 다운로드할 수 있습니다. 인터액티브 IRB에서 데이터베이스에 접근하기 위한 Ruby 코드를 직접 작성할 수도 있지만, 그리 깔끔한 방법은 아닙니다. 보다 좋은 방법은 Ruby 스크립트 파일에 데이터베이스 액세스 코드를 작성해 넣은 후 ruby 인터프리터 커맨드를 사용해서 이 스크립트 파일을 실행하는 것입니다.
Ruby와 오라클 DDL SQL. 먼저 새로운 테이블을 생성하는 Ruby 스크립트 파일을 작성해 보겠습니다. 우선 require 구문을 사용해서 Ruby/DBI를 사용함을 선언한 후 Ruby/DBI API를 사용합니다. 구현된 코드가 Listing 1과 같습니다.
Listing 1 createStatesTable.rb
require 'dbi'

dbh = DBI.connect('DBI:OCI8:ORCL', 'hr', 'hr')
dbh.do("CREATE TABLE states (
           id CHAR(2) PRIMARY KEY,
    name VARCHAR2(15) NOT NULL,
    capital VARCHAR2(25) NOT NULL)")
dbh.disconnect 
Listing 1의 코드 중 대부분은 SQL*Plus 또는 SQL Developer에서 새로운 데이터베이스 테이블을 생성하기 위해 사용하는 SQL 코드와 동일합니다. 데이터베이스 연결 문자열은 "DBI:OCI8:ORCL" 문자열과 유저네임/패스워드(hr/hr)로 구성되어 있습니다. "DBI"는 표준적으로 정의되며, "OCI8"은 Ruby/OCI8 드라이버를, 그리고 "ORCL"은 데이터베이스 서비스를 의미합니다. 이 파일(createStatesTable.rb)은 커맨드 라인에서 간단한 createStatesTable.rb 명령으로 실행될 수 있습니다. 커맨드가 성공적으로 실행되면 아무런 출력도 제공되지 않지만, HR 스키마에 새로운 테이블이 생성된 것을 확인할 수 있습니다.
다른 데이터베이스 작업을 설명하기 전에, ruby 인터프리터 커맨드가 명령을 실행하기 전에 신택스를 점검할 수 있는 기능을 제공한다는 점을 미리 언급해 두는 것이 도움이 될 듯 합니다. 예를 들어, 테이블을 실제로 생성하지 않고 createStatesTable.rb 스크립트의 신택스만을 점검하고 싶다면 아래와 같이 -c 옵션을 사용하면 됩니다. ruby -c createStatesTable.rb.
Listing 1에서 dbh 변수의 데이터타입이 정의되어 있지 않음을 주목하시기 바랍니다. 다른 다이내믹 스크립팅 언어와 마찬가지로, Ruby는 변수의 데이터타입 선언을 요구하지 않으며 변수의 컨텍스트에 따라 데이터타입을 다이내믹하게 적용합니다. 나머지 Ruby 코드 예제에서도 이러한 "오리 타입(duck typing)"이 사용될 것입니다. 무슨 말인고 하니, 오리처럼 울고 걷는다면 그건 오리임에 분명하다는 뜻입니다.
Ruby와 오라클 DML SQL. 이제 생성된 STATES 테이블에 데이터를 입력해 봅시다. 몇 가지 미국의 주 정보를 입력하기 위한 코드가 Listing 2와 같습니다.
Listing 2 populateStatesTable.rb
require 'dbi'

dbh = DBI.connect('DBI:OCI8:ORCL', 'hr', 'hr')
sqlInsert = "INSERT INTO states (id, name, capital)
                         VALUES (?, ?, ?)"
dbh.do(sqlInsert, "AL", "Alabama", "Birmingham")
dbh.do(sqlInsert, "AZ", "Arizona", "Phoenix")
dbh.do(sqlInsert, "CO", "Colorado", "Denver")
dbh.do(sqlInsert, "FL", "Florida", "Tallahassee")
dbh.do(sqlInsert, "MA", "Maine", "Augusta")
dbh.do(sqlInsert, "PA", "Pennsylvania", "Philadelphia")
dbh.do(sqlInsert, "UT", "Utah", "Salt Lake City")
dbh.do(sqlInsert, "WA", "Washington", "Seattle")
dbh.do(sqlInsert, "WY", "Wyoming", "Cheyenne")
dbh.commit
dbh.disconnect
Listing 2에서 Ruby/DBI가 제공하는 몇 가지 새로운 기능을 확인할 수 있습니다. 먼저, INSERT 구문에서 위치지정자(placeholder)로 물음표 기호가 사용되었음을 주목하시기 바랍니다. 이 기호는 구문을 먼저 생성한 뒤, 각각의 주(state) 정보를 테이블에 입력하는 과정에서 매우 유용하게 활용됩니다. INSERT 구문은 DML 구문이므로 (Listing 1의 DDL CREATE 구문과 달리) 뒷부분에 반드시 COMMIT을 붙여 주어야 합니다.
스크립트 실행이 완료되면, 데이터가 입력된 STATES 데이터베이스 테이블을 얻게 됩니다. 이제 사용자가 입력 과정에서 몇 가지 실수를 했다고 가정해 봅시다. (MA는 Massachusetts의 약자이지만, 위에서는 MA가 Maine의 약자로 잘못 사용되었습니다. 그리고 주 정부가 위치한 도시의 이름들도 잘못 입력되었습니다.)
Listing 3는 이 문제를 해결하기 위한 간단한 UPDATE 스크립트를 예시하고 있습니다. Listing 3는 위치지정자를 사용해서 주 정부가 위치한 도시 이름을 업데이트하고, 위치지정자를 사용하지 않고 Maine 주의 약자를 수정하고 있습니다.
Listing 3 updateStatesTable.rb
require 'dbi'

dbh = DBI.connect('DBI:OCI8:ORCL', 'hr', 'hr')
sqlCapitalsUpdate = "UPDATE states SET capital = ? WHERE id = ?"
dbh.do(sqlCapitalsUpdate, "Montgomery", "AL")
dbh.do(sqlCapitalsUpdate, "Harrisburg", "PA")
dbh.do(sqlCapitalsUpdate, "Olympia", "WA")
dbh.do("UPDATE states SET id = 'ME' WHERE name = 'Maine'")
dbh.commit
dbh.disconnect
이미 예상하셨겠지만, DELETE는 INSERT, UPDATE와 같은 다른 DML 구문과 매우 유사한 방법으로 실행됩니다. 따라서 DELETE에 대한 설명은 생략하고 SELECT 구문으로 바로 넘어가겠습니다. SELECT 구문은 데이터베이스 쿼리를 통해 결과 셋을 가져온다는 점에서 다른 DML 구문과 차이를 갖습니다.
Listing 4는 데이터가 입력된 STATES 테이블에 간단한 쿼리를 수행하는 방법을 예시하고 있습니다. 빌트인 P 함수는 반환된 로우를 프린트합니다(그림 5 참고). 또는 빌트인 puts 메소드 도는 pp("pretty printer") 라이브러리를 사용해서 쿼리 결과를 디스플레이할 수도 있습니다. Listing 4에서는 쿼리 결과의 프린트를 위한 대안적인 방법들을 "#" 기호로 커멘트 처리하고 있습니다.
Listing 4 queryStatesTable.rb
require 'dbi'

dbh = DBI.connect('DBI:OCI8:ORCL', 'hr', 'hr')
rs = dbh.prepare('SELECT * FROM states')
rs.execute
while rsRow = rs.fetch do
   p rsRow
   #Alternative output: puts rsRow
   #Alternative output: pp rsRow
end
rs.finish
dbh.disconnect   
Figure 5
그림 5 쿼리 결과
Ruby DBI는 결과 출력을 위한 멋들어진 포맷팅 기능을 별도로 제공하고 있습니다. Listing 5, 6는 DBI를 사용하여 동일한 쿼리 결과를 테이블 포맷과 XML 포맷으로 출력하고 있습니다. Listing 5, 6에서는 결과 출력을 위해 DBI::Utils를 사용하고 있을 뿐 아니라, 결과 셋의 조회 및 처리 방법도 Listing 4와 조금 다릅니다.
Listing 5 queryStatesTableFormatter.rb
require 'dbi'

dbh = DBI.connect('DBI:OCI8:ORCL', 'hr', 'hr')
rs = dbh.execute('SELECT * FROM states')
rows = rs.fetch_all
column_names = rs.column_names
rs.finish
DBI::Utils::TableFormatter.ascii(column_names, rows)
dbh.disconnect
Listing 6: queryStatesTableXML.rb
require 'dbi'

dbh = DBI.connect('DBI:OCI8:ORCL', 'hr', 'hr')
rs = dbh.execute('SELECT * FROM states')
states_rows = rs.fetch_all
rs.finish
DBI::Utils::XMLFormatter.table(states_rows)
dbh.disconnect   
위 스크립트에 의해 생성된 테이블 출력과 XML 출력은 각각 그림 6, 7에서 확인하실 수 있습니다.
Figure 6
그림 6 쿼리 결과의 테이블 출력
Figure 7
그림 7 쿼리 결과의 XML 출력
지금까지 오라클 환경에서 Ruby를 이용하여 기본적인 CRUD (CREATE, RETRIEVE, UPDATE, DELETE) 작업을 실행하는 방법에 대해 설명했습니다. 이제 Ruby에서 오라클 스토어드 프로시저를 사용하는 방법을 배워 볼 차례입니다.
Ruby와 오라클 스토어드 프로시저. PL/SQL은 다양한 오라클 데이터베이스 기반 애플리케이션에서 적극적으로 활용되고 있는 언어입니다. 오라클 스토어드 프로시저에 관련하여 사용자들이 축적한 경험과 지식이 상당한 수준에 이르고 있기 때문에, 어떤 언어를 사용하든 오라클 스토어드 프로시저의 강력한 기능을 함께 활용하는 것이 매우 중요합니다.
Listing 7은 빌트인 PL/SQL 스토어드 프로시저 DBMS_UTILITY.DB_VERSION에 접근하기 위한 코드를 예시하고 있습니다.DBMS_UTILITY.DB_VERSION은 두 개의 OUT 매개변수를 제공하고 있으며, 코드는 이 매개변수들을 통해 전달된 결과를 출력합니다.
Listing 7 builtInDBVersionCompat.rb
require 'dbi'

db_read_str = 'BEGIN DBMS_UTILITY.DB_VERSION(?, ?); END;'
dbh = DBI.connect('DBI:OCI8:ORCL', 'hr', 'hr')
sth_db = dbh.prepare(db_read_str)
sth_db.bind_param(1, ' ' * 50)  # allow for up to 50 chars
sth_db.bind_param(2, ' ' * 50)  # allow for up to 50 chars
sth_db.execute
version = sth_db.func(:bind_value, 1)
puts "Oracle DB Version: " + version
compatibility = sth_db.func(:bind_value, 2)
puts "Oracle DB Compatibility: " + compatibility
dbh.disconnect   
위의 Ruby 코드를 실행한 결과가 그림 8과 같습니다.
Figure 8
그림 8 DBMS_UTILITY.DB_VERSION에 액세스하는 Ruby 코드의 실행 결과
Listing 7에서 흥미로운 점을 한 가지 발견할 수 있습니다. 이 코드는 Ruby 심볼(코드의 :bind_value)을 사용하는 방법과 DBI::Handle(코드의 sth_db) func 메소드를 사용해서 Ruby 데이터베이스 드라이버의 기능을 호출하는 방법을 예시하고 있습니다.
Listing 8의 코드는 Ruby DBI를 이용하여 빌트인 스토어드 함수 DBMS_METADATA.GET_DDL을 실행하는 방법을 예시하고 있습니다. 이 빌트인 함수는 여러 가지 관점에서 매우 유용합니다. 그 이유의 하나로 RUBY DBI의 함수로부터 반환된 값을 가져올 수 있다는 점을 들 수 있습니다. 이 함수는 오브젝트 타입과 오브젝트 네임이 다른 옵션 매개변수와 함께 전달될 것을 요구하고 있습니다. 아래 코드에서는 필수적으로 요구되는 두 개의 매개변수만을 전달하고 있으며, 매개변수 전달을 위해 "name notation"을 사용하고 있습니다.
Listing 8 builtInGetDDL.rb
require 'dbi'

db_read_str = 'BEGIN :out1 := DBMS_METADATA.GET_DDL(object_type=&gt;:in1, '
db_read_str += 'name=&gt;:in2); END;'
puts db_read_str
dbh = DBI.connect('DBI:OCI8:ORCL', 'hr', 'hr')
sth_db = dbh.prepare(db_read_str)
sth_db.bind_param("out1", ' ' * 20000 )
sth_db.bind_param("in1", "TABLE")
sth_db.bind_param("in2", "STATES")
sth_db.execute
puts sth_db.func("bind_value", "out1")
dbh.disconnect
DBMS_METADATA.GET_DDL 함수는 테이블 생성을 위한 DDL 구문을 반환합니다. 이 DDL 구문을 이용하면 필요할 때 테이블을 재생성할 수 있으므로 유용합니다. 반환된 DDL 구문은 앞에서 우리가 사용한 CREATE TABLE보다 더 자세하며, 우리가 가정한 설정을 명시적으로 정의하고 있습니다. 이 결과를 통해 오라클 데이터베이스의 내부적인 동작 원리에 대한 이해를 높일 수 있을 뿐 아니라, 어떤 매개변수를 튜닝해야 하는지 판단하기 위한 정보로 활용할 수도 있습니다.
Listing 8은 오라클 스토어드 함수로부터 반환된 값에 접근하는 방법과 함께, 앞에서 사용한 변수의 바인딩을 위한 새로운 방법을 예시하고 있습니다. 앞에서 바인드 변수를 사용한 코드(Listing 7)에서, 우리는 "positional binding"을 사용했습니다. 다시 말해, 데이터베이스 실행 문자열에 물음표 기호(?)를 위치시키고 1로 시작하는 연속적인 정수를 사용하여 값을 참조하였습니다. Listing 8에서는 "name binding"을 사용하고 있습니다. 즉, Ruby 심볼(:out1, :in1, :in2)을 위치시키고 이름 정보를 이용하여 바인드 변수들을 참조하고 있습니다. Ruby의 "positional/name binding" 지원 기능은 PL/SQL의 "positional/named parameter notation" 지원 기능과 유사합니다. 그림 9는 Listing 8(STATES 테이블 생성을 위한 DDL)의 실행 결과를 보여 주고 있습니다.
Figure 9
그림 9 DBMS_METADATA.GET_DDL로부터 생성된 DDL CREATE 구문

Ruby와 오라클: 데이터베이스가 전부는 아니다.

오라클 전문가들의 관심은 단지 오라클 데이터베이스에만 한정되는 것은 아닙니다. 설정 파일이 있고, 환경 변수가 있고, Oracle Application Server와 같은 다른 오라클 제품들도 있습니다. 이러한 영역에서 Ruby를 활용하는 방법에 대해 알아 보기로 합시다.
Ruby와 환경 변수. 를 이용하면 운영 체제의 환경 변수에 쉽게 접근할 수 있습니다. Listing 9은 정의된 환경 변수의 목록을 확인하기 위한 간단한 Ruby 프로그램의 예를 보여 주고 있습니다.
Listing 9 displayOracleENV.rb
ENV.each {|key ,value| print key, "=", value, "\n"}  
위 코드는 ENV 해쉬에 대해 반복 실행되며, 라인별로 하나씩 환경 변수를 출력합니다. 이 한 줄의 코드만으로도 Ruby 언어가 갖는 파워와 간결성을 확인할 수 있습니다.
Ruby와 운영 체제 파일. 오라클 데이터베이스를 관리하다 보면 init.ora와 같은 설정 파일의 컨텐트에 접근해야 하는 경우가 많습니다. Listing 10은 Ruby를 이용하여 파일의 key-value 설정을 조회하는 방법을 예시하고 있습니다.
Listing 10 displayInitOra.rb
=begin
This Ruby script demonstrates several Ruby features while performing the
functionality of returning values and their setting from the init.ora file.
This multiline comment block is demarcated by the =begin and =end.
Normal, single-line comments are also shown in this code (pound sign).
=end

fileName = ARGV.to_s
# example of if statement
if fileName.size &lt; 1
  print "Enter init.ora path and name: "
  fileName = gets.chomp!
end

#example of unless statement
unless fileName.size &gt; 1
  fileName = "C:\\oracle\\product\\10.1.0\\admin\\orcl\\init.ora"
end
print "File Name: " + fileName + "!"
theFile = File.new(fileName, "r")  # read the file
text = theFile.read  # copy file's contents into string
theFile.close        # string holds file contents; close file
regExp = Regexp.new('^.+=.+$')
puts text.scan(regExp)
Listing 10에서는 Ruby의 여러 가지 기능이 활용되고 있습니다. 그 중에서도 가장 중요한 기능으로 정규 표현식 처리를 위한 Regexp의 활용을 들 수 있을 것입니다. Regexp 인스턴스는 매치되는 문자열에 가장 적합한 패턴(^.+=.+$)으로 인스턴스화(instantiate) 됩니다. 정규 표현식은 문자열의 scan 메소드에 적용되어 정규 표현식에서 정의된 문자열과 매치되는 서브문자열을 반환합니다. Perl과 마찬가지로, Ruby는 환상적인 정규 표현식 기능을 제공합니다.
Listing 10은 또 커맨드 라인 또는 콘솔 기반 사용자 프롬프트로부터 입력을 받아 들이는 방법을 예시하고 있습니다. 코드는 먼저 사전 정의된 ARGV 변수를 이용하여 커맨드 라인으로부터 파일 경로와 파일 이름을 입력 받고 있습니다. 이 방법이 성공적이지 못한 경우, 다음으로 사용자에게 경로를 묻습니다. 사용자가 경로와 파일 이름을 입력하지 않았을 때에는 하드 코딩된 경로가 사용됩니다. 이 과정에서 if 구문과 (Perl과 유사한) unless 구문이 사용되고 있습니다.
또 Listing 10의 코드는 chomp! 메소드의 활용 예를 보여 주고 있습니다. 이 String 메소드는 사용자 콘솔로부터 문자열로 입력된 파일 이름의 뒷부분에서 구분자(separator)를 제거하기 위해 사용됩니다. 이 테크닉을 사용하지 않는 경우, 입력을 통해 전달된 newline 문자로 인해 File 오브젝트를 여는 과정에서 문제가 발생하게 됩니다. Ruby 메소드에 사용되는 느낌표(!)는 메소드가 오브젝트에 잠재적으로 위험한 작업을 수행함을 표시합니다. 또 Ruby의 메소드 뒤에 물음표(?)가 사용된 경우는 True 또는 False의 결과가 반환됨을 의미합니다.
이번 섹션의 마지막 예제에서는 두 개의 init.ora 파일을 비교하고 그 차이를 보고하는 간단한 Ruby 스크립트를 작성해 보겠습니다. Listing 11은 Listing 10과 유사한 방법을 사용하고 있지만, 커맨드 라인 매개변수를 통해 두 init.ora 파일의 컨텐트를 읽어 들인다는 점에서 다릅니다.
Listing 11 diffInitOra.rb
=begin
This script compares two files and returns from each file what it has that
the other provided file does not have.  Original order of either file does
not matter.
=end

require 'pp'

unless ARGV.size == 2
  print "Usage: ruby arrayMagic.rb firstFile secondFile"
  exit
end

firstFile = File.new(ARGV[0], "r")
secondFile = File.new(ARGV[1], "r")
regExp = Regexp.new('^.+=.+$')
text1 = firstFile.read.scan(regExp)
text2 = secondFile.read.scan(regExp)
firstFile.close
pp firstFile
puts text1-text2, "\n"
pp secondFile
puts text2-text1
secondFile.close
위의 예제 코드는 pp 라이브러리를 이용해서 파일 이름을 출력하고, 두 파일 중 하나가 아직 열리지 않은 상태이면 파일이 닫혀있음을 보고합니다. 또 Ruby의 강력한 마이너스 연산자의 활용 예를 확인하실 수 있습니다. 파일로부터 읽어 온 두 개의 문자열 사이에 마이너스 기호를 적용하기만 하면, 파일 간의 차이를 쉽게 확인할 수 있습니다.
Listing 11의 실행을 위해, 필자는 기존 init.ora 파일의 복사본을 생성한 후 복사본에서 3 개의 매개변수(open_cursors, db_name, job_queue_processes)를 변경하였습니다. 또 좀 더 흥미를 돋구기 위해, init.ora 파일 복사본의 매개변수 순서를 변경해 보았습니다. 그림 10는 이 두 개의 init.ora 파일에 대해 Listing 11의 코드를 실행한 결과를 보여 주고 있습니다. 그림에서 확인할 수 있듯 아주 간단한 코드 만으로 (심지어 파일의 라인 순서가 뒤바뀐 상태에서도) 파일 간의 차이를 비교할 수 있었습니다.
Figure 10
그림 10 두 init.ora 파일의 차이 비교
위 예제에서 확인한 것처럼, Ruby는 매우 단순하고도 강력한 파일 처리 기능을 제공합니다. 스풀링된 출력과 다른 유형의 파일에서도 Ruby를 유용하게 활용할 수 있습니다.

Ruby의 예외 처리 기능

Ruby 는 스크립트 및 OO(object-oriented) 애플리케이션에서 활용 가능한 강력한 기능을 제공하고 있습니다. 그 대표적인 예의 하나로 Ruby의 예외 처리(exception handling) 기능을 들 수 있습니다. Listing 12는 Ruby의 예외 처리 메커니즘을 구현한 예입니다.
Listing 12 rubyExceptions.rb
=begin
This script is similar to Listing 10, but demonstrates Ruby exception handling
using functionality originally demonstrated in Listing 10.
=end

fileName = ARGV.to_s

#obtain file name if not provided on command-line
if fileName.size &lt; 1
  print "Enter init.ora path and name: "
  fileName = gets.chomp!
end

#ensure something has been provided for file name
begin
  if fileName.size &lt; 1
    raise ArgumentError, "No valid file name provided" + "\n"
  end
rescue ArgumentError =&gt; argErr
  print argErr
  raise  # re-raise this exception and force script termination
end

#get file contents
begin #Begin exception handling block for file I/O
  theFile = File.new(fileName, "r")
  text = theFile.read
  theFile.close
rescue IOError
  print "I/O Error: Problem accessing file " + fileName + "\n"
  exit
rescue Errno::ENOENT
  print "ENOENT: Cannot find file " + fileName + "\n"
  exit
rescue Errno::EPERM
  print "EPERM: Insufficient rights to open " + fileName + "\n"
  raise
rescue Exception  # Catch-all: More exceptions captured than with "rescue" alone
  print "Generic error rescued (captured) during file I/O attempt." + "\n"
  raise
else
  print "Good news!  There was no problem with file I/O for " + fileName + "\n"
ensure
  print "Good or bad, file handling attempt is now complete!\n"
end #End exception handling block for file I/O

#obtain text string for regular expression
print "Enter regular expression pattern: "
pattern = gets.chomp!

begin #Begin exception handling block for regular expression
  regExp = Regexp.new(pattern)
rescue RegexpError
  print "Problem with regular expression " + regExp.to_s + "\n"
  exit  # Nothing to be done with a bad regular expression
ensure
  print "Regular expression evaluated was: " + regExp.to_s + "\n"
end #End exception handling block for regular expression

puts text.scan(regExp)
Listing 12에서는 begin 키워드를 사용하여 익셉션(exception)이 발생될 수 있는 코드 블록의 시작 부분을 표시하고 있습니다. 또 raise 키워드를 사용하여 스크립트가 자체적으로 익셉션을 발생시킬 수 있도록 하였습니다. 위 코드에서 여러 차례 사용된 rescue 키워드는 Java의 catch 키워드와 유사합니다. Ruby의 ensure 키워드는 Java의 finally 키워드와 유사하며, 이 코드에서는 익셉션 발생 여부에 관계없이 기능을 실행하기 위해 적용되었습니다.
Listing 12에서 확인할 수 있는 것처럼, Ruby는 begin과 end로 묶인 코드 블록에서 익셉션이 발생하지 않는 경우 특정 기능을 실행하기 위한 else 키워드를 지원합니다. 코드에 포함된 커멘트를 통해 Ruby의 예외 처리 기능에 대한 자세한 정보를 얻으실 수 있을 것입니다.
그림 11는 Listing 12의 스크립트를 3 회에 걸쳐 실행한 결과를 보여 주고 있습니다. 첫 번째 스크립트에서는 예외 처리 기능을 호출하기 위해 존재하지 않는 파일 이름을 지정해 보았습니다. 그런 다음 올바른 파일 이름을 이용하여 스크립트를 재실행하여, else 블록을 실행하고 정규 표현식 처리를 위한 다음 블록으로 이동하는 과정을 테스트하였습니다. 스크립트를 두 번째 실행하는 과정에서, RegexpError를 발생시키기 위해 올바르지 않은 정규 표현식을 적용하였습니다. 세 번째로, 익셉션이 전혀 발생하지 않는 조건 하에서 스크립트를 실행하였습니다. ensure 블록은 세 번의 실행 과정 모두에서 실행됩니다. 이 블록은 익셉션의 발생 여부와 무관하게 항상 호출되도록 정의되어 있기 때문입니다.
Figure 11
그림 11 Ruby 예외 처리 기능의 실행
Ruby DBI 예외 처리. 바로 앞의 섹션에서 Ruby의 예외 처리 기능에 대해 알아 보았습니다. Ruby/DBI는 자체적인 예외 처리 계층을 제공합니다(Listing 13 참고). 실제 환경에서는 Listing 13과 같이 "database catch all" 익셉션(DBI::DatabaseError)만을 캡처하고 그 속성에 접근하여 데이터베이스 코드와 에러 메시지를 출력하는 방법이 자주 활용되고 있습니다.
Listing 13 rubyDbExceptions.rb
=begin
Listing13-rubyDbExceptions.rb

This script demonstrates the use of exceptions with DBI::DatabaseError
and database-related exception classes that inherit from DBI::DatabaseError.
Often, it is enough to capture DatabaseError, but this example shows all
of the inherited exception classes.  DatabaseError is rescued last so that
a more particular database-related exception might be rescued first.

This "try" block of this code includes an "infinite" while loop that will
open connections without closing them until a DBI::DatabaseError is forced.
=end

require 'dbi'

begin
  counter = 0
  while 0  # "infinite" loop because 0 resolves to "true" for Ruby conditional
    dbh = DBI.connect('DBI:OCI8:ORCL', 'hr', 'hr')
    counter += 1
    puts "DB Connection #" + counter.to_s + "\n"
    #Intentionally NOT closing with dbh.close to force DatabaseError.
  end
rescue DBI::DataError =&gt; dataErr
  dbh.rollback
  puts "DB error due to problem with data"
  puts "Error Code: #{dataErr.err}"
  puts "Error Message: #{dataErr.errstr}"
  puts "DB rollback.\n"
rescue DBI::IntegrityError =&gt; integErr
  # Example: Trying to insert same value for unique column twice.
  dbh.rollback
  puts "DB error due to integrity problem."
  puts "Error Code: #{integErr.err}"
  puts "Error Message: #{integErr.errstr}"
  puts "DB rollback.\n"
rescue DBI::InternalError =&gt; internErr
  dbh.rollback
  puts "DB error database internal error."
  puts "Error Code: #{internErr.err}"
  puts "Error Message: #{internErr.errstr}"
  puts "DB rollback.\n"
rescue DBI::NotSupportedError =&gt; notSuppErr
  dbh.rollback 
  puts "DB feature not supported."
  puts "Error Code: #{notSuppErr.err}"
  puts "Error Message: #{notSuppErr.errstr}"
  puts "DB rollback.\n"
rescue DBI::OperationalError =&gt; opErr
  dbh.rollback
  puts "DB error due to problems with operation of database."
  puts "Error Code: #{opErr.err}"
  puts "Error Message: #{opErr.errstr}"
  puts "DB rollback.\n"
rescue DBI::ProgrammingError =&gt; dbProgErr
  # Example: Bad column name in SQL statement.
  dbh.rollback
  puts "DB error due to programming problem.\n"
  puts "Error Code: #{dbProgErr.err}"
  puts "Error Message: #{dbProgErr.errstr}"
  puts "DB rollback.\n"
rescue DBI::DatabaseError =&gt; dbErr
  # Catch-all for all database exceptions.
  dbh.rollback
  puts "Database exception encountered."
  puts "Error Code: #{dbErr.err}"
  puts "Error Message: #{dbErr.errstr}"
  puts "DB rollback."
rescue DBI::InterfaceError =&gt; ifError
  dbh.rollback
  puts "Problem with DBI interface encountered."
rescue RuntimeError
  dbh.rollback
  puts "Unknown error (not DB or DBI) encountered."
else
  puts "DB commit.\n"
  dbh.commit
ensure
  puts "Disconnecting database handler."
  dbh.disconnect
end  
Listing 13에서 사용된 DBI 익셉션은 DBI::DatabaseError로부터 유도된 것 말고도 (데이터베이스가 아닌 DBI 인터페이스와 관련된 에러를 캐치하기 위한) DBI::InterfaceError 익셉션을 포함하고 있습니다.
Listing 13의 코드를 실행하면 익셉션이 발생됩니다. 익셉션이 발생될 때까지 "while 0" 루프(Ruby에서 0은 "true"를 의미합니다)가 반복적으로 실행되기 때문입니다. 익셉션이 발생되는 이유는 오픈된 연결을 닫지 않은 상태에서 DBI:DatabaseError 익셉션이 발생할 때까지 DBI.connect가 반복적으로 호출되기 때문입니다. 이때 발생되는 에러 코드는 12520(오라클의 데이터베이스 에러 코드), 에러 문자열은 "ORA-12520: TNS:listener could not find available handler for requested type of server"입니다. 이 코드와 문자열 값은 각각 DBI::DatabaseError의 err, errstr 속성을 이용해서 출력할 수 있습니다.
Listing 13에서 의도적으로 데이터베이스 에러를 발생시키기 위해 추가된 while 루프를 정상적인 데이터베이스 구문(예: SELECT 구문)으로 대치한다면, Listing 12의 경우와 마찬가지로 rescue, else, ensure 블록이 활성화될 것입니다. 혹시라도 (무결성 제약 조건 위반 등으로 인해) 익셉션이 발생하는 경우 "rescue" 블록이 호출되어 처리됩니다. rescue 블록이 지정되지 않은 익셉션이 발생하는 경우, else 블록의 코드가 실행되고 트랜잭션은 커밋 처리됩니다. 어떤 경우든, 다시 말해 익셉션의 발생 여부에 관계없이 ensure 블록의 코드는 무조건적으로 실행되어 핸들러와의 연결을 해제합니다.
Ruby 스크립트를 작성할 때, 반드시 익셉션을 캐치(rescue)해야 하는 것은 아닙니다. (Java의 "unchecked" 익셉션을 상기하시기 바랍니다.) Listing 12 이전의 모든 코드에서도 예외 처리 기능은 구현되지 않았습니다. 하지만, 특정 익셉션이 발생할 가능성이 있고 이에 대해 어떤 식으로든 대응하고자 한다면, Ruby를 이용하여 간단하게 예외 처리 기능을 구현할 수 있습니다. 익셉션이 발생되는 코드 블록에 rescue-else-ensure 블록을 연결시키지 않는 경우, 스크립트는 그 블록 내에서의 실행을 중단하고 "general exception" 정보를 표시한 후 다음 코드 블록을 실행합니다.
그림 12는 Ruby의 주요 익셉션 중 몇 가지를 보여 주고 있습니다. 그림 13은 Ruby DBI 익셉션을 보여 주고 있습니다. 이러한 표준 익셉션 이외에도 직접 Ruby 익셉션을 생성하여 활용할 수도 있습니다.
Figure 12
그림 12 몇 가지 Ruby 익셉션
Figure 13
그림 13 Ruby/DBI 익셉션
Java와 마찬가지로 Ruby는 오브젝트 지향형(OO) 언어로 구현되었습니다. 덕분에 필자는 그림 12, 13의 클래스 다이어그램을 Oracle JDeveloper 10g의 UML 모델링 툴을 이용하여 생성할 수 있었습니다.

Ruby와 O-R(Object-Relational) 매핑

본 문서를 통해 Ruby와 Ruby/DBI를 이용해서 데이터베이스 작업을 수행하는 방법을 배워 보았습니다. 데이터베이스에 직접 스크립트를 실행하는 일반적인 환경이라면, 지금까지 설명한 방법이 가장 합리적인 선택이 될 것입니다. 하지만 Ruby와 오라클 데이터베이스에서 오브젝트-관계형(object-relational) 매핑 접근법을 사용하고자 한다면, ActiveRecord가 적절한 선택이 될 수 있습니다.
ActiveRecord는 Ruby on Rails에서 처음 소개되었지만, 현재는 Rails가 구현되지 않은 환경에서도 사용이 가능합니다. ActiveRecord는 ORM 환경을 단순화하기 위한 여러 가지 관례와 가정에 의존하고 있습니다. ActiveRecord에서 사용되는 대부분의 관례는 Ruby 모델 클래스, 오라클 데이터베이스 테이블 및 컬럼의 명명 규칙과 관계되어 있습니다. ActiveRecord는 또 기존 관례 및 가정에서 벗어난 예외 규칙을 적용하기 위한 단순화된 override 메커니즘을 제공하고 있습니다.
ActiveRecord는 Ruby의 OO 기능을 활용한 대표적인 사례이며, 특히 상속(inheritance)와 믹스-인(mix-in)을 지원합니다. 개발자들은 ActiveRecord를 사용하면서 ActiveRecord 모델 클래스에 거의 코드를 추가할 필요가 없습니다. 대부분의 기능이 전체 모델에 의해 상속되는 베이스 ActiveRecord 클래스를 통해 제공되고 있기 때문입니다.

Ruby와 웹 개발

최근 들어 Ruby on Rails의 인기가 급증하면서, 이제 Ruby를 위한 다른 웹 프레임워크의 대안은 고려할 수조차 없게 되었습니다. 다른 웹 프레임워크도 Ruby를 지원하고 있지만, Rails는 이 분야에서 분명한 강자로 인정받고 있습니다. 실제로 Ruby on Rails는 Ruby가 명성을 얻게 되는 계기가 되었을 뿐 아니라, Python, Java와 같은 다른 언어에서도 이와 유사한 프레임워크를 개발하기 위한 동기를 제공하였습니다. Ruby를 이용하여 웹 개발을 수행한다면, Ruby on Rails가 유력한 선택이 될 수밖에 없습니다.

Ruby는 단순한 스크립팅 언어가 아닙니다.

본 문서에서는 데이터베이스 접근 및 데이터베이스 파일의 처리에 관련한 Ruby의 스크립팅 기능에 초점을 맞추고 있습니다. 하지만 Ruby는 그 이상의 것을 제공합니다. 우아함, 단순성, 다양한 라이브러리, 강력한 OO(object-oriented) 기능을 지원하는 Ruby는 일반 애플리케이션뿐 아니라 스크립트 개발을 위한 강력한 언어 환경을 제공합니다.
Rails를 사용하든 사용하지 않든, Ruby는 배우고 사용할 가치가 충분한 유용한 언어입니다. Ruby는 복잡한 오브젝트 지향형 애플리케이션이나 웹 애플리케이션의 개발을 위해 사용될 수 있으며, 또 한편으로 오라클 데이터베이스와 기타 오라클 툴에 관련한 스크립팅을 위한 매우 강력한 도구로 활용됩니다.

Dustin Marx는 Raytheon Company의 수석 소프트웨어 엔지니어 겸 아키텍트입니다.

[Ruby] Ruby on Rails on Oracle: 간단한 튜토리얼

Ruby on Rails on Oracle: 간단한 튜토리얼 

저자 Richard Monson-Haefel

Rails는 매우 쉽고 편리한 프레임워크 이지만, 다른 테크놀로지와 마찬가지로 마스터하는데 시간이 필요합니다.
게시일: 2006년 4월
이미 Ruby on Rails에 대한 소식을 들으셨을 줄 압니다. Rails는 웹 개발자 커뮤니티, 특히 J2EE/PHP 개발자들 사이에서 센세이션을 불러일으키고 있는 새로운 애플리케이션 프레임워크입니다.
Rails 는 상당한 잠재력을 가진 애플리케이션 플랫폼으로, 불과 2년 사이에 J2EE/PHP 프로그래머들 사이에서 큰 반향을 불러 일으키는데 성공하였습니다. Rails가 제공하는 장점을 고려한다면 이러한 반응이 결코 놀랄 일은 아닙니다. 특히, Rails는 누구나 인정할 만큼 엄격한 모델-뷰-컨트롤러(model-view-controller) 아키텍처를 사용하고 있으며, 이 때문에 J2EE 개발자들 사이에서 높은 인기를 얻고 있습니다. 또 다른 한편으로, Rails를 이용한 기본적인 시스템의 개발이 매우 쉽고 간단하다는 점에서 PHP 개발자들 사이에서 인기를 누리고 있습니다.
하지만, 데이터베이스 관점에서 보았을 때 Rails는 몇 가지 심각한 제약 사항을 안고 있습니다. Rails는 데이터베이스 레이아웃과 애플리케이션 요구사항에 대해 지나칠 정도로 많은 가정을 수행합니다. 한 예로, Rails는 모든 테이블이 단일 비조합형(non-compound) 프라이머리 키를 사용한다고 가정합니다. 따라서 조합형 프라이머리 키는 지원이 불가능합니다! 또 Rails는 2 단계 커밋을 지원하지 않으며, 단이 데이터베이스 백엔드에서만 사용이 가능하도록 설계되어 있습니다.
본 문서는 Rails를 과대평가하거나 평가절하하지 않고, 단순히 테크놀로지에 대한 개요를 제공하기 위한 목적에서 작성되었습니다. 본 문서는 Rails에 대한 찬사와 비난을 모두 포함하고 있습니다. (Rails 옹호자의 입장에서) Rails에 대한 필자의 비판이 지나치다고 생각되는 부분도 있을 수 있습니다. 하지만 J2EE, ASP.NET, PHP 등 어떤 환경에서든 웹 애플리케이션 프레임워크의 적용은 까다로운 작업일 수 밖에 없습니다. 장기적으로 볼 때 다른 웹 애플리케이션 개발 플랫폼보다 Rails가 높은 생산성을 제공하는 것으로 판명될 수도 있겠지만, 그 비결을 터득하기까지는 어느 정도 시간이 필요합니다.
Ruby란 무엇인가? Rails란 무엇인가?
Ruby 는 Perl, Python, Smalltalk와 여러 가지 측면에서 유사성을 갖는 다이내믹 프로그래밍 언어입니다. Java와 PHP 프로그래머들은 Ruby를 비교적 쉽게 터득하고 Ruby의 강력한 옹호 계층을 형성하고 있습니다. 또 마이크로소프트 세계에서 잘 알려진 돈 박스(Don Box)와 같은 이 역시 이 언어의 매력에 빠져들고 있습니다.
Ruby 는 새로운 기술이 아닙니다. Ruby는 1993년 고안되었으며, 따라서 1995년 최초로 공개된 Java, PHP보다 오랜 역사를 갖고 있습니다. 따라서 Ruby는 성숙도 면에서 뛰어남에도 불구하고 다른 언어에 비해 높은 인기를 누리지 못했습니다. 이러한 이유로, Ruby의 주변 환경은 Java, PHP, Perl 만큼 풍요롭지 못하며, Ruby에 관련한 프레임워크, 라이브러리, 전문 서적, 웹 사이트, 블로그 등의 리소스도 드문 편입니다.
하지만 최근 들어 David Heinemeier Hanson이 (Ruby의 역사상 가장 인기 있는 애플리케이션이 되어 버린) Rails 프레임워크를 공개한 이후로, Ruby 커뮤니티의 마케팅 파워는 급상승하기 시작했습니다. Rails는 Ruby 프로그래밍 언어를 웹 개발을 위해 특화된 도메인 단위의 언어로 확장할 수 있게 합니다. 또 ActiveRecord와 같은 익스텐션을 이용하여 Ruby를 오브젝트-관계형 퍼시스턴스에 적용하는 것도 가능합니다. Rails이 조합형 프라이머리 키와 2단계 커밋을 지원하지 않는다는 문제를 제외했을 때, Ruby의 도입에 가장 큰 걸림돌이 되는 것은 아마도 새로운 언어를 배워야 한다는 부담일 것입니다. 새로운 언어를 배운다는 것은 매우 흥미롭기도 하지만 또 한편으로 무척 어려운 일이기도 합니다.
하 지만 여러분의 경력을 개발하는 것이 주된 관심사라면, 필자로서는 Ruby보다 적절한 언어를 추천하기 어렵습니다. Ruby는 상업적 이해관계에 휘둘리지 않은 채로 개발자 커뮤니티에서 지난 10 년간 축적된 성과를 함축하고 있는 언어입니다. 그 결과로 Ruby는 매우 다루기 즐거운 언어가 되었을 뿐 아니라 많은 경우 Java, C, Microsoft .NET 언어보다 수십 배 뛰어난 생산성을 제공합니다. (예외적인 경우로 IronPython을 생각할 수 있습니다. IronPython은 Python을 Microsoft .NET 환경에 포팅한 다이내믹 언어로, Ruby와 마찬가지로 뛰어난 생산성을 제공합니다.)
Rails는 어떻게 활용되는가?
Rails 는 관계형 데이터베이스 백엔드를 사용하는 다이내믹 웹 사이트의 생성을 위해 설계된 플랫폼입니다. Rails는 Ruby 프로그래밍 언어에 키워드를 추가하여 웹 애플리케이션의 설정을 용이하게 합니다. 또 Rails는 기존 데이터베이스 스키마로부터 (다소 거칠지만) 완결된 형태의 웹 애플리케이션을 자동으로 생성하는 기능을 제공하도록 설계되었습니다. 이 기능은 Ruby의 가장 뛰어난 장점이자 동시에 아킬레스 건이기도 합니다. Rails는 데이터베이스 스키마의 명명법(naming convention)에 대해 가정을 수행합니다. 이 가정이 올바르다면, 단 하나의 커맨드만으로도 기본적인 웹 사이트를 성공적으로 생성할 수 있습니다. 하지만 이를 위해 추가적인 설정이 필요할 수도 있고, 경우에 따라서는 아예 불가능할 수도 있습니다. 물론 데이터베이스에 대한 Rails의 가정을 무효화할 수도 있지만, 가정되는 내용이 적어질 수록 플랫폼의 생산성 또한 저하됩니다. Rails가 신규 데이터베이스를 포함하는 애플리케이션을 새로이 개발하는 경우에 특히 유용한 이유가 여기에 있습니다. 아쉽게도, Rails는 레거시 시스템에 관련해서는 훌륭한 솔루션이 되기 어렵습니다.
Rails를 이용하여 신규 애플리케이션을 개발하는 과정을 예로 들어, 그 효과를 확인해 보기로 합시다. 이미 오라클 데이터베이스가 설치되어 있는 환경이라면, 불과 15 분 만에 전체 웹 애플리케이션을 생성할 수 있습니다. 아래에서는 Ruby on Rails를 사용하여 제품 카탈로그를 생성하는 방법을 예시하고 있습니다.
예제: 간단한 제품 카탈로그의 생성
작 년, 필자는 1946년 이후 발매된 HG 코믹 북을 수집하면서, 구입 또는 판매된 만화책 정보를 업데이트하기 위한 간단한 Ruby on Rails 데이터베이스 애플리케이션을 작성하였습니다. 이 애플리케이션은 개인적인 용도로만 사용되는 것이었으므로 그 구조를 매우 간단하게 가져갈 수 있었습니다. 본 문서에서 예시되는 애플리케이션은, 필자가 집에서 사용 중인 Ruby on Rails 애플리케이션의 간소화된 버전입니다.
Rails과 오라클 데이터베이스는 다양한 플랫폼을 지원하지만, 예제에서는 (오라클 애플리케이션 개발자들이 가장 즐겨 사용하는 운영체제의 하나인) Windows XP 환경에 초점을 맞추고 있습니다. 본 예제는 매우 단순한 형태를 취하며, 프로그래밍 언어의 “Hello World” 예제와 비슷한 수준으로 생각하실 수 있습니다. 본 예제는 Ruby에 대한 간단한 “맛보기” 용도로 제공되며, 따라서 Rails가 포함하는 전체 기능과는 무관합니다.
본 예제를 실행하는 과정에서 문제가 발생했다면, 그 원인은 다음 세 가지 중 하나일 것입니다. 먼저 잘못된 코드를 다운로드했거나, 데이터베이스에 대한 연결이 올바르게 설정되어 있지 않거나, Windows XP 운영체제가 문제가 될 가능성이 있습니다. 본 예제를 개발하는 과정에서, 필자는 버전 및 데이터베이스 설정에 관련한 여러 가지 문제들을 경험했습니다. 필자의 친구인 Michael Carlland의 도움 덕분에 최대한 단순화된 형태의 실행 가능한 예제를 구현할 수 있었습니다.
하지만 실제로 Ruby on Rails와 오라클 환경을 연동하는 것은 그리 간단한 작업이 아닙니다. 때로는 이러한 과정이 무척 까다롭게 느껴질 수도 있습니다. 본 문서의 지시사항을 그대로 따른다면 문제를 겪을 일이 없을 것입니다. 하지만, 본 예제의 지시사항에서 조금이라도 벗어나는 경우 몇 가지 문제가 발생할 것을 각오해야 합니다. Rails는 매우 뛰어난 생산성을 제공하는 플랫폼이지만, 기본적으로 커맨드 라인 개발 환경만을 구현하고 있으므로 최신 통합 개발 환경에서 일반적으로 기대되는 “자동화” 기능을 제공하지 않습니다. 여러분이 DIY 타입의 개발자가 아니라면, 필자는 현 시점에서 여러분에게 Rails를 추천하지 않겠습니다.
1 단계: 오라클 데이터베이스의 셋업
먼 저 오라클 데이터베이스 인스턴스가 설치된 환경에 새로운 테이블을 추가해야 합니다. 이 과정에서 본 문서에서 사용된 것과 동일한 명명법을 사용하도록 주의해야 합니다. 그렇지 않은 경우 Rails가 제공하는 자동 코드 생성 기능이 제대로 동작하지 않을 것입니다. 새로 생성되는 테이블의 구조가 아래와 같습니다:
CREATE TABLE comics (
 id  NUMBER(10) NOT NULL,
 title  VARCHAR2(60),
 issue  NUMBER(4),
 publisher VARCHAR2(60),
 PRIMARY KEY (id)
);
CREATE SEQUENCE comics_seq;
테이블을 생성하고 데이터를 추가하기 위한 SQL 스크립트는 이곳에 서 확인하실 수 있습니다. 예제와 동일하게 애플리케이션을 구성하기 위해서라도 이 스크립트를 이용하는 것을 권장 드립니다. 가장 간단한 방법은 아래와 같이 SQL*Plus를 실행하는 것입니다. (여기에서는 오라클 데이터베이스가 이미 설치되어 있고, 여러분이 그 사용 방법을 숙지하고 있음을 가정합니다.)
SQL*Plus를 이용하여 아래와 같이 DBA 권한을 가진 사용자를 생성합니다.
SQL&gt; GRANT dba TO ruby IDENTIFIED BY ruby;
SQL&gt; ALTER USER ruby DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp;
SQL&gt; EXIT
SQL 파일을 사용하여 COMICS 애플리케이션 테이블을 생성하고 샘플 데이터를 일부 입력합니다.
C:\&gt; sqlplus ruby/ruby@rails @comics.sql
이 미 눈치채셨겠지만, COMICS 테이블의 이름은 복수형으로 명명되었습니다. 일반적으로 테이블이 단수형의 이름(예: COMIC)을 갖는 것을 감안한다면 이러한 표기법은 문제가 될 소지가 있습니다. 하지만 Rails는 복수형의 테이블 이름을 사용하는 접근법을 취합니다. Rails 설정에서 옵션의 변경이 가능하긴 하지만, 그 보다는 그냥 복수형의 이름을 사용하는 것이 좀 더 간단합니다.
2 단계: Ruby, RubyGems, Rails, Rails Oracle 라이브러리의 설치
Windows XP 환경에서 Rails를 사용하기 위해 반드시 설치해 주어야 하는 소프트웨어가 RubyGems 설치 패키지와 Rails 1.0(최근 1.1이 발표되었지만 본 문서에서는 1.0 버전을 기준으로 합니다), 그리고 Rails Oracle 데이터베이스 라이브러리입니다. Gems 패키지 인스톨러와 함께 Ruby를 다운로드하고 설치하려면, 아래와 같이 작업합니다.
  1. http://rubyinstaller.rubyforge.org/에 접속합니다.
  2. “One-Click Ruby Installer”를 다운로드합니다.
  3. 설치 방법을 참조합니다.
Ruby 프로그래밍 플랫폼의 설치가 완료된 후에는 RubyGems를 사용할 수 있습니다. RubyGems는 Ruby 프레임워크를 매우 쉽게 설치할 수 있게 하는 Ruby 애플리케이션입니다. Ruby 애플리케이션 개발 프레임워크를 설치하기 위해서, 커맨드라인 프롬프트를 열고 아래와 같이 명령을 실행합니다.
C:\&gt; gems install rails -v 1.0.0 --remote
이 제 Ruby, RubyGems, Rails가 설치되었습니다. 다음으로 Rail 애플리케이션과 오라클 데이터베이스 서버의 연동을 위한 코드 라이브러리를 설치할 차례입니다. Oracle Rails 라이브러리를 다운로드/설치하려면 http://rubyforge.org/projects/ruby-oci8에 접속한 후, C 드라이브에 ruby-oci8-0.1.13-mswin.r을 다운로드하고, 커맨드 창에서 아래와 같이 명령을 실행합니다.
C:\&gt; ruby ruby-oci8-0.1.13-mswin.rb
모든 작업이 순조롭게 진행되었다면, 이제 Ruby, Rails, Rails-Oracle 연결을 위한 라이브러리의 설치가 완료되었을 것입니다. 이제 Ruby on Rails 웹 애플리케이션을 처음으로 생성할 준비를 마쳤습니다.
3 단계: 웹 애플리케이션의 생성
새로운 Rails 애플리케이션을 생성하기 전에, 먼저 새로운 Rails 프로젝트를 아래와 같이 생성합니다.
Rails 커맨드라인 애플리케이션을 이용하여 새로운 프로젝트를 생성합니다 (새로운 디렉토리는 자동으로 생성됩니다).
C:\&gt; rails comics_catalog
위에서 생성된 디렉토리로 이동합니다.
C:\&gt; cd comics_catalog
C:\comics_catalog&gt;
이제 새로운 Rails 프로젝트 디렉토리가 생성되었습니다. 다음으로 Rails 애플리케이션이 Rails-Oracle 커넥션 라이브러리를 사용하도록 설정해 줄 차례입니다.
프로젝트 디렉토리 내의 config 디렉토리에는 database.yml이라는 이름의 파일이 존재합니다. 텍스트 편집기를 이용하여 database.yml을 수정합니다. 수정 이전의 상태는 아래와 같습니다:
development:
  adapter: mysql
  database: rails_development
  host: localhost
  username: root
  password: 

# Warning: The database defined as 'test' will be erased and
# re-generated from your development database when you run 'rake'.
# Do not set this db to the same as development or production.
test:
  adapter: mysql
  database: rails_test
  host: localhost
  username: root
  password:

production:
  adapter: mysql
  database: rails_production
  host: localhost
  username: root
  password:
데이터베이스의 종류에 따라 다른 연결 속성이 설정되어야 합니다. Rails는 디폴트 상태에서 MySQL과 연동하도록 설정되어 있으므로, Oracle을 사용하도록 설정을 변경해야 합니다. development 속성을 아래와 같이 변경하도록 합니다 (test, production 속성 역시 변경 가능하지만, 본 문서에서는 여기까지 언급하지 않는 것으로 합니다.)
development:
  adapter: oci
  username: ruby
  password: ruby
  host: RAILS 
Rails에서 웹 애플리케이션을 생성하는 방법에는 여러 가지가 있지만, 가장 간단한 것은 Rails 1.0.0에서 추가된 커맨드라인 기능을 이용하는 것입니다. 아래와 같이 하나의 커맨드 만으로 전체 애플리케이션을 생성할 수 있습니다.
C:\comics_catalog&gt; ruby script/generate scaffold Comic 
이 제 어떻게 되었을까요? Rails의 코드 생성기는 COMICS 테이블에 접근하기 위한 모델, 뷰, 컨트롤러 Ruby 코드를 생성하였습니다. 이 경우 애플리케이션 생성에 관련한 모든 작업은 Rails scaffold 명령을 통해 자동으로 수행되었습니다. 데이터베이스 테이블에 변경 사항이 발생한 경우에는 scaffold 명령을 다시 한 번 실행해 주어야 합니다 (그렇지 않은 경우 애플리케이션이 정상적으로 동작하지 않을 수도 있습니다.
이제 웹 애플리케이션이 생성되었으므로, Ruby 웹 서버 WEBRick을 시작합니다.
C:\comics_catalog&gt; ruby script/server
웹 서버를 재시작하지 않고도 애플리케이션의 Ruby 코드 또는 COMICS 테이블을 언제든 변경할 수 있습니다. 하지만 데이터베이스 설정 파일(예: database.yml)을 변경한 경우에는 서버를 재시작해야 합니다.
이제 여러분이 즐겨 사용하는 웹 브라우저를 통해 Rails Comic Catalog 애플리케이션에 액세스할 수 있습니다. 아래 URL로 접속합니다.
http://localhost:3000/comics/list
그림 1과 같이 카탈로그에 포함된 만화책 리스트가 표시될 것입니다.

그림 1: 제품 카탈로그 리스트
scaffold 커맨드를 사용하여 Rails Web 애플리케이션을 생성하는 과정에서, 타겟 데이터베이스의 레코드 목록을 조회하고 테이블의 레코드를 삽입, 수정, 삭제하기 위한 세 가지 웹 컴포넌트가 자동으로 생성됩니다. 그림 1은 튜토리얼의 시작 부분에서 SQL 스크립트를 실행하는 과정에서 데이터베이스에 삽입된 샘플 데이터의 목록을 보여주고 있습니다.
Listing 뷰와 별도로 Details 뷰가 존재합니다. 각 레코드 옆의 “Show” 링크를 클릭하면 해당 레코드에 대한 자세한 데이터가 출력됩니다. 그림 2는 Details 페이지의 예를 보여주고 있습니다.

그림 2: Details 페이지
데 이터베이스 테이블에서 임의의 레코드를 편집할 수도 있습니다. “Back” 링크를 클릭하거나 브라우저의 “뒤로” 버튼을 클릭하여 Listing 페이지로 돌아온 후 임의의 “Edit” 링크를 클릭합니다. 그림 3은 COMICS 데이터베이스 테이블의 특정 레코드에 대한 Editing 뷰의 예를 보여 주고 있습니다.

그림 3: Editing 뷰
또는 Listing 뷰로 돌아가 새로운 “New Comic” 링크를 클릭하고 COMICS 테이블에 새로운 레코드를 추가할 수도 있습니다. 이와 같이 하여 그림 3과 매우 유사한 Insertion 뷰로 이동할 수 있습니다.
Rails 마스터하기
지 금까지 Product Catalog 예제를 통해 Rails를 이용하여 간단한 애플리케이션을 생성하는 방법을 예시하였습니다. 이 애플리케이션은 인벤토리 추적 이외에는 별다른 기능이 포함되어 있지 않습니다. Rails를 이용하여 훨씬 더 복잡한 웹 애플리케이션을 개발할 수도 있지만, 이를 위해서는 좀더 세부적인 코딩이 필요합니다. Rails는 매우 다루기 쉬운 프레임워크이지만, 다른 테크놀로지와 마찬가지로 마스터하기까지 어느 정도의 시간이 요구됩니다. 현 시점에서 필자는 신기술에 대한 관심이 높은 개발자 또는 신규 애플리케이션 개발 작업을 시작하는 개발 팀에 Rails를 추천합니다. 이 두 가지에 해당되지 않는다면, Rails에 관련한 툴이 충분히 성숙할 때까지 Rails를 사용하지 않는 쪽을 권장하겠습니다.
Rails 은 제대로 마스터하려면 전문서를 참고해야 합니다. 올해 들어 Rails를 주제로 한 여러 권의 책이 출판되었지만 그 중에서도 내용이 특히 좋은 책으로 David Heninmier Hanson과 Dave Thomas가 공동 집필한 &lt;Agile Web Programming with Ruby on Rails (Pragmatic Bookshelf, 2005)&gt;를 추천합니다. Hanson은 Rails를 최초로 개발한 당사자이며, Thomas는 &lt;Programming Ruby: The Pragmatic Programmers' Guide (Pragmatic Bookshelf; 2nd edition, 2004)&gt;의 저자이기도 합니다.

[Ruby] 루비로 웹 서비스 만들기

Rails 설치하기
gem install rails --include-dependencies

Demo라는 웹 어플리케이션을 생성해보겠습니다.
rails Demo


http://localhost:3000/test 로 맵핑될 페이지 생성
ruby Demo\script\generate controller test index
결과로 Demo\app\controllers\test_controller.rb 과
Demo\app\views\main\index.rhtml 파일이 생성된다.

페이지 구성은 index.rhtml에서 쿼리를 입력하고
작성된 쿼리는 rcv.rhtml로 POST할 계획이다.

그러기 위해 해야할 일은 test_controller.rb파일에
rcv(페이지명과 동일한) 메소드를 생성하고 넘어온 쿼리를
처리하게 하고, 처리된 결과를 보여줄 페이지인 rcv.rhtml 파일을
Demo\app\views\main 폴더에 생성한다.
직접 작성한 test_controller.rb와 index.rhtml, rcv.rhtml 파일의
내용은 다음과 같다.

** test_controller.rb **
class TestController < ApplicationController
  def index
  end
  def rcv
   @txt = params[:txt]
   @pw = params[:pw]
  end
end

** index.rhtml **
<h1>Throw values</h1>
<form method=post action="/test/rcv">
<table border=1>
 <tr>
  <td>Text type value</td>
  <td><input type=text name=txt></td>
  </tr><tr>
  <td>Password type value</td>
  <td><input type=password name=pw></td>
 </tr>
 <tr>
  <td colspan=2>
   <input type=submit value=SUBMIT />
  </td>
 </tr>
</table>
</form>


** rcv.rhtml **
<h1>Catch values</h1>
<table border=1>
 <tr>
  <td>Text type value</td>
  <td><%= @txt %></td>
  </tr><tr>
  <td>Password type value</td>
  <td><%= @pw %></td>
 </tr>
</table>


모두 끝나면 서버를 작동하면 된다.
ruby Demo\script\server



참고사이트  http://wiki.rubyonrails.org/rails/pages/Tutorial

2016년 5월 25일 수요일

[HTML] HTML Meta Tag 속성

meta 태그에는 name, content, http-equiv 3가지 속성이 있다.

<meta name="Subject" content=""> //홈페이지 주제
<meta name="Title" content=""> //제목
<meta name="Keywords" content=""> //키워드
<meta name="Description" content=""> //요약설명
<meta name="Author" content=""> //제작자
<meta name="Publisher" content=""> //제작사
<meta name="Other Agent" content=""> //웹책임자
<meta name="Claasification" content=""> //카테고리위치,분류
<meta name="Generator" content=""> //제작도구
<meta name="Reply-To" content=""> //메일주소
<meta name="Email" content=""> //메일주소
<meta name="Filename" content=""> //파일이름
<meta name="Author-Date" content=""> //제작일
<meta name="Date" content=""> //제작일
<meta name="Location" content=""> //위치
<meta name="Distribution" content=""> //배포자
<meta name="Copyright" content=""> //저작권
<meta name="Robots" content="ALL">
<meta name="Robots" content="index,follow"> //이 문서도 긁어가고 링크된 문서도 긁어감
<meta name="Robots" content="noindex,follow"> //이 문서는 긁어가지 말고 링크된 문서만 긁어감
<meta name="Robots" content="index,nofollow"> //이 문서는 긁어가고 링크는 무시함
<meta name="Robots" content="noindex,nofollow"> //이 문서도 긁지 않고 링크도 무시함


<meta http-equiv="Content-Type" content="text/html; charset=euc-kr"> //웹문서 언어 설정
<meta http-equiv="Imagetoolbar" content="no"> //그림위에 마우스 오버시 이미지 관련 툴바 숨김
<meta http-equiv="Refresh" content="60"> //60초 마다 새로고침
<meta http-equiv="Refresh" ccontent="5;url=주소"gt; //주소로 5초후 이동
<meta http-equiv="Cash-Control" content="no-cache"> //캐쉬가 되지 않게
<meta http-equiv="Last-Modified" content="Mon,20 Jul 2008 19:30:30"> //최종 수정일
<meta http-equiv="Pragma" content="no-cache"> //캐쉬가 되지 않게
<meta http-equiv="Expires" content="Mon, 08 Sep 2003 10:10:10 GMT">"> //캐쉬 만료(파기)일


<meta http-equiv="Page-Enter" content="revealtrans(Duration=1,Transition=12)">

//페이지 들어갈때 트랜지션 효과(장면 전환 효과)
<meta http-equiv="Page-Exit" content="revealtrans(Duration=1,Transition=12)">

//페이지 나갈때 트랜지션 효과(장면 전환 효과)

장면 전환 효과 속성값
Box out : 네모난 박스가 안쪽에서 바깥쪽으로
Circle in : 원이 바깥에서 안쪽으로
Circle out : 원이 안쪽에서 바깥쪽으로
Wipe up : 이미지의 아래에서 위쪽으로 수직 이동
Wipe down : 이미지의 위에서 아래쪽으로 수직 이동
Wipe right : 이미지의 왼쪽에서 오른쪽으로 수평 이동
Wipe left : 이미지의 오른쪽에서 왼쪽으로 수평 이동
Vertical blinds : 수직 블라인드가 쳐지는 형태로 변환
Horizontal blinds : 수평 블라인드가 쳐지는 형태로 변환
Checkerboard across : 바둑판 형태의 격자가 왼쪽에서 오른쪽으로 생성
Checkerboard down : 바둑판 형태의 격자가 위에서 아래로 생성
Random dissove : 안개와 비슷한 형태로 변환
Split vertical in : 왼쪽과 오른쪽 끝에서 중앙으로 수직 이동
Split vertical out : 중앙에서 양쪽 끝으로 수직 이동
Split Horizontal in : 양쪽에서 중앙으로 수평 이동
Split Horizontal out : 중앙에서 양쪽끝으로 수직 이동
Strips left down : 대각선 형태로 오른쪽 상단에서 왼쪽 하단으로 이동
Strips left up : 대각선 형태로 오른쪽 하단에서 왼쪽 상단으로 이동
Strips right down : 대각선 형태로 왼쪽 상단에서 오른쪽 하단으로 이동
Strips right up : 대각선 형태로 왼쪽 하단에서 오른쪽 상단으로 이동
Random bars horizontal : 수평선이 무작위로 생성
Random bars vertical : 수직선이 무작위로 생성
Random : 임의로 생성

[R] About R

Install R for Ubuntu

# sudo apt-get update
# sudo apt-get install r-base
(Installed location: /usr/share/R)

 

Install RStudio

http://www.rstudio.com 에서 해당 OS에 맞는 제품을 설치

 

Update packages for R

# sudo R
> update.packages(ask=FALSE)
# sudo apt-get install libcurl4-openssl-dev

 

References

http://livesoncoffee.wordpress.com/2012/12/09/installing-r-on-ubuntu-12-04/

2014년 11월 6일 목요일

[APEX] Installation Oracle Application Express 4.2 using Embeded PLSQL Gateway

Download and Install Oracle Application Express
http://www.oracle.com/technetwork/developer-tools/apex/downloads/index.html
> unzip apex_4.2.zip> sqlplus "/as sysdba"SQL> @apexins.sql  SYSAUX SYSAUX TEMP /i/    (Full: @apexins.sql tablespace_apex tablespace_files tablespace_temp images)SQL> @apxrtins.sql SYSAUX SYSAUX TEMP /i/    (Runtime: @apxrtins.sql tablespace_apex tablespace_files tablespace_temp images)

Change the Password for the ADMIN Account
SQL> @apxchpwd.sql

Configure the Embeded PL/SQL Gateway
SQL> @apex_epg_config.sql c:\Oracle\app\oracle\product\11.2.0\server
SQL> ALTER USER ANONYMOUS ACCOUNT UNLOCK;

Verifying the Oracle XML DB Protocol Server Port
SQL> SELECT DBMS_XDB.GETHTTPPORT FROM DUAL;
=> 8080
  
Enabling Oracle XML DB Protocol Server
SQL> EXEC DBMS_XDB.SETHTTPPORT(8080);
  
Enable Network Services in Oracle Database 11g

DECLARE
  ACL_PATH  VARCHAR2(4000);
BEGIN
  -- Look for the ACL currently assigned to '*' and give APEX_040200
  -- the "connect" privilege if APEX_040200 does not have the privilege yet.

  SELECT ACL INTO ACL_PATH FROM DBA_NETWORK_ACLS
   WHERE HOST = '*' AND LOWER_PORT IS NULL AND UPPER_PORT IS NULL;

  IF DBMS_NETWORK_ACL_ADMIN.CHECK_PRIVILEGE(ACL_PATH, 'APEX_040200', 'connect') IS NULL THEN
      DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(ACL_PATH, 'APEX_040200', TRUE, 'connect');
  END IF;

EXCEPTION
  -- When no ACL has been assigned to '*'.
  WHEN NO_DATA_FOUND THEN
  DBMS_NETWORK_ACL_ADMIN.CREATE_ACL('power_users.xml', 'ACL that lets power users to connect to everywhere', 'APEX_040200', TRUE, 'connect');
  DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL('power_users.xml','*');
END;
/
COMMIT;


DECLARE
  ACL_PATH  VARCHAR2(4000);
BEGIN
  -- Look for the ACL currently assigned to 'localhost' and give APEX_040200
  -- the "connect" privilege if APEX_040200 does not have the privilege yet.
  SELECT ACL INTO ACL_PATH FROM DBA_NETWORK_ACLS
   WHERE HOST = 'localhost' AND LOWER_PORT IS NULL AND UPPER_PORT IS NULL;
   
  IF DBMS_NETWORK_ACL_ADMIN.CHECK_PRIVILEGE(ACL_PATH, 'APEX_040200', 'connect') IS NULL THEN
      DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(ACL_PATH, 'APEX_040200', TRUE, 'connect');
  END IF;

EXCEPTION
  -- When no ACL has been assigned to 'localhost'.
  WHEN NO_DATA_FOUND THEN
  DBMS_NETWORK_ACL_ADMIN.CREATE_ACL('local-access-users.xml', 'ACL that lets users to connect to localhost', 'APEX_040200', TRUE, 'connect');
  DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL('local-access-users.xml','localhost');
END;
/
COMMIT;
  
Installing a Translated Version of Oracle Application Express
> set NLS_LANG=American_America.AL32UTF8
> sqlplus "/as sysdba"SQL> @load_trans.sql ko
or
> set NLS_LANG=American_America.AL32UTF8> sqlplus "/as sysdba"SQL> alter session set current_schema = APEX_040200;SQL> @builder/ko/load_ko.sql

Configuring the SHARED_SERVERS Parameter
SQL> ALTER SYSTEM SET SHARED_SERVERS = 5 SCOPE=BOTH;
  
Connect to APEX
http://localhost:8080/apexhttp://localhost:8080/apex/apex_admin



References