액션 뷰(폼 도우미 메소드)

IT(Old)/RubyOnRails-Tip 2008. 1. 22. 12:19
<% form_for :person, Lurl => {:action => "create"} do |f| %>
<p>이름: <%= f.text_field("name") %> </p>
<p>그룹: <%= f.select("group",
                                 [["A", "1"], ["B", "2"], ["C", "3"]]) %> </p>
<p>노트: <br /><%= f.text_area("note") %> </p>
<p><%= submit_tag("입력") %></p>
<% end %>

f.text_field(name, options) : 텍스트 필드를 출력해줌. 한줄의 텍스트를 입력받을 때 사용
f.text_area(name, options): TextArea 필드를 출력해줌
f.password_field(name, options): 패스워드 필드를 출력해줌.
f.hidden_field(name, options): 히든 필드를 출력해줌
f.select(name, options):콤보박스 필드를 출력해줌.
<%= f.select("group_id", @groups.map{|g| [g.name, g.id]},
                   :selected => "2", :include_blank => true) %>
=>
<select name="person[group_id]">
...

f.date_select(name, options): 날짜 입력을 위한 콤보 박스 필드를 출력해줌.
<% f.date_select("birth_date", :start_year => 2000,
                                           :end_year => 2010,
                                           :use_month_numbers => true) %>

f.datetime_select(name, options): 날짜 입력을 위한 콤보 박스 필드를 출력해 줌
f.check_box(name, options): 체크박스 필드를 출력해줌
f.radio_button(name, options): 라디오 버튼 필드를 출력해줌
f.file_field(name, options): 파일 업로드 필드를 출력해줌
submit_tag(name): html 입력 필드를 출력해줌

액션뷰 (h메소드)

IT(Old)/RubyOnRails-Tip 2008. 1. 22. 10:37
<%= h("차림표") %>
부분의 코드에서 h도우미 메소드는 인자로 받는 문자열 중에
<, >, & 등의 문자가 있을 때 이를 이스케이프 시켜주는 메소드이다. 이들 문자는 html내에서 특별하게 인식되기 때문에, 이들 문자가 텍스트 중에 그대로 사용되면, 브라우저에서 html화면이 깨져 보이게 된ㄷ.ㅏ 따라서 텍스트 데이터가 html문서의 중간에 삽이되는 경우에는 항상 h메소드를 적용하는 습관을 들이는 것이 좋다.

액션 뷰(빈줄 삽입)

IT(Old)/RubyOnRails-Tip 2008. 1. 22. 10:17
HTML코드에서 <% @name = "홍길동" %> 이 입력되었던 다리에 빈줄이 삽입된 것을 알 수 있다.
이러한 빈 줄이 삽입되지 않기를 원한다면, <% @name = "홍길동" %> 대신에 <% @name = "홍길동" =%>이라고 입력하면 된다.

플래시 사용예제

IT(Old)/RubyOnRails-Tip 2008. 1. 22. 10:03


class UsersController < ApplicationController
  def list
    @users = User.find(:all)
    @message = flash[:message]
  end
 
  def show
    @user = User.find(params[:id])
  end
 
  def new
    @user = User.new
  end
 
  def create
    @user = User.new(params[:user])
    if @user.save
      flash[:message] = "새로운 사용자가 추가되었습니다."
      redirect_to :action => 'list'
    else
      render :action => 'new'
    end
   
  end
end

쿠키사용예제

IT(Old)/RubyOnRails-Tip 2008. 1. 22. 09:54

옵션들
:expire = 웹 브라우저가 쿠키를 얼마나 오랫동안 보관할 것인지를 지정하는 옵션이다. :expire 옵션에는 쿠키가 유효한 최종 날짜를 지정하면 된다.
(expire옵션이 생략되는 경우, 해당 쿠키는 웹브라우저가 종료되는 순간까지만 보관된다.)

:domain = 쿠키가 사용될 도메인을 지정하는 데 사용된다. 이 옵션이 생략되면 현재 사용되고 있는 웹 애플리케이션의 도메인이 사용되는데, 이런 경우 쿠키가 다른 서브 도메인과 공유되지 않는다. 예를 들어 현재의 웹 애플리케이션이 www.mysite.co.kr도메인을 사용하고 있다면, 이 서버에서 웹 브라우저에 저장한 쿠키는 help.mysite.co.kr 도메인을 사용하는 웹 애플리케이션으로는 보내지지 않는다.
(사용법 : :domain => ".mysite.co.kr")

:path = 쿠키가 사용될 URL의 디렉토리 경로를 지정하는 데 사용된다. 예를 들어 :path => "/search" 라는 옵션을 지정하면, 이 쿠키는 URL이 www.mysite.co.kr/search로 시작되는 경우에만 서버로 보내진다. 이 옵션이 생략되면, 쿠키의 :path값으로 현재 페이지의 디렉토리 경로가 사용된다.

:secure = :secure => true 옵션을 사용하면, 쿠키가 https프로토콜이 사용되는 경우에만 보내지게 된다. HTTPS는 HTTP에 보안 기능이 추가된 프로토콜로, HTTPS를 사용하여 전송되는 모든 정보는 암호화되어 안전하게 전송된다.

class LoginController < ApplicationController

  def login_form
    reset_session
    @login = cookies[:login]
  end

  def login
    @user = User.find_by_login(params[:login])
    cookies[:login] = {:value => @user.login, :expire => 30.day.from_now}
   
    if @user && (@user.password == params[:password])
      session[:user_id] = @user.id
      redirect_to :action => "index"
    else
      flash[:error] = "로그인 ID나 비밀번호가 틀렸습니다!"
      redirect_to(:action => "index")
    end
  end

  def logout
    reset_session
    redirect_to(:action => "login_form")
  end

  def index
    if session[:user_id]
      render_text "#{User.find(session[:user_id]).name}님 환영합니다.!"
    else
      redirect_to :action => "login_form"
    end
  end
end

세션과(session) 플래시(flash) 기능 팁

IT(Old)/RubyOnRails-Tip 2008. 1. 22. 09:08

1. session : session 메소드는 해시 객체를 리턴하는데, 이 해시가 바로 세션 데이터가 저장되는 장소이다.
사용자가 로그인 된 이후에는, sessoin[:user_id]이 현재 로그인된 사용자 ID를 리턴하게 된다. 만약 현재의 사용자가 로그인되어 있지 않다면, session[:user_id]는 nil을 리턴한다.

세션기능은 기본적으로 on 상태이기 때문에 이 기능을 필요치 않은 페이지에서는
각 컨트롤러 선언부 바로 밑에
session :off
을 사용하여 중지시킬수도 있다.

2. Flash : 플래시 기능이 유용한 것은 앞에서도 설명한 바와 같이 HTTP 프로토콜이 상태를 보존할 수 없는 프로토콜이기 때문이다. 플래시는 세션과는 다르게 웹 브라우저의 바로 다음 요청까지만 데이터를 보존한다. 즉 login 액션에서 플래시에 저장된 에러 메세지는 바로 다음 요청인 login_form 액션까지만 유지되고, 그 이후에는 자동으로 삭제된다. 플래시에 대한 자세한 내용은 5.5절 '플래시'에서 다루고 있다.


사용예제
class LoginController < ApplicationController

  def login_form
    reset_session
   
  end

  def login
    @user = User.find_by_login(params[:login])
   
    if @user && (@user.password == params[:password])
      session[:user_id] = @user.id
      redirect_to :action => "index"
    else
      flash[:error] = "로그인 ID나 비밀번호가 틀렸습니다!"
      redirect_to(:action => "index")
    end
  end

  def logout
    reset_session
    redirect_to(:action => "login_form")
  end

  def index
    if session[:user_id]
      render_text "#{User.find(session[:user_id]).name}님 환영합니다.!"
    else
      redirect_to :action => "login_form"
    end
  end
end

rails console사용하기 2 (activeRecord의 수정,삭제사용법)

IT(Old)/RubyOnRails 2008. 1. 21. 16:22
1. 수정

간단하다

@user = User.find(1)
@user.password = "aaa"
@user.save

2. 삭제
한개삭제
@user = User.find(3)
@user.destroy

여러개 삭제
@user = User.find(:all, conditions > ["id" >1])
@user.destroy_all

아이디로 삭제
User.delete(3)
User.delete([1, 2, 5])

조건별로 여러개 삭제
User.delete_all(["registered_on = ?", Date.today])

migration 문법

IT(Old)/RubyOnRails 2008. 1. 21. 15:08
1. 널값 허용X

create_table "groups" do |t|
  t.column "name", :string, Lnull => false
end

2. default값 지정
create_table "users" do |t|
  t.column "type", :string, Ldefault => "일반"
end

3. 문자열 컬럼 길이 지정
create_table "groups" do |t|
  t.column "name", :string, Llimit => 10
end

4. 숫자컬럼 길이지정
create_table "people" do |t|
  t.column "name", :string
  t.column "height", :decimal, Lprecision => 5, Lscale => 2
end

5. boolean
boolean은 TINYINT로 지정이 되어 true(1), false(2) 로 저장이 된다.

6. 테이블명 변경
rename_table "groups", categories"

7. 인덱스 추가
  add_index "groups", "name", :unique => true
  remove_index "groups", "name"

8. 기타 SQL
마이그레이션에서 지원하지 않는 비표준 기능은 execute를 사용해라

execute "ALTER TABLE people ADD CONSTRAINT fk_person_group"
 

테이블 명명규칙

IT(Old)/RubyOnRails-Tip 2008. 1. 21. 09:47

rails에서는

테이블명에는 복수형을(끝에 s붙임)

모델은 단수형을 사용한다.

그래야...자동으로 테이블 일대일매핑이 가능하다.

ㅡ.ㅡ

3. 기본문법3(Containers, Blocks, and Iterators)

IT(Old)/RubyOnRails 2008. 1. 15. 16:01

1. Containers

DATA를 저장하는 Container객체에 대해 알아보자
이런저런 설명 빼고 어떻게 사용하는지만 보면 될 듯 싶다.

- Arrays

a = [ 3.14159, "pie", 99 ] 
a.type  » Array 
a.length  » 3 
a[0]  » 3.14159 
a[1]  » "pie" 
a[2]  » 99 
a[3]  » nil 
 
b = Array.new 
b.type  » Array 
b.length  » 0 
b[0] = "second" 
b[1] = "array" 
b  » ["second", "array"] 


이건 그냥 대략 이해 가고

a = [ 1, 3, 5, 7, 9 ] 
a[-1]  » 9 
a[-2]  » 7 
a[-99]  » nil


여기서 주의할 점은 -(마이너스)인덱스도 거꾸로 1까지만 가고 그 이상이 되면(-6) nil값을 return한다.

a = [ 1, 3, 5, 7, 9 ] 
a[1, 3]  » [3, 5, 7] 
a[3, 1]  » [7] 
a[-3, 2]  » [5, 7]
 

이것은 arrya[start, count] 방식으로 사용한다.

a = [ 1, 3, 5, 7, 9 ] 
a[1..3]  » [3, 5, 7] 
a[1...3]  » [3, 5] 
a[3..3]  » [7] 
a[-3..-1]  » [5, 7, 9]
 

.. 은 마지막것을 포함 ...은 마지막을 제외한다.

a = [ 1, 3, 5, 7, 9 ] » [1, 3, 5, 7, 9]
a[1] = 'bat' » [1, "bat", 5, 7, 9]
a[-3] = 'cat' » [1, "bat", "cat", 7, 9]
a[3] = [ 9, 8 ] » [1, "bat", "cat", [9, 8], 9]
a[6] = 99 » [1, "bat", "cat", [9, 8], 9, nil, 99]


마지막에 인덱스를 건더뛰게되면 중간에 빈것은 nil

a = [ 1, 3, 5, 7, 9 ] » [1, 3, 5, 7, 9]
a[2, 2] = 'cat' » [1, 3, "cat", 9]
a[2, 0] = 'dog' » [1, 3, "dog", "cat", 9]
a[1, 1] = [ 9, 8, 7 ] » [1, 9, 8, 7, "dog", "cat", 9]
a[0..3] = [] » ["dog", "cat", 9]
a[5] = 99 » ["dog", "cat", 9, nil, nil, 99]


여기서는 처음것은 index 두번째것은 length(0은 빈곳 삽입, 1은 한개만 replace, 2는 두개 replace)

- Hashes

h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' } 
 
h.length  » 3 
h['dog']  » "canine" 
h['cow'] = 'bovine' 
h[12]    = 'dodecine' 
h['cat'] = 99 
h  » {"cow"=>"bovine", "cat"=>99, 12=>"dodecine", "donkey"=>"asinine", "dog"=>"canine"}
 

2. Implementing a SongList Container

class Song
 
  attr_reader :name, :artist, :duration
  def initialize(name, artist, duration)
    @name = name
    @artist = artist
    @duration = duration
  end
  def name
    @name
  end
  def artist
    @artist
  end
  def duration
    @duration
  end
  def duration=(newDuration)
    @duration = newDuration
  end
  def durationInMinutes
     @duration/60.0
   end
end

class SongList
  def initialize
    @songs = Array.new
  end
 
  def append(aSong)
    @songs.push(aSong)
    self
  end
 
  def deleteFirst
    @songs.shift
  end
  def deleteLast
    @songs.pop
  end
 
  def [] (key)
    if key.kind_of?(Integer)
      @songs[key]
    else
      # ...
    end
  end
end

list = SongList.new
list.
  append(Song.new('title1','artist1',1)).
  append(Song.new('title2','artist2',2)).
  append(Song.new('title3','artist3',3)).
  append(Song.new('title4','artist4',4))
 
 
#puts list.deleteFirst
#puts list.deleteFirst
#puts list.deleteFirst
#puts list.deleteFirst
#puts list.deleteFirst

#puts list[0]
#puts list[2]
#puts list[9]


여기서 shift 는 queue라 봤을때 처음값을 삭제
pop은 마지막것을 삭제한다 보면 된다.

key.kind_of?(Integer) 부분은 인자값을로 받은것이 정수인지 구분

3. Blocks and Iterators

위의것은 인덱스로만 검색하는 것이고 이제부터는 문자열로 검색 가능토록 만들어보자

총 3가지 방법이 있다.
첫번째는

class SongList
  def [](key)
    if key.kind_of?(Integer)
      return @songs[key]
    else
      for i in
0...@songs.length
        return @songs[i] if key == @songs[i].name
      end
    end
    return nil
  end
end


다른 언어에서와 같이 평범하다. 여기에 루비 문법을 적용해보면
두번째와 같다.

class SongList
  def [](key)
    if key.kind_of?(Integer)
      result = @songs[key]
    else
      result = @songs.find { |aSong| key == aSong.name }
    end
    return result
  end
end


어랏 간단해졌네... 하지만 이것도 맛배기.. 더 간단히 줄여보자
세번째는 다음과 같다.

class SongList
  def [](key)
    return @songs[key] if key.kind_of?(Integer)
    return @songs.find { |aSong| aSong.name == key }
  end
end


헐;;; 사람들이 루비 칭찬하는 이유를 알겠다.....
이제부터 나는 세번째 방법으로 할련다.

- Implementing Iterator

앞서 아래와 같이 yield의 간단한 사용법을 배웠다
def threeTimes
  yield
  yield
  yield
end
threeTimes { puts "Hello" }

 
produces: Hello
Hello
Hello


이것 응용한 것을 보면 다음과 같다.(아 머리 아파 하지 말자)

def fibUpTo(max)
  i1, i2 = 1, 1        # parallel assignment
  while i1 <= max
    yield i1
    i1, i2 = i2, i1+i2
  end
end
fibUpTo(1000) { |f| print f, " " }

produces: 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

값의 흐름을 보면 간단하니깐
i1  i2
1    1
1    2
2    3
3    5
5    8
....
610 987
이런 형태로 값이 쌓인다.

주의해서 볼 것은 병렬로 값의 저장이 가능하다는 것과
yield로 자기를 호출한 것에 다시 값을 return 해 준다는 것.. 쫌만 쬐려보면 금방 이해 된다.

더 응용된 예제를 보자

class Array 
  def find 
    for i in 0...size 
      value = self[i] 
      return value if yield(value) 
    end 
    return nil 
  end 
end
 
 
[1, 3, 5, 7, 9].find {|v| v*v > 30 } 

위 예제는 find를 하면서 loop를 돌고
일방적으로 값을 넘기는 것이 아니고 서로 통신하고 잇따 보면 된다. 결과 값을 puts로 찍으면 7
설명이 길어지니 pass

또다른 형태의 iterator 방법을 보자

[ 1, 3, 5 ].each { |i| puts i }
 
produces: 1
3
5


각각의 값을 받고 1, 3, 5출력

puts ["H", "A", "L"].collect { |x| x.succ }

이것은 I B M 출력한다.
succ는 바로 다음 ascii코드를 뿌리는건가? 에랏 모르겠다.

4. Ruby Compared with C++ and Java

class Array 
  def inject(n) 
     each { |value| n = yield(n, value) } 
     n 
  end 
  def sum 
    inject(0) { |n, value| n + value } 
  end 
  def product 
    inject(1) { |n, value| n * value } 
  end 
end 
puts [ 1, 2, 3, 4, 5 ].sum  #≫ 15 
puts [ 1, 2, 3, 4, 5 ].product  #≫ 120


이것도 설명이 길어지므로 pass

5. Blocks for Transactions

Blocks can be used to define a chunk of code that must be run under some kind of transactional control. For example, you'll often open a file, do something with its contents, and then want to ensure that the file is closed when you finish. Although you can do this using conventional code, there's an argument for making the file responsible for closing itself. We can do this with blocks. A naive implementation (ignoring error handling) might look something like the following.

class File
  def File.openAndProcess(*args)
    f = File.open(*args)
    yield f
    f.close()
  end
end

File.openAndProcess("testfile", "r") do |aFile|
  print while aFile.gets
end

 
produces: This is line one
This is line two
This is line three
And so on...



This small example illustrates a number of techniques. The openAndProcess method is a class method---it may be called independent of any particular File object. We want it to take the same arguments as the conventional File.open method, but we don't really care what those arguments are. Instead, we specified the arguments as *args, meaning ``collect the actual parameters passed to the method into an array.'' We then call File.open, passing it *args as a parameter. This expands the array back into individual parameters. The net result is that openAndProcess transparently passes whatever parameters it received to File.open .

Once the file has been opened, openAndProcess calls yield, passing the open file object to the block. When the block returns, the file is closed. In this way, the responsibility for closing an open file has been passed from the user of file objects back to the files themselves.

Finally, this example uses do...end to define a block. The only difference between this notation and using braces to define blocks is precedence: do...end binds lower than ``{...}''. We discuss the impact of this on page 234.

The technique of having files manage their own lifecycle is so useful that the class File supplied with Ruby supports it directly. If File.open has an associated block, then that block will be invoked with a file object, and the file will be closed when the block terminates. This is interesting, as it means that File.open has two different behaviors: when called with a block, it executes the block and closes the file. When called without a block, it returns the file object. This is made possible by the method Kernel::block_given? , which returns true if a block is associated with the current method. Using it, you could implement File.open (again, ignoring error handling) using something like the following.

class File
  def File.myOpen(*args)
    aFile = File.new(*args)
    # If there's a block, pass in the file and close
    # the file when it returns
    if block_given?
      yield aFile
      aFile.close
      aFile = nil
    end
    return aFile
  end
end


6. Blocks Can Be Closures

Let's get back to our jukebox for a moment (remember the jukebox?). At some point we'll be working on the code that handles the user interface---the buttons that people press to select songs and control the jukebox. We'll need to associate actions with those buttons: press STOP and the music stops. It turns out that Ruby's blocks are a convenient way to do this. Let's start out by assuming that the people who made the hardware implemented a Ruby extension that gives us a basic button class. (We talk about extending Ruby beginning on page 169.)

bStart = Button.new("Start")
bPause = Button.new("Pause")

# ...

What happens when the user presses one of our buttons? In the Button class, the hardware folks rigged things so that a callback method, buttonPressed, will be invoked. The obvious way of adding functionality to these buttons is to create subclasses of Button and have each subclass implement its own buttonPressed method.

class StartButton < Button
  def initialize
    super("Start")       # invoke Button's initialize
  end
  def buttonPressed
    # do start actions...
  end
end

bStart = StartButton.new

There are two problems here. First, this will lead to a large number of subclasses. If the interface to Button changes, this could involve us in a lot of maintenance. Second, the actions performed when a button is pressed are expressed at the wrong level; they are not a feature of the button, but are a feature of the jukebox that uses the buttons. We can fix both of these problems using blocks.

class JukeboxButton < Button
  def initialize(label, &action)
    super(label)
    @action = action
  end
  def buttonPressed
    @action.call(self)
  end
end

bStart = JukeboxButton.new("Start") { songList.start }
bPause = JukeboxButton.new("Pause") { songList.pause }

The key to all this is the second parameter to JukeboxButton#initialize. If the last parameter in a method definition is prefixed with an ampersand (such as &action), Ruby looks for a code block whenever that method is called. That code block is converted to an object of class Proc and assigned to the parameter. You can then treat the parameter as any other variable. In our example, we assigned it to the instance variable @action. When the callback method buttonPressed is invoked, we use the Proc#call method on that object to invoke the block.

So what exactly do we have when we create a Proc object? The interesting thing is that it's more than just a chunk of code. Associated with a block (and hence a Proc object) is all the context in which the block was defined: the value of self, and the methods, variables, and constants in scope. Part of the magic of Ruby is that the block can still use all this original scope information even if the environment in which it was defined would otherwise have disappeared. In other languages, this facility is called a closure.

Let's look at a contrived example. This example uses the method proc, which converts a block to a Proc object.

def nTimes(aThing) 
  return proc { |n| aThing * n } 
end 
 
p1 = nTimes(23) 
p1.call(3)  » 69 
p1.call(4)  » 92 
p2 = nTimes("Hello ") 
p2.call(3)  » "Hello Hello Hello "
 

The method nTimes returns a Proc object that references the method's parameter, aThing. Even though that parameter is out of scope by the time the block is called, the parameter remains accessible to the block