<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3708407902829149391</id><updated>2012-02-02T05:14:17.918-08:00</updated><category term='http_proxy'/><category term='RubyOCI8V2'/><category term='cucumber'/><category term='Metadata'/><category term='OracleArrayDML'/><category term='ruby-oci8-gem'/><category term='ObjectType'/><category term='git'/><category term='BDD'/><category term='ruby-oci8'/><category term='transconnect'/><category term='rails'/><title type='text'>Liming's Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://limlian.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://limlian.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Liming Lian</name><uri>http://www.blogger.com/profile/03877330950571137973</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>6</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3708407902829149391.post-4037345359705379906</id><published>2008-10-18T20:17:00.000-07:00</published><updated>2008-10-20T19:05:47.037-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='BDD'/><category scheme='http://www.blogger.com/atom/ns#' term='cucumber'/><title type='text'>Behaivour-driven development using plain Chinese story</title><content type='html'>This blog post is talking about how to use rspec and cucumber in Ruby to make behavior driven development with plain story in Chinese language.&lt;br /&gt;&lt;br /&gt;It seems behaviour-driven development is getting more and more popular in recent days. If you are still not sure what BDD is, take a look at following links:&lt;br /&gt;&lt;br /&gt;1] &lt;a href="http://dannorth.net/introducing-bdd/"&gt;Introducing BDD&lt;/a&gt; by Dan North&lt;br /&gt;2] &lt;a href="http://www.youtube.com/watch?v=XOkHh8zF33o"&gt;Beyond Test Driven Development: Behaviour Driven Development&lt;/a&gt;, Google Talk, by Dave Astels&lt;br /&gt;3] &lt;a href="http://rubyconf2007.confreaks.com/d3t1p2_rspec.html"&gt;Behaviour Driven Development with RSpec&lt;/a&gt;, RubyConf 2007, by &lt;span class="caption"&gt;David Chelimsky, Dave Astels&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The most interesting feature of BDD is using stories of plain text as the test cases. Here the story text itself is not only the description of the application's functionality, but also the executable acceptance criterion of application's behavior. Let's have a look at the story example of a calculator addition feature:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Feature: Addition&lt;br /&gt; In order to avoid silly mistakes&lt;br /&gt; As a math idiot&lt;br /&gt; I want to be told the sum of two numbers&lt;br /&gt;&lt;br /&gt;Scenario: Add two numbers&lt;br /&gt; Given I have entered 50 into the calculator&lt;br /&gt; And I have entered 70 into the calculator&lt;br /&gt; When I press add&lt;br /&gt; Then the result should be 120 on the screen&lt;br /&gt; And the result class should be Fixnum&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Both developers and customers can benefit from above story since it is in plain text and easily understood. The further question you might ask is that if it is possible to use spoken languages other than English to write our BDD stories? The answer is "definitely yes!". Thanks to the cucumber -- the new RSpec's Story Runner. Multiple spoken languages support is a built-in feature of cucumber.&lt;br /&gt;&lt;br /&gt;The first step is to install cucumber, make sure you have install rpsec. You can install cucumber from gem:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;gem install cucumber&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;or building gem yourself:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;git clone git://github.com/aslakhellesoy/cucumber.git&lt;br /&gt;cd cucumber&lt;br /&gt;rake install_gem&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The keyword translation for Chinese language in cucumber is defined as following:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;"zh-CN":&lt;br /&gt;   feature: 功能&lt;br /&gt;   scenario: 场景&lt;br /&gt;   given_scenario: 引用场景&lt;br /&gt;   given: 假如&lt;br /&gt;   when: 当&lt;br /&gt;   then: 那么&lt;br /&gt;   and: 而且&lt;br /&gt;   but: 但是&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;OK, let's write our story in Chinese:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;功能:加法&lt;br /&gt; 为了避免一些愚蠢的错误&lt;br /&gt; 作为一个数学白痴&lt;br /&gt; 我希望有人告诉我数字相加的结果&lt;br /&gt;&lt;br /&gt;场景: 两个数相加&lt;br /&gt; 假如我已经在计算器里输入6&lt;br /&gt; 而且我已经在计算器里输入7&lt;br /&gt; 当我按相加按钮&lt;br /&gt; 那么我应该在屏幕上看到的结果是13&lt;br /&gt;&lt;br /&gt;场景: 三个数相加&lt;br /&gt; 假如我已经在计算器里输入6&lt;br /&gt; 而且我已经在计算器里输入7&lt;br /&gt; 而且我已经在计算器里输入1&lt;br /&gt; 当我按相加按钮&lt;br /&gt; 那么我应该在屏幕上看到的结果是14&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;Save the plain text in Chinese to a file, here we give it name "addition.feature".  Now we can run this feature in command line:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&gt; cucumber --language zh-CN addition.feature&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;You should see following output:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;功能:加法  # addition.feature&lt;br /&gt; 为了避免一些愚蠢的错误&lt;br /&gt; 作为一个数学白痴&lt;br /&gt; 我希望有人告诉我数字相加的结果&lt;br /&gt;&lt;br /&gt;场景: 两个数相加                             # addition.feature:6&lt;br /&gt; 假如 我已经在计算器里输入6            # addition.feature:7&lt;br /&gt; 而且 我已经在计算器里输入7            # addition.feature:8&lt;br /&gt; 当 我按相加按钮                            # addition.feature:9&lt;br /&gt; 那么 我应该在屏幕上看到的结果是13  # addition.feature:10&lt;br /&gt;&lt;br /&gt;场景: 三个数相加                             # addition.feature:12&lt;br /&gt; 假如 我已经在计算器里输入6            # addition.feature:13&lt;br /&gt; 而且 我已经在计算器里输入7            # addition.feature:14&lt;br /&gt; 而且 我已经在计算器里输入1            # addition.feature:15&lt;br /&gt; 当 我按相加按钮                            # addition.feature:16&lt;br /&gt; 那么 我应该在屏幕上看到的结果是14  # addition.feature:17&lt;br /&gt;&lt;br /&gt;9 steps pending&lt;br /&gt;&lt;br /&gt;You can use these snippets to implement pending steps:&lt;br /&gt;&lt;br /&gt;假如 /^我已经在计算器里输入6$/ do&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;假如 /^我已经在计算器里输入7$/ do&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;当 /^我按相加按钮$/ do&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;那么 /^我应该在屏幕上看到的结果是13$/ do&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;假如 /^我已经在计算器里输入1$/ do&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;那么 /^我应该在屏幕上看到的结果是14$/ do&lt;br /&gt;end&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;See pending step notification? Yes, that is because we haven't defined the steps for this feature. Before we define the steps, we might first consider writing our calculator code. Following is a simple implementation. Here we add a silly bug(The initial sum is not 0 but 1)  to let cucumber report it.&lt;br /&gt;&lt;div class="line" id="LC1"&gt;&lt;span class="k"&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;class &lt;span class="nc"&gt;Calculator&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;span class="k"&gt;  def&lt;/span&gt; &lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span class="vi"&gt;    @args&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;br /&gt;&lt;/span&gt;&lt;span class="vi"&gt;    @args&lt;/span&gt; &lt;span class="o"&gt;&lt;&lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;br /&gt;&lt;/span&gt;&lt;span class="k"&gt;  end&lt;br /&gt;&lt;/span&gt;&lt;span class="k"&gt;&lt;br /&gt; def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;br /&gt;&lt;/span&gt;&lt;span class="vi"&gt;    @args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;&lt;br /&gt; end&lt;br /&gt;&lt;/span&gt;end&lt;span class="k"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC6"&gt;  &lt;/div&gt;Save the code to a local file within the same directory of your feature file. Now let's define the step matcher for addition feature with Calculator class defined above.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;require 'spec'&lt;br /&gt;require 'calculator'&lt;br /&gt;&lt;br /&gt;Before do&lt;br /&gt; @calc = Calculator.new&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;After do&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;Given "我已经在计算器里输入$n" do |n|&lt;br /&gt; @calc.push n.to_i&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;When /我按(.*)按钮/ do |op|&lt;br /&gt; if op == '相加'&lt;br /&gt;   @result = @calc.send "add"&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;Then /我应该在屏幕上看到的结果是(.*)/ do |result|&lt;br /&gt; @result.should == result.to_f&lt;br /&gt;end&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;Now run the feature again, you should see:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;功能:加法  # addition.feature&lt;br /&gt; 为了避免一些愚蠢的错误&lt;br /&gt; 作为一个数学白痴&lt;br /&gt; 我希望有人告诉我数字相加的结果&lt;br /&gt;&lt;br /&gt; 场景: 两个数相加                             # addition.feature:6&lt;br /&gt;   假如 我已经在计算器里输入6            # calculator_steps.rb:11&lt;br /&gt;   而且 我已经在计算器里输入7            # calculator_steps.rb:11&lt;br /&gt;   当 我按相加按钮                            # calculator_steps.rb:15&lt;br /&gt;   那么 我应该在屏幕上看到的结果是13  # calculator_steps.rb:21&lt;br /&gt;expected: 13.0,&lt;br /&gt;   got: 14 (using ==) (Spec::Expectations::ExpectationNotMetError)&lt;br /&gt;./calculator_steps.rb:22:in `那么 /461021457224505745453450456117457125447012473413451060473204477323463634463057(.*)/'&lt;br /&gt;addition.feature:10:in `那么 我应该在屏幕上看到的结果是13'&lt;br /&gt;&lt;br /&gt; 场景: 三个数相加                             # addition.feature:12&lt;br /&gt;   假如 我已经在计算器里输入6            # calculator_steps.rb:11&lt;br /&gt;   而且 我已经在计算器里输入7            # calculator_steps.rb:11&lt;br /&gt;   而且 我已经在计算器里输入1            # calculator_steps.rb:11&lt;br /&gt;   当 我按相加按钮                            # calculator_steps.rb:15&lt;br /&gt;   那么 我应该在屏幕上看到的结果是14  # calculator_steps.rb:21&lt;br /&gt;expected: 14.0,&lt;br /&gt;  got: 15 (using ==) (Spec::Expectations::ExpectationNotMetError)&lt;br /&gt;./calculator_steps.rb:22:in `那么 /461021457224505745453450456117457125447012473413451060473204477323463634463057(.*)/'&lt;br /&gt;addition.feature:17:in `那么 我应该在屏幕上看到的结果是14'&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;Lets change the calculator class to fix the bug:&lt;br /&gt;&lt;span class="k"&gt;&lt;pre&gt;&lt;code&gt;class &lt;span class="nc"&gt;Calculator&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;span class="k"&gt;   def&lt;/span&gt; &lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span class="vi"&gt;     @args&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;br /&gt;&lt;/span&gt;&lt;span class="vi"&gt;     @args&lt;/span&gt; &lt;span class="o"&gt;&lt;&lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;br /&gt;&lt;/span&gt;&lt;span class="k"&gt;   end&lt;br /&gt;&lt;/span&gt;&lt;span class="k"&gt;&lt;br /&gt;  def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;br /&gt;&lt;/span&gt;&lt;span class="vi"&gt;     @args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;&lt;br /&gt;  end&lt;br /&gt;&lt;/span&gt;end&lt;span class="k"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;div class="line" id="LC6"&gt;  And run cucumber again, you should see:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;功能:加法  # addition.feature&lt;br /&gt; 为了避免一些愚蠢的错误&lt;br /&gt; 作为一个数学白痴&lt;br /&gt; 我希望有人告诉我数字相加的结果&lt;br /&gt;&lt;br /&gt;场景: 两个数相加                             # addition.feature:6&lt;br /&gt; 假如 我已经在计算器里输入6            # calculator_steps.rb:11&lt;br /&gt; 而且 我已经在计算器里输入7            # calculator_steps.rb:11&lt;br /&gt; 当 我按相加按钮                            # calculator_steps.rb:15&lt;br /&gt; 那么 我应该在屏幕上看到的结果是13  # calculator_steps.rb:21&lt;br /&gt;&lt;br /&gt;场景: 三个数相加                             # addition.feature:12&lt;br /&gt; 假如 我已经在计算器里输入6            # calculator_steps.rb:11&lt;br /&gt; 而且 我已经在计算器里输入7            # calculator_steps.rb:11&lt;br /&gt; 而且 我已经在计算器里输入1            # calculator_steps.rb:11&lt;br /&gt; 当 我按相加按钮                            # calculator_steps.rb:15&lt;br /&gt; 那么 我应该在屏幕上看到的结果是14  # calculator_steps.rb:21&lt;br /&gt;&lt;br /&gt;9 steps passed&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Congratulations! All steps passed!&lt;br /&gt;&lt;br /&gt;You can find the code of this example at /examples/chinese_simplified_calculator of cucumber git repository(git://github.com/aslakhellesoy/cucumber.git).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3708407902829149391-4037345359705379906?l=limlian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://limlian.blogspot.com/feeds/4037345359705379906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3708407902829149391&amp;postID=4037345359705379906' title='35 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default/4037345359705379906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default/4037345359705379906'/><link rel='alternate' type='text/html' href='http://limlian.blogspot.com/2008/10/behaivour-driven-development-using.html' title='Behaivour-driven development using plain Chinese story'/><author><name>Liming Lian</name><uri>http://www.blogger.com/profile/03877330950571137973</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>35</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3708407902829149391.post-4480737789470006580</id><published>2008-08-26T23:17:00.000-07:00</published><updated>2008-08-27T00:05:22.482-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='transconnect'/><category scheme='http://www.blogger.com/atom/ns#' term='http_proxy'/><title type='text'>Use http proxy for git client</title><content type='html'>I am using a network behind a http proxy. As more and more &lt;a href="http://rubyonrails.org" target="_blank"&gt;Rails&lt;/a&gt; projects migrate to Git,  for accessing those external Git repositories, I'd like to have a method to configure Git client to go through the http proxy. By searching the web, I found several solutions. After some trying, I found the easiest approach is to use &lt;a href="http://sourceforge.net/projects/transconnect" target="_blank"&gt;transconnect&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I am using Ubuntu and find that there is no package support for transconnect. So I have to install it manually from the source code, fortunately, it is fairly easy to setup transconnect. Following is the steps:&lt;br /&gt;&lt;br /&gt;1) Download transconnect source code from &lt;a href="http://sourceforge.net/projects/transconnect" target="_blank"&gt;its website&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;2) Uncompress the .tar.gz package, to install it, simply type:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;make&lt;br /&gt;make install&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The above is the standard installation, for others, please refer to INSTALL located within the uncompressed directory.&lt;br /&gt;&lt;br /&gt;3)  A new directory '.tconn' will be created under your HOME directory by the installer and a config file 'tconn.conf' will be copied to that directory.  Open 'tconn.conf', you will find two options named 'proxyserv' and 'proxyport'. Replace the default value with the proxy you are in use.&lt;br /&gt;&lt;br /&gt;And that's all for setting!&lt;br /&gt;&lt;br /&gt;4) It is easy to start transconnect by exporting an environment variable:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;LD_PRELOAD=$HOME/.tconn/tconn.so&lt;br /&gt;export LD_PRELOAD&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;After that, try your git client, it should work on current terminal by going through the proxy you have set.&lt;br /&gt;&lt;br /&gt;5) It is also easy to stop transconnect. In the terminal you have exported LD_RELOAD, simply unset it.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;unset LD_PRELOAD&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Yes, that's all, enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3708407902829149391-4480737789470006580?l=limlian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://limlian.blogspot.com/feeds/4480737789470006580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3708407902829149391&amp;postID=4480737789470006580' title='60 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default/4480737789470006580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default/4480737789470006580'/><link rel='alternate' type='text/html' href='http://limlian.blogspot.com/2008/08/use-http-proxy-for-git-client.html' title='Use http proxy for git client'/><author><name>Liming Lian</name><uri>http://www.blogger.com/profile/03877330950571137973</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>60</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3708407902829149391.post-3300303689493265782</id><published>2008-07-03T00:20:00.001-07:00</published><updated>2008-07-03T00:22:48.365-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby-oci8'/><category scheme='http://www.blogger.com/atom/ns#' term='ruby-oci8-gem'/><title type='text'>Ruby-OCI8 1.0.2 gem is available</title><content type='html'>As &lt;a href="http://groups.google.com/group/comp.lang.ruby/msg/c7bc02eb2dc0784f"&gt;Kubo announced in Ruby mailing list&lt;/a&gt;, with the release of version 1.0.2, the gem of Ruby-OCI8 is available.&amp;nbsp; Now you can easily install ruby-oci8 by simple commd "gem install ruby-oci8". &lt;br /&gt;&lt;br /&gt;Though the installation of Ruby-OCI8 has been eased a lot with gem, you still have to pay attention to:&lt;br /&gt;&lt;br /&gt;1) The same as installation from source code,&amp;nbsp; Oracle client is still required to be installed before the gem installation. Check help page "&lt;a href="http://ruby-oci8.rubyforge.org/en/InstallForFullClient.html"&gt;Oracle Full Client&lt;/a&gt;" and "&lt;a href="http://ruby-oci8.rubyforge.org/en/InstallForInstantClient.html"&gt;Oracle Instant Client&lt;/a&gt;" on ruby-oci8 website for details, please be specially careful to the setting of environment variable "LD_LIBRARY_PATH".&lt;br /&gt;&lt;br /&gt;2) If you don't tell the ruby to load RubyGems every time it starts up by setting the environment variable "RUBYOPT" to "rubygems", you should add "require 'rubygems'" before "require 'oci8'", or you will get error "no such file to load -- oci8".&lt;br /&gt;&lt;br /&gt;Now the Ruby-OCI8 gem is only available for version 1.0.2,&amp;nbsp; no support for 2.0 yet.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3708407902829149391-3300303689493265782?l=limlian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://limlian.blogspot.com/feeds/3300303689493265782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3708407902829149391&amp;postID=3300303689493265782' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default/3300303689493265782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default/3300303689493265782'/><link rel='alternate' type='text/html' href='http://limlian.blogspot.com/2008/07/ruby-oci8-102-gem-is-available.html' title='Ruby-OCI8 1.0.2 gem is available'/><author><name>Liming Lian</name><uri>http://www.blogger.com/profile/03877330950571137973</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3708407902829149391.post-6923481273096642917</id><published>2008-05-09T07:49:00.000-07:00</published><updated>2008-05-11T19:04:43.330-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby-oci8'/><category scheme='http://www.blogger.com/atom/ns#' term='Metadata'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOCI8V2'/><title type='text'>Ruby-OCI8 2.0 New Feature: Complete Schema Object Metadata Describe Support</title><content type='html'>&lt;span style="font-size:130%;"&gt;1, Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This feature enables you to perform an explicit describe of the following schema objects and their subschema objects via Ruby-OCI8:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;    tables and views&lt;/li&gt;&lt;li&gt;    synonyms&lt;/li&gt;&lt;li&gt;    procedures&lt;/li&gt;&lt;li&gt;    functions&lt;/li&gt;&lt;li&gt;    packages&lt;/li&gt;&lt;li&gt;    sequences&lt;/li&gt;&lt;li&gt;    collections&lt;/li&gt;&lt;li&gt;    types&lt;/li&gt;&lt;li&gt;    schemas&lt;/li&gt;&lt;li&gt;    databases&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Information about other schema elements (procedure/function arguments, columns, type attributes, and type methods) is available through a describe of one of the above schema objects or an explicit describe of the subschema object.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;2, Ruby-OCI8 2.0 Installation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;svn co http://ruby-oci8.rubyforge.org/svn/trunk/ruby-oci8&lt;br /&gt;&lt;br /&gt;And then follow the &lt;a href="http://ruby-oci8.rubyforge.org/en/HowToInstall.html" target="_blank"&gt;Ruby-OCI8 install instruction&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;3,Metadata Describe API&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;[General Purpose]&lt;br /&gt;This method can be used to describe any schema object.&lt;br /&gt;OCI8#describe_any(object_name)&lt;br /&gt;&lt;br /&gt;[table or view]                                                                                                                &lt;br /&gt;OCI8#describe_table(table_name, table_only = false)                                          &lt;br /&gt;Return:&lt;br /&gt;OCI8::Metadata::Table&lt;br /&gt;       &lt;br /&gt;[view]                                                                                                                        &lt;br /&gt;OCI8#describe_view(view_name)                                                                                           &lt;br /&gt;Return:&lt;br /&gt;OCI8::Metadata::View&lt;br /&gt;&lt;br /&gt;[procedure]                                                                                                                    &lt;br /&gt;OCI8#describe_procedure(procedure_name)                                                                                    &lt;br /&gt;Return:&lt;br /&gt;OCI8::Metadata::Procedure&lt;br /&gt;&lt;br /&gt;[function]                                                                                                                    &lt;br /&gt;OCI8#describe_function(function_name)                                                                                      &lt;br /&gt;Return:&lt;br /&gt;OCI8::Metadata::Function&lt;br /&gt;&lt;br /&gt;[package]                                                                                                                      &lt;br /&gt;OCI8#describe_package(package_name)                                                                                        &lt;br /&gt;Return:&lt;br /&gt;OCI8::Metadata::Package&lt;br /&gt;&lt;br /&gt;[type]                                                                                                                        &lt;br /&gt;OCI8#describe_type(type_name)                                                                                              &lt;br /&gt;Return:&lt;br /&gt;OCI8::Metadata::Type&lt;br /&gt;&lt;br /&gt;[synonym]                                                                                                                      &lt;br /&gt;OCI8#describe_synonym(synonym_name, check_public_also = false)                                                            &lt;br /&gt;Return:&lt;br /&gt;OCI8::Metadata::Synonym&lt;br /&gt;&lt;br /&gt;[sequence]                                                                                                                    &lt;br /&gt;OCI8#describe_sequence(sequence_name)                                                                                      &lt;br /&gt;Return:&lt;br /&gt;OCI8::Metadata::Sequence&lt;br /&gt;&lt;br /&gt;[schema]                                                                                                                      &lt;br /&gt;OCI8#describe_schema(schema_name)&lt;br /&gt;Return:&lt;br /&gt;OCI8::Metadata::Schema                                                                                      &lt;br /&gt;&lt;br /&gt;[database]                                                                                                                    &lt;br /&gt;OCI8#describe_database(database_name)&lt;br /&gt;Return:&lt;br /&gt;OCI8::Metadata::Database&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;4, Examples&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;4.1 Describe Table&lt;br /&gt;&lt;br /&gt;Table definition:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;CREATE TABLE employees_demo(&lt;br /&gt;  employee_id    NUMBER(6),&lt;br /&gt;  first_name     VARCHAR2(20),&lt;br /&gt;  last_name      VARCHAR2(25),&lt;br /&gt;  email          VARCHAR2(25)&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Describe via Ruby-OCI8&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;require 'oci8'&lt;br /&gt;conn = OCI8.new('ruby','oci8','localhost')&lt;br /&gt;emp_tab = conn.describe_table('employees_demo')&lt;br /&gt;puts "Table Name: #{emp_tab.obj_name}"&lt;br /&gt;emp_tab.columns.each do |col|&lt;br /&gt;  puts "  Column #{col.name}, type: #{col.data_type}, size: #{col.data_size}"&lt;br /&gt;end&lt;br /&gt;conn.logoff&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Output:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;Table Name: EMPLOYEES_DEMO&lt;br /&gt;  Column EMPLOYEE_ID, type: number, size: 22&lt;br /&gt;  Column FIRST_NAME, type: varchar2, size: 20&lt;br /&gt;  Column LAST_NAME, type: varchar2, size: 25&lt;br /&gt;  Column EMAIL, type: varchar2, size: 25&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;4.2 Describe Procedure&lt;br /&gt;&lt;br /&gt;Procedure definition:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;CREATE OR REPLACE PROCEDURE get_name(emp_id IN NUMBER, emp_name OUT VARCHAR2) AS&lt;br /&gt;  emp_fn VARCHAR2(20);&lt;br /&gt;  emp_ln VARCHAR2(25);&lt;br /&gt;BEGIN&lt;br /&gt;SELECT first_name, last_name INTO emp_fn, emp_ln&lt;br /&gt;  FROM employees_demo WHERE employee_id = emp_id;&lt;br /&gt;emp_name := emp_fn || ' ' ||  emp_ln;&lt;br /&gt;END;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Describe via Ruby-OCI8&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;require 'oci8'&lt;br /&gt;conn = OCI8.new('ruby','oci8','localhost')&lt;br /&gt;get_name_proc = conn.describe_procedure('get_name')&lt;br /&gt;puts "Procedure Name: #{get_name_proc.obj_name}"&lt;br /&gt;args = get_name_proc.arguments&lt;br /&gt;args.each { |arg|&lt;br /&gt;  puts "  Argument #{arg.name}, type: #{arg.data_type}, in/out: #{arg.iomode.to_s}"&lt;br /&gt;}&lt;br /&gt;conn.logoff&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Output:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;Procedure Name: GET_NAME&lt;br /&gt;  Argument EMP_ID, type: number, in/out: in&lt;br /&gt;  Argument EMP_NAME, type: varchar2, in/out: out&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;4.3 Describe Function&lt;br /&gt;&lt;br /&gt;Function definition:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;CREATE OR REPLACE FUNCTION get_email(emp_id NUMBER)&lt;br /&gt;RETURN VARCHAR2 AS&lt;br /&gt;  emp_email VARCHAR2(25);&lt;br /&gt;BEGIN&lt;br /&gt;  SELECT email INTO emp_email FROM employees_demo&lt;br /&gt;    WHERE employee_id = emp_id;&lt;br /&gt;  RETURN(emp_email);&lt;br /&gt;END;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Describe via Ruby-OCI8&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;get_email_func = conn.describe_function('get_email')&lt;br /&gt;puts "Function Name: #{get_email_func.obj_name}"&lt;br /&gt;args = get_email_func.arguments&lt;br /&gt;args.each_index { |i|&lt;br /&gt;if i == 0&lt;br /&gt;  puts "  Return Type: #{args[i].data_type}"&lt;br /&gt;else&lt;br /&gt;  puts "  Argument #{i}: #{args[i].name}, Type: #{args[i].data_type}"&lt;br /&gt;end                     &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Output:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;Function Name: GET_EMAIL&lt;br /&gt;  Return Type: varchar2&lt;br /&gt;  Argument 1: EMP_ID, Type: number&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;4.4 Describe Package&lt;br /&gt;&lt;br /&gt;Package Definition&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;CREATE OR REPLACE PACKAGE emp_pkg AS&lt;br /&gt;  FUNCTION get_email(emp_id NUMBER) RETURN VARCHAR2;&lt;br /&gt;  PROCEDURE get_name(emp_id IN NUMBER, emp_name OUT VARCHAR2);&lt;br /&gt;END emp_pkg;&lt;br /&gt;&lt;br /&gt;CREATE OR REPLACE PACKAGE BODY emp_pkg AS&lt;br /&gt;  FUNCTION get_email(emp_id NUMBER)&lt;br /&gt;  RETURN VARCHAR2 AS&lt;br /&gt;    emp_email VARCHAR2(25);&lt;br /&gt;  BEGIN&lt;br /&gt;    SELECT email INTO emp_email FROM employees_demo&lt;br /&gt;      WHERE employee_id = emp_id;&lt;br /&gt;    RETURN(emp_email);&lt;br /&gt;  END;&lt;br /&gt;&lt;br /&gt;  PROCEDURE get_name(emp_id IN NUMBER, emp_name OUT VARCHAR2) AS&lt;br /&gt;    emp_fn VARCHAR2(20);&lt;br /&gt;    emp_ln VARCHAR2(25);&lt;br /&gt;  BEGIN&lt;br /&gt;    SELECT first_name, last_name INTO emp_fn, emp_ln&lt;br /&gt;      FROM employees_demo WHERE employee_id = emp_id;&lt;br /&gt;    emp_name := emp_fn || ' ' ||  emp_ln;&lt;br /&gt;  END;&lt;br /&gt;END emp_pkg;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Describe via Ruby-OCI8&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;require 'oci8'&lt;br /&gt;conn = OCI8.new('ruby','oci8','localhost')&lt;br /&gt;emp_pkg = conn.describe_package('emp_pkg')&lt;br /&gt;puts "Package Name: #{emp_pkg.obj_name}"&lt;br /&gt;sub_progs = emp_pkg.subprograms&lt;br /&gt;sub_progs.each { |subp|&lt;br /&gt;  if subp.is_a? OCI8::Metadata::Function&lt;br /&gt;    puts "Subprogram:  Function #{subp.name}"&lt;br /&gt;    args = subp.arguments&lt;br /&gt;    args.each_index { |i|&lt;br /&gt;      if i == 0&lt;br /&gt;        puts "  Return Type: #{args[i].data_type}"&lt;br /&gt;      else&lt;br /&gt;        puts "  Argument #{i}: #{args[i].name}, Type: #{args[i].data_type}"                       &lt;br /&gt;      end&lt;br /&gt;    }&lt;br /&gt;  elsif subp.is_a? OCI8::Metadata::Procedure&lt;br /&gt;    puts "Subprogram:  Procedure #{subp.name}"&lt;br /&gt;    args = subp.arguments&lt;br /&gt;    args.each { |arg|&lt;br /&gt;      puts "Argument #{arg.name}, type: #{arg.data_type}, in/out: #{arg.iomode.to_s}"&lt;br /&gt;    }&lt;br /&gt;  end&lt;br /&gt;}&lt;br /&gt;conn.logoff&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Result:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;Package Name: EMP_PKG&lt;br /&gt;Subprogram:  Function GET_EMAIL&lt;br /&gt;  Return Type: varchar2&lt;br /&gt;  Argument 1: EMP_ID, Type: number&lt;br /&gt;Subprogram:  Procedure GET_NAME&lt;br /&gt;  Argument EMP_ID, type: number, in/out: in&lt;br /&gt;  Argument EMP_NAME, type: varchar2, in/out: out&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;4.5 Describe Type&lt;br /&gt;&lt;br /&gt;Type definition:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;CREATE OR REPLACE TYPE person_t AS object&lt;br /&gt;  (name varchar2(30),&lt;br /&gt;  age number(3));&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Describe via Ruby-OCI8&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;require 'oci8'&lt;br /&gt;conn = OCI8.new('ruby','oci8','localhost')&lt;br /&gt;person_t = conn.describe_type('person_t')&lt;br /&gt;puts "Type Name: #{person_t.obj_name}"&lt;br /&gt;person_t.type_attrs.each { |attr|&lt;br /&gt;  puts "  Attribute #{attr.name}, type: #{attr.data_type}, size: #{attr.data_siz  e}"}&lt;br /&gt;conn.logoff&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;Result:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;Type Name: PERSON_T&lt;br /&gt;  Attribute NAME, type: varchar2, size: 30&lt;br /&gt;  Attribute AGE, type: number, size: 22&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;span style="font-size:130%;"&gt;5, Reference&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://download.oracle.com/docs/cd/B14117_01/appdev.101/b10779/oci06des.htm#446491" target="_blank"&gt;Describing Schema Metadata&lt;/a&gt; on &lt;a href="http://download.oracle.com/docs/cd/B14117_01/appdev.101/b10779/toc.htm" target="_blank"&gt;Oracle Call Interface Programmer's Guide&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3708407902829149391-6923481273096642917?l=limlian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://limlian.blogspot.com/feeds/6923481273096642917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3708407902829149391&amp;postID=6923481273096642917' title='98 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default/6923481273096642917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default/6923481273096642917'/><link rel='alternate' type='text/html' href='http://limlian.blogspot.com/2008/05/ruby-oci8-20-new-feature-complete.html' title='Ruby-OCI8 2.0 New Feature: Complete Schema Object Metadata Describe Support'/><author><name>Liming Lian</name><uri>http://www.blogger.com/profile/03877330950571137973</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>98</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3708407902829149391.post-5141491075427703209</id><published>2008-05-03T23:29:00.000-07:00</published><updated>2008-05-08T01:39:29.965-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby-oci8'/><category scheme='http://www.blogger.com/atom/ns#' term='OracleArrayDML'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOCI8V2'/><title type='text'>Ruby-OCI8 2.0 New Feature: Array DML Support</title><content type='html'>&lt;span style="font-size:130%;"&gt;1, Introduction To Array DML&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Oracle Call Interface provides an Array Interface. This array interface significantly reduces round trips to the database when you are updating or inserting a large volume of data. This reduction can lead to considerable performance gains in a busy client/server environment. For example, consider an application that needs to insert 100 rows into the database. Calling OCIStmtExecute() 100 times with single values results in 100 network round trips to insert all the data. The same result is possible with a single call to OCIStmtExecute() using an input array, which involves only one network round trip.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;2, Ruby-OCI8 v2.0 Installation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;svn co http://ruby-oci8.rubyforge.org/svn/trunk/ruby-oci8&lt;br /&gt;&lt;br /&gt;And then follow the &lt;a href="http://ruby-oci8.rubyforge.org/en/HowToInstall.html" target="_blank"&gt;Ruby-OCI8 install instruction&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;3, Usage&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Three new instance methods are added to class OCI8::Cursor for supporting array dml:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1) max_array_size = val&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Set the maximum array size for bind_param_array. This method should be called before bind_param_array.&lt;br /&gt;&lt;br /&gt;example:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;cursor = conn.parse("INSERT INTO test VALUES(:name, :age)")&lt;br /&gt;cursor.max_array_size = 3&lt;br /&gt;cursor.bind_param_array(:name, ['mike', 'john', 'danny'])&lt;br /&gt;cursor.bind_param_array (:age, [20, 21, 22])&lt;br /&gt;cursor.exec_array&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;When calling this method, all the binds will be clean from cursor if instance variable max_array_size of cursor is set before.&lt;br /&gt;&lt;br /&gt;example:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;cursor = conn.parse("INSERT INTO test VALUES(:name, :age)")&lt;br /&gt;cursor.max_array_size = 3&lt;br /&gt;cursor.bind_param_array(:name, ['mike', 'john', 'danny'])&lt;br /&gt;cursor.bind_param_array(:age, [20, 21, 22])&lt;br /&gt;cursor.max_array_size = 4&lt;br /&gt;cursor.exec_array&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Above example will generate an exception because you don't re-bind the params after calling max_array_size.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2) bind_param_array(key, var_array, type = nil, max_item_length = nil)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Bind array explicitly. This method is used to bind an array of values to a placeholder embedded in the prepared statement which is to be executed with "exec_array".&lt;br /&gt;&lt;br /&gt;When key is number, it binds by position, which starts from 1. When key is string, it binds by the name of placeholder.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;cursor = conn.parse("INSERT INTO test VALUES(:name)")&lt;br /&gt;cursor.max_array_size = 3&lt;br /&gt;cursor.bind_param_array(:name, ['mike', 'john', 'danny'])  #bind by name&lt;br /&gt;... or ...&lt;br /&gt;cursor.bind_param_array(1, ['mike', 'john', 'danny']) #bind by position&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The size of arrays bound through bind_param_array should not be greater than the size set by method  max_array_size = val.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;cursor = conn.parse("INSERT INTO test VALUES(:name)")&lt;br /&gt;cursor.max_array_size = 2&lt;br /&gt;cursor.bind_param_array(:name, ['mike', 'john', 'danny'])&lt;br /&gt;cursor.exec_array&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Above example will generate an exception because the size of array passed to bind_param_array is 3, which is greater than the size 2 set by max_array_size.&lt;br /&gt;&lt;br /&gt;If you are binding more than one parameters, all the arrays are required the same size.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;cursor = conn.parse("INSERT INTO test VALUES(:name, :age)")&lt;br /&gt;cursor.max_array_size = 3&lt;br /&gt;cursor.bind_param_array(:name, ['mike', 'john', 'danny'])&lt;br /&gt;cursor.bind_param_array(:age, [20, 21])&lt;br /&gt;cursor.exec_array&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Above example will generate an exception becase the name parameter array and age parameter array are not the same size.&lt;br /&gt;&lt;br /&gt;The array dml also supports setting values through method "[key] = val".&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;cursor = conn.parse("INSERT INTO test VALUES(:name, :age)")&lt;br /&gt;cursor.max_array_size = 3&lt;br /&gt;cursor.bind_param_array(1, nil, String)&lt;br /&gt;cursor.bind_param_array(2, nil, Fixnum)&lt;br /&gt;cursor[1] = ['mike', 'john', 'danny']&lt;br /&gt;cursor[2] = [20, 21, 22]&lt;br /&gt;cursor.exec_array&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3) exec_array&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Executes the SQL statement assigned the cursor with array binding. This implementation currently only supports non-data returning statements (INSERT, UPDATE, DELETE but not SELECT). All binding arrays should be the same size and this size will be used as iteration count for OCIStmtExecute().&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;cursor = conn.parse("INSERT INTO test VALUES(:name, :age)")&lt;br /&gt;cursor.max_array_size = 10&lt;br /&gt;cursor.bind_param_array(1, nil, String)&lt;br /&gt;cursor.bind_param_array(2, nil, Fixnum)&lt;br /&gt;cursor[1] = ['mike', 'john', 'danny']&lt;br /&gt;cursor[2] = [20, 21, 22]&lt;br /&gt;cursor.exec_array&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;In above example, three rows are inserted to the table though max_array_size is set 10.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3708407902829149391-5141491075427703209?l=limlian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://limlian.blogspot.com/feeds/5141491075427703209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3708407902829149391&amp;postID=5141491075427703209' title='154 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default/5141491075427703209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default/5141491075427703209'/><link rel='alternate' type='text/html' href='http://limlian.blogspot.com/2008/05/ruby-oci8-v20-new-feature-array-dml.html' title='Ruby-OCI8 2.0 New Feature: Array DML Support'/><author><name>Liming Lian</name><uri>http://www.blogger.com/profile/03877330950571137973</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>154</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3708407902829149391.post-7553802897299493974</id><published>2008-04-25T02:13:00.000-07:00</published><updated>2008-05-08T01:40:27.714-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby-oci8'/><category scheme='http://www.blogger.com/atom/ns#' term='ObjectType'/><category scheme='http://www.blogger.com/atom/ns#' term='RubyOCI8V2'/><title type='text'>Ruby-OCI8 2.0 New Feature: Oracle Object Type support</title><content type='html'>There are two main versions in Ruby-OCI8. Stable version 1.x has been widely used in Ruby and RoR apps, and the unstable version is 2.x, in which many new features are under experiment. Here I will give a short tutorial on how to manipulates Object Type via Ruby-OCI8 v2.0.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;1, Introduction to Oracle Object Type&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Object types are abstractions of the real-world entities, such as purchase orders, that application programs deal with. An object type is a schema object with three kinds of components:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A name, which identifies the object type uniquely within that schema.&lt;/li&gt;&lt;li&gt;Attributes, which are built-in types or other user-defined types. Attributes model the structure of the real-world entity.&lt;/li&gt;&lt;li&gt;Methods, which are functions or procedures written in PL/SQL and stored in the database, or written in a language like C or Java and stored externally. Methods implement operations the application can perform on the real-world entity.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Learn more at &lt;a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/statements_8001.htm#BABHJHEB" target="_blank"&gt;Oracle® Database SQL Language Reference&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;2, Ruby-OCI8 v2.0 Installation&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;svn co http://ruby-oci8.rubyforge.org/svn/trunk/ruby-oci8&lt;br /&gt;&lt;/pre&gt;And then follow the &lt;a href="http://ruby-oci8.rubyforge.org/en/HowToInstall.html" targe="_blank"&gt;Ruby-OCI8 install instruction&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;3, Tutorial&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Suppose we use account ruby/oci8 on an Oracle db installed on localhost&lt;br /&gt;&lt;br /&gt;Step 1, Create object type and table in database&lt;br /&gt;&lt;pre&gt;CREATE TYPE person_t AS object&lt;br /&gt;   (name varchar2(30),&lt;br /&gt;   age number(3));&lt;br /&gt;&lt;br /&gt;CREATE TABLE person_tab&lt;br /&gt;   (person_no number,&lt;br /&gt;   person person_t);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Step 2, Insert sample data&lt;br /&gt;&lt;pre&gt;INSERT INTO person_tab VALUES (1, person_t('Lan', 20));&lt;br /&gt;INSERT INTO person_tab VALUES (2, person_t('Chang', 21));&lt;br /&gt;&lt;/pre&gt;Step 3, Retrieve object type data via Ruby-OCI8&lt;br /&gt;&lt;pre&gt;require 'oci8'&lt;br /&gt;conn = OCI8.new('ruby','oci8','localhost')&lt;br /&gt;cursor = conn.exec('select * from person_tab')&lt;br /&gt;while r = cursor.fetch&lt;br /&gt;   puts "Person no: #{r[0]}"&lt;br /&gt;   puts "  name: #{r[1].name}"&lt;br /&gt;   puts "  age: #{r[1].age}"&lt;br /&gt;end&lt;br /&gt;cursor.close&lt;br /&gt;conn.logoff&lt;br /&gt;&lt;/pre&gt;Result:&lt;br /&gt;&lt;pre&gt;Person No.: 1&lt;br /&gt;   name: Lan&lt;br /&gt;   age: 20&lt;br /&gt;Person NO.: 2&lt;br /&gt;   name: Change&lt;br /&gt;   age: 21&lt;br /&gt;&lt;/pre&gt;As we see, once we have retrieved an Object Type object in Ruby, we can use .{AttributeName} to get its specific attribute value stored in database.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3708407902829149391-7553802897299493974?l=limlian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://limlian.blogspot.com/feeds/7553802897299493974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3708407902829149391&amp;postID=7553802897299493974' title='69 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default/7553802897299493974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3708407902829149391/posts/default/7553802897299493974'/><link rel='alternate' type='text/html' href='http://limlian.blogspot.com/2008/04/oracle-object-type-support-in-ruby-oci8.html' title='Ruby-OCI8 2.0 New Feature: Oracle Object Type support'/><author><name>Liming Lian</name><uri>http://www.blogger.com/profile/03877330950571137973</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>69</thr:total></entry></feed>
