루비 온 레일즈 붉은색 서적 "Biginning Ruby on Rails 라는 책에 첫 튜토리얼중 Yes it's Working 을 Local 로 html로 올리는 부분에 오류가 납니다.

그래서 무시하고 다른부분부터 보기 시작했는데 마음에 걸려 삽질을 해본결과 책에 전혀 기술되지 않은 오류 정보더군요 ㅠㅠ
 
에러내용중" MissingSourceFile in AppController#greeting" 결국 sqlite3 라는DB 를 설치 하지 않아서 ...라더군요


sqlite를 일단 설치했습니다..

설치 방법은 루비가 설치된 콘솔 창에 "gem install sqlite3-ruby" 으로 설치하시면 됩니다.                         .

hello.app 를 실행합니다. 그결과 또다른 에러가 발생합니다..

에러내용은 sqlite3.dll 이 없다고 나오네요 http://sqlite.org/download.html 에 가셔서 dll 파일을 받아 Windows\system32 아래 넣어주시면 모든 에러가 해결됩니다.

정말 기본 비기닝 책이 이렇게 힘들줄은 몰랐습니다 ㅠ 이오류는 sqllite 라는 DB에 관한 오류지만 책에서는 Mysql 을 다룹니다 ㅠㅠ 흐악 과연 또다른 문제가 어떻게 발생할지 모르겠군요...



저작자 표시 비영리
Posted by 티엘로



웹 개발을 하는데 있어서 정보들을 저장하는 DB schema 또한 개발된다.

문제는 이러한 DB의 버전 관리가 매우 어렵다는 것이다.

레일즈에서는 DB의 버전 관리를 보다 쉽게 할 수 있는 도구(마이그레이션)을 제공한다.

 

마이그레이션은 단지 db/migrate 디렉토리에 있는 루비 소스 파일에 불과하다.

각 마이그레이션의 파일 이름은 세 자리 버전 숫자와 밑줄 문자로 시작한다.

마이그레이션을 생성하는 방법에는 크게 두 가지가 있다.

모델을 생성할 때 마이그레이션이 기본적으로 생성된다.

(물론 --skip-migration 옵션을 통해 생성되지 않게 할 수도 있다)

 ruby script/generate model account

또는 모델과는 상관없이 그냥 마이그레이션을 추가할 수도 있다.

 ruby script/generate migration add_account

사실 db/migrate에 원하는 파일을 직접 만들어서 작성해도 되지만 권장되지 않는다.

 

마이그레이션 파일을 작성하기에 앞서 마이그레이션을 실행하는 방법을 알아보자.

마이그레이션은 rake 프로그램을 통해 실행할 수 있다.

 rake db:migrate

이 명령은 현재 마이그레이션되지 않은 파일이 있으면 그 정보를 DB에 반영한다.

만약 현재 DB 버전이 최신 버전이라면 아무것도 반영되지 않는다.

이어서, DB를 이전 버전으로 돌리고 싶은 경우가 있을 것이다.

이 경우에는 rake task에 VERSION=?? 옵션을 주어 원하는 버전으로 되돌릴 수 있다.

 rake db:migrate VERSION=12

이제 마이그레이션 파일을 작성하는 방법에 대해 알아보도록 한다.

 

제일 처음 마이그레이션 파일을 생성하면 다음과 같은 구조를 볼 수 있다.

(흐린 부분은 마이그레이션 종류에 따라 바뀔 수 있음)

class Account < ActiveRecord::Migration

 def self.up

  # 모델을 생성한 경우엔 다음 코드가 추가되어있음

  create_table :accounts do |t|

  end

 end

 

 def self.down

  # 모델을 생성한 경우엔 다음 코드가 추가되어있음

  drop_table :accounts

 end

end

여기서 self.up은 DB schema 변경을 적용하는 역할을 하고,

self.down은 DB schema를 뒤로 되돌리는 역할을 한다.

 

이제 기본적으로 마이그레이션에 사용되는 코드들을 한번 보도록 한다.

 

table_name이라는 테이블 생성

create_table :table_name do |t| ... end

여기에 :option => "auto_increment = 100"과 같이 여러 SQL 설정을 조작할 수 있다.

또한 :primary_key => :login_id와 같이 기본 키를 직접 지정할 수도 있다.

(이 옵션을 주지 않고 :id => false 옵션을 주면 기본 키가 없는 테이블이 만들어진다)

 

table_name이라는 테이블 제거

drop_table :table_name

 

테이블 table_name1의 이름을 table_name2로 변경

rename_table :table_name1, :table_name2

단, 테이블 이름을 바꾸는 경우 문제가 되는 경우가 많으므로 주의해야 한다.

 

테이블에 컬럼 등록 / 추가 / 제거 / 이름바꾸기

컬럼을 등록할 때는 테이블 생성시에 같이 작성해주어야 한다.

create_table :table_name do |t|

 t.column :column1, :string

 t.column :column2, :integer

end

이후에 컬럼 추가 / 제거 / 이름 바꾸기는 다음과 같이 할 수 있다.

add_column :table_name, :column3, :float

remove_column :table_name, :column2

rename_column :table_name, :column3, :column4


저작자 표시 비영리
Posted by 티엘로

#!/usr/bin/ruby -w
#xmlrpc-upc.rb
require 'xmlrpc/client' #xml-rpc 사용!
require 'pp'  #pretty-printer를 사용합니다.

def find_product(upc)
 server = XMLRPC::Client.new2('http://www.upcdatabase.com/rpc')
 begin
  response = server.call('lookupUPC', upc)
  pp response        # 이쁘게 출력합뉘다.

 rescue XMLRPC::FaultException => e
  puts "오류 : "
  puts e.faultCode
  puts e.faultString
 end
end

#puts find_product("001441000055").each{}
#puts find_product("001441000055")['description']
#puts find_product("001441000055")['foundsize']
#puts find_product("001441000055")['size']
find_product("001441000055")

# "Trader Joe's Thai Rice Noodles"

저작자 표시 비영리
Posted by 티엘로

Ruby로 만든 관리자 로그인 페이지 입니다.

로그인 폼을 만들고 액션을 해결할 컨트롤러를 생성하고,  폼에서 전달받은 내용으로 관리자임을 확인하고
쿠키를 만든 후 관리자 페이지로 이동하거나, 혹은 로그인 페이지로 다시 이동하는 기능을 합니다. 

우선 폼을 위한 html파일을 만들었습니다.
rails 프로젝트를 만든 이후에 '/public/admin/logn.html'를 만듭니다.
html안에는 간단한 폼만 있습니다.


 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>
<body>
<table style="position:absolute; top:35%; left:35%" >
 <tr><td align="left">
 <form action="/login/admin_login" method="post" name="adminLoginForm" onsubmit="return false">
 <fieldset>
 <legend>관리자 로그인</legend>
 <div><span style="margin-right:80px;">Id</span><input id="id" name="id" size="20" type="text" value="" /></div>
 <div style="margin-top:10px"><span style="margin-right:33px;">Password</span><input id="password" name="password" size="20" type="password" value="" /></div>
 <div style="position: relative; margin-top:10px; left: 200px"><input name="commit" onclick="this.disabled=true;this.value='Please wait...';this.form.submit();" type="submit" value="Login" /></div>
 </fieldset>
 </form>
 </td></tr>
</table>
</body>
</html>



action의 값을 '/login/admin_login'으로 정했습니다.
이제 Login 컨트롤러를 만들고 admin_login 메서드/뷰 를 추가하는 작업을 진행합니다.

 class LoginController < ApplicationController
 
  def admin_login
    admin_id = params[:id]
    admin_password = params[:password]
    if admin_id == 'admin' && admin_password == '1234' then
      # make cookie
      cookies[:membership] = { :value => "admin", :expires => 5.hour.from_now }
      success_to
    else
      failed_to
    end
  end
 
  def admin_logout
    # delete cookie
    cookies.delete :membership
    failed_to
  end
 
  def success_to
    redirect_to('/admin/main')
  end
 
  def failed_to
    redirect_to('/admin/login.html')
  end
 
  private :success_to, :failed_to
 
end


성공했을 경우에는 Admin 컨트롤러를 호출하게 됩니다.
이제 Admin컨트롤러를 만들고 main 메서드/뷰를 만들겠습니다. 

 require 'admin'

class AdminController < ApplicationController
  layout 'admin_page'

  before_filter :is_admin
 
  def is_admin
    if cookies['membership'] != "admin" then
      redirect_to('/admin/login.html')
    end
  end
 
  def main

  end
 end



Admin 컨트롤러를 통해서 만나는 뷰페지이지 들은  'admin_page' 레이아웃을 기본으로 합니다.
admin_page 레이아웃을 '/app/view/layouts/admin_page.rhtml'로 생성합니다.


 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>
<body>
<div>상단 <a href="/login/admin_logout">로그아웃</a></div>
<div><%= @content_for_layout %></div>
<div>하단</div>
</body>
</html>


'<%= @content_for_layout %>'에 지정된 뷰가 들어가게 됩니다.
admin/main으로 호출했으니 '/app/view/admin/main.rhtml'이 저 자리에 들어가게 됩니다.
Admin 컨트롤러에는 'before_filter'이 포함되어 있습니다.
단어 그대로 항상 먼저 실행되게 됩니다. 이렇게 함으로 /admin/ ... 으로 시작하는 모든 페이지는 쿠키값을 통해서 admin 로그인 여부를 확인하게 됩니다.

익숙한 언어로 만든다면 눈깜짝할 사이에 해결할 수도 있겠지만 

저작자 표시 비영리
Posted by 티엘로

루비(Ruby) 프로그래밍

루비 변수, 쿼트, 어레이, 객체, 메소드

developerWorks
문서 옵션
수평출력으로 설정

이 페이지 출력

이 페이지를 이메일로 보내기

이 페이지를 이메일로 보내기


제안 및 의견
피드백

난이도 : 초급

Joshua D. Drake, 프로젝트 매니저, Command Prompt, Inc

2001 년 8 월 01 일

Linux Networking HOWTO, Linux PPP HOWTO, Linux Consultants HOWTO의 저자이자 Command Prompt, Inc 의 공동 창업자인 Joshua Drake가 Ruby 프로그래밍을 설명한다. 다른 언어 사용자라도 이 글을 통해 유용한 정보를 얻을 수 있을 것이다.

루비(Ruby)는 일본의 Yukihiro Matsumoto가 개발한 순수한 객체 지향 스크립팅 언어이다. 텍스트 프로세싱과 시스템 관리 태스크를 핸들하도록 디자인되었다.

아래 예제에서 보듯이, 펄 또는 PHP 같은 스크립팅 언어를 작성해 본 경험이 있는 사람이라면 루비 신택스도 익숙할 것이다. 그러나, 펄 또는 PHP와는 다르게, 라인 종결자로 세미 콜론(semi-colon)을 사용해야 한다. 어떤 개발자들은 이런 사실 때문에 혼란스러워 할 수도 있지만 실제로 이것은 개발 속도를 높일 수 있다.


Listing 1. Hello world
#!/usr/bin/ruby
#
# My first ruby program
#
print "Hello World\n"


Listing 2. 아웃풋 변경하기
#!/usr/bin/ruby
#
# My first ruby program
#

# Declare our salutation

$salut = "Good Bye World\n"

# Prepare statements

 print "Hello World\n"
 print $salut

Using the $salut 변수를 사용하여 언제라도 두 번째 print 문장을 쉽게 변경할 수 있다. 프로그램의 어떤 지점에서도 변수를 선언할 수 있다.


Listing 3. 변수 선언하기
#!/usr/bin/ruby
#
# My first ruby program
#

$salut = "Good Bye World\n"

 print "Hello World\n"
 print $salut

#
# Declare a new value for $salut.
#

$salut = "Oh, I am sorry. I didn't mean to warn
you...\n"

 print "What do you mean Good Bye World?\n"
 print $salut

위 예제를 실행하면 아웃풋은 다음과 같다:


Hello World
Good Bye World
What do you mean Good Bye World?
Oh, I am sorry. I didn't mean to warn you...

변수 재지정(re-assignment)이 작동한다.




위로


싱글 쿼트(single quote) & 더블 쿼트(double quote)

대부분의 언어가 그렇듯, 루비도 싱글 쿼트와 더블 쿼트가 구별된다. 루비에서 더블 쿼트는 "루비는 쿼트 안에 있는 모든 값을 인터프리팅한다"는 것을 의미한다:


print "Hello World\n"

루비 인터프리터는 \n 을 이스케이핑 하지 않고 대신 새로운 라인을 STDOUT (Standard Out)에 프린트 할 것이다. 하지만 싱글 쿼트로 같은 문장을 실행시키면 다음과 같다:


print 'Hello World\n'

루비는 다음과 같이 아웃풋을 만들것이다:


Hello World\n

새로운 라인이 프린트되지 않았다는 것을 주목하라. 대신 루비는 전체 문장이 리터럴(literal)이라고 생각한다. 이것은 펄이 사용하는 것과 같은 기능이다.




위로


단어 수학

루비에서 모든 스트링은 연산자를 사용할 수 있다. 다시 말해서 단어에 대해 수학을 사용할 수 있다는 의미이다. 예를 들어:


$salut = $salut * 3

결과는 다음과 같다:


Oh, I am sorry. I didn't mean to warn you...
Oh, I am sorry. I didn't mean to warn you...
Oh, I am sorry. I didn't mean to warn you...

그리고


$salut = $salut + " 10, 9, 8..."

 print $salut

다음과 같이 결과가 나온다:


Oh, I am sorry. I didn't mean to warn you...
Oh, I am sorry. I didn't mean to warn you...
Oh, I am sorry. I didn't mean to warn you...
 10, 9, 8...

변수가 세번 프린트되었지만, "10, 9, 8..."은 프로그램의 끝에 한 번만 프린트되었다. 이유는 무엇일까?

이유는 "10, 9, 8..." 을 변수의 끝에 추가했기 때문이다. 변수에게 "10, 9, 8..."을 각 라인에 추가하라고 명령하지 않았다.

"What do you mean Good Bye World? \n" 에서 "Hello World\n" 로 바꾸었을 때 설명했지만, 일단 변수가 지정되면 그 변수가 재 지정(reassigned)되지 않는 한 정적(static)이다. 하지만 이것은 멀티플라이어(multiplier) 또는 연결(concatenation)이 변수와 함께 사용되는 경우를 의미하지는 않는다. 변수와 함께 연결(+ 표시)을 사용하면 이전에 지정된 변수와 지정된 변수에 추가된 스트링을 변수가 상속받을 수 있다. 우리의 경우, " 10, 9, 8..." 이다.




위로


어레이

$salut 변수를 여러번 재지정해야 한다면? 대부분 그런일은 발생하기 마련이다. 따라서 변수를 재지정하는 대신, 모든 변수 값을 어레이에 놓을 수 있다.

어레이는 각 변수의 값이 개별적으로 어드레스(address) 할 수 있도록 한다. 다음 예제를 보자:


$salut = ['Hello World','Good Bye World','What do you
mean Good Bye World?']

 print $salut

위에 대한 결과 아웃풋은 다음과 같다:


Hello WorldGood Bye WorldWhat do you mean Good Bye
World?

원하던 아웃풋이 아니다. 공간이나 새로운 라인이 없다. 따라서 우리는 어떤 부분의 어레이를 디스플레이 할지 정할 수 있고 아웃풋을 읽을 수 있도록 하기 위해서 연결(concatenation)을 사용할 수 있다.


$salut = ['Hello World','Good Bye World','What do you
mean Good Bye World?']

 print $salut[0] + "\n"
 print $salut[1] + "\n"
 print $salut[2] + "\n"

아웃풋은 다음과 같다:


Hello World
Good Bye World
What do you mean Good Bye World?

코드를 분석해보자:


$salut = ['Hello World','Good Bye World','What do you
mean Good Bye World?']

루비에서는 다음의 값을 갖고 있는 salut 변수를 지정할 수 있다:

$salut = 0 1 2
Hello World Good Bye World What do you mean Good Bye World?

0

으로 시작하고 이것에서 부터 늘어난다. 어레이의 두 번째 값을 프린트하기 위해 다음과 같이 타이핑한다:


 print $salut[1]




위로


IF, ELSE 조건

루비에서 데이터를 나타내는 기초를 살펴보았다. 이제 루비 프로그램의 로직에 대해 살펴보자. 말하자면 프로그래머에게 받은 결과에 근거한 기본 함수작동을 수행하도록 지시하는 것이다. 또한 루비 프로그램이 사용자에게 받은 결과에 대한 조건을 수행하는 방법도 살펴 볼 것이다. 새로운 코드가 이 예제에 사용될 것이다.


Listing 4. 결과에 근거한 기본 함수 수행하기
$salut = ['Hello World','Good Bye World','What do you
mean Good Bye World?']

 print "When you enter the world, what do you say? "
 while enterWorld = STDIN.gets
   enterWorld.chop!
   if enterWorld == $salut[0]
     print "\n" + "Yes. Hello World would be
polite.\n"
     break
   else
     print "You say '", enterWorld, "'?!\n" + "You
humans are so rude!\n"
   end
  end

루비 개발의 새로운 면이 위 코드에 많이 소개되었다.


예제
#!/usr/bin/ruby
#
# My first interactive ruby script
#

# Define our main variable with an array

$salut = ['Hello World','Good Bye World','What do you
mean Good Bye World?']

# Print my first question

 print "When you enter the world, what do you say? "

# Create a while loop with the object enterWorld and
await data from
# standard input. The while loop will make sure that
ruby continues
# to process the application until the program tells
it to stop.

 while enterWorld = STDIN.gets

# Make sure we use the chop method on the enterWorld
object. The use
# of the chop method will insure that we strip new
lines and carriage
# returns from our input.

# You will notice that using the chop method has an
extra
# character. The ! allows the existing object to be
modified
# by the method. If you did not use the !, you would
have to redeclare
# the enterWorld object for the if condition to
correctly occur.

   enterWorld.chop!

# Begin the condition sequence. Basically, if
enterworld equals
# Hello World, which is 0, within the array, print
# a new line. Then print, "Yes, Hello World would be
polite." to the screen.

   if enterWorld == $salut[0]
     print "\n" + "Yes. Hello World would be
polite.\n"

# The break statement tells ruby to stop executing if
the previous
# condition is met. If we did not include this in our
while loop,
# the program would run continuously.

    break

# The else statement is used as the secondary
condition. In other
# words, if the first condition is not met, please do
the following.

   else
     print "You say '", enterWorld, "'?!\n" + "You
humans are so rude!\n"
   break

# The end statement is used to close a condition or
loop. In our case,
# it is being used to close both. We are first closing
our if
# condition statements and then stopping our while
loop.

   end
  end




위로


객체와 메소드

이 코드에 사용된 몇 가지의 기술과 방법들은 여러분에게 생소할 수도 있다. 루비는 객체 지향 프로그래밍(OOP) 언어이다. OOP를 사용한다는 것은 일반적으로 객체와 매소드 같은 아이템을 호출하는 것이다. 객체(object)는 콘테이너와 같다. 이것은 변수와 함수를 포함하고 있다. 매소드(method) 는 객체를 어드레싱하는 함수와 같은 것이다. 이전 예제에서, 객체와 메소드가 모두 실행되는 것을 보여줄 수 있다.


1
while enterWorld = STDIN.gets
   enterWorld.chop!

두 개의 객체와 두 개의 메소드가 있다. 첫 번째 객체는 enterWorld 이고 두 번째 객체는 STDIN 이다. enterWorld 객체는 사용자 정의 객체이고 STDIN 객체는 루비에 구현되어 있다.

예제에는 두 개의 메소드도 있다. 첫 번째는 gets 이고 두 번째는 chop!이다. 앞서 언급했지만 메소드는 객체를 어드레싱 한다. 특히 메소드는 객체 안에서 액션을 수행한다. gets 메소드를 사용하여 루비에게 STDIN을 얻도록(get) 명령할 수 있다. 루비가 STDIN 과 관련된 gets를 보면, 키보드 인풋과 캐리지 리턴(carriage return)을 기다릴 것이다. STDIN.gets은 사용자가 무언가를 타이핑하고 엔터를 치기를 기다린다.

두 번째 메소드인 chop!은 사용자 정의 객체인 enterWorld를 어드레싱 한다. chop! 메소드는 enterWorld에게 enterWorld 객체와 관련된 데이터에서 새로운 라인과 캐리지리턴으로 자르도록 (chop) 명령한다. 이전의 코드에서chop! (또는 chomp!)을 사용하지 않는다면 "true"가 결코 될 수 없다.


 if enterWorld == $salut[0]

chop!를 사용하지 않고 $salut[0]이 실제로 $salut[0]\n와 같기 때문에 "false"가 된다. 새로운 라인은 STDIN 객체가 gets 메소드에서 받은 인풋에 의해 생겨난다. 캐리지 리턴을 사용하면 새로운 라인 문자들을 값의 끝에 추가하게 된다.




위로


결론

루비는 매우 강력하지만 사용하기가 쉽지만은 않다. C++, Perl, Python 프로그래밍 경험이 있다면 그러한 언어들과 루비와의 상당한 유사성을 발견하게 될 것이다 (특히 Python).



참고자료



필자소개

Joshua Drake는 Command Prompt, Inc의 공동 창립자이다. PostgreSQL과 리눅스 개발을 하고 있다. Linux Networking HOWTO, Linux PPP HOWTO, Linux Consultants HOWTO의 저자이기도 하다.

저작자 표시 비영리
Posted by 티엘로