'Ruby on Rails'에 해당되는 글 8건

  1. 2007.02.15 [Ruby syntax] Ruby 문법 (3)
  2. 2007.01.29 Rolling with Ruby on Rails 5/5
  3. 2007.01.29 Rolling with Ruby on Rails 4/5
  4. 2007.01.29 Rolling with Ruby on Rails 3/5
  5. 2007.01.29 Rolling with Ruby on Rails 2/5
  6. 2007.01.29 Rolling with Ruby on Rails 1/5
  7. 2007.01.24 개발환경 만들기 (Local)
  8. 2007.01.24 개발을 위한 Download 사이트
영문이라고 너무 서운해 하지 마세요 ^^
의미전달은 영문이 다소 편하답니다.
더욱시 sample 코드들이 들어 있어서 영문밖에 없다 불편해 하실것도
아닐것 같습니다.

Ruby syntax

The character set used in the Ruby source files for the current implementation is based on ASCII. The case of characters in source files is significant. All syntactic constructs except identifiers and certain literals may be separated by an arbitrary number of whitespace characters and comments. The whitespace characters are space, tab, vertical tab, backspace, carriage return, and form feed. Newlines works as whitespace only when expressions obviously continues to the next line.



Ruby identifiers are consist of alphabets, decimal digits, and the underscore character, and begin with a alphabets(including underscore). There are no restrictions on the lengths of Ruby identifiers.


	# this is a comment line

Ruby comments start with "#" outside of a string or character literal (?#) and all following text until the end of the line.


	the everything between a line beginning with `=begin' and
	that with `=end' will be skipped by the interpreter.

If the Ruby interpreter encounters a line beginning with =begin, it skips that line and all remaining lines through and including a line that begins with =end.

The reserved words are:

	BEGIN	 class	  ensure   nil	    self     when
	END	 def	  false    not	    super    while
	alias	 defined  for	   or	    then     yield
	and	 do	  if	   redo     true
	begin	 else	  in	   rescue   undef
	break	 elsif	  module   retry    unless
	case	 end	  next	   return   until


	print "hello world!\n"

Ruby programs are sequence of expressions. Each expression are delimited by semicolons(;) or newlines. Backslashes at the end of line does not terminate expression.


	if test then ok else ng end

Ruby expressions can be grouped by parentheses.


	"this is a string expression\n"
	%q!I said, "You said, 'She said it.'"!
	%!I said, "You said, 'She said it.'"!
	%Q('This is it.'\n)

String expressions begin and end with double or single quote marks. Double-quoted string expressions are subject to backslash escape and expression substitution. Single-quoted strings are not (except for \' and \\).

The string expressions begin with % are the special form to avoid putting too many backslashes into quoted strings. The %q/STRING/ expression is the generalized single quote. The %Q/STRING/ (or %/STRING/) expression is the generalized double quote. Any non-alphanumeric delimiter can be used in place of /, including newline. If the delimiter is an opening bracket or parenthesis, the final delimiter will be the corresponding closing bracket or parenthesis. (Embedded occurrences of the closing bracket need to be backslashed as usual.)

Backslash notation   (top▲)

carriage return(0x0d)
form feed(0x0c)
character in octal value nnn
character in hexadecimal value nn
control x
control x
meta x (c | 0x80)
meta control x
character x itself

The string literal expression yields new string object each time it evaluated.


	%x{ date }

Strings delimited by backquotes are performed by a subshell after escape sequences interpretation and expression substitution. The standard output from the commands are taken as the value. Commands performed each time they evaluated.

The %x/STRING/ is the another form of the command output expression.


	/^Ruby the OOPL/
	/my name is #{myname}/o

Strings delimited by slashes are regular expressions. The characters right after latter slash denotes the option to the regular expression. Option i means that regular expression is case insensitive. Option i means that regular expression does expression substitution only once at the first time it evaluated. Option x means extended regular expression, which means whitespaces and commens are allowd in the expression. Option p denotes POSIX mode, in which newlines are treated as normal character (matches with dots).

The %r/STRING/ is the another form of the regular expression.

beginning of a line or string
end of a line or string
any character except newline
word character[0-9A-Za-z_]
non-word character
whitespace character[ \t\n\r\f]
non-whitespace character
digit, same as[0-9]
beginning of a string
end of a string, or before newline at the end
end of a string
word boundary(outside[]only)
non-word boundary
[ ]
any single character of set
0 or more previous regular expression
0 or more previous regular expression(non greedy)
1 or more previous regular expression
1 or more previous regular expression(non greedy)
at least m but most n previous regular expression
at least m but most n previous regular expression(non greedy)
0 or 1 previous regular expression
( )
grouping regular expressions
(?# )
(?: )
grouping without backreferences
(?= )
zero-width positive look-ahead assertion
(?! )
zero-width negative look-ahead assertion
turns on (or off) `i' and `x' options within regular expression. These modifiers are localized inside an enclosing group (if any).
(?ix-ix: )
turns on (or off) `i' and `x' options within this non-capturing group.

Backslash notation and expression substitution available in regular expressions.


	"my name is #{$ruby}"

In double-quoted strings, regular expressions, and command output expressions, the form like "#{expression}" extended to the evaluated result of that expression. If the expressions are the variables which names begin with the character either `$',`@', expressions are not needed to be surrounded by braces. The character `#' is interpreted literally if it it not followed by characters `{',`$',`@'.

There's a line-oriente form of the string literals that is usually called as `here document'. Following a << you can specify a string or an identifier to terminate the string literal, and all lines following the current line up to the terminator are the value of the string. If the terminator is quoted, the type of quotes determines the type of the line-oriented string literal. Notice there must be no space between << and the terminator.

If the - placed before the delimiter, then all leading whitespcae characters (tabs or spaces) are stripped from input lines and the line containing delimiter. This allows here-documents within scripts to be indented in a natural fashion.

	  print <<EOF
	The price is #{$Price}.

	  print <<"EOF";			# same as above
	The price is #{$Price}.

	  print <<`EOC`			# execute commands
	echo hi there
	echo lo there

	  print <<"foo", <<"bar"	# you can stack them
	I said foo.
	I said bar.

	  myfunc(<<"THIS", 23, <<'THAT')
	Here's a line
	or two.
	and here's another.

	  if need_define_foo
	    eval <<-EOS			# delimiters can be indented
              def foo
                print "foo\n"

integer(underscore within decimal numbers ignored)
floating point number
floating point number
hexadecimal integer
binary integer
octal integer
ASCII code for character `a'(97)
Integer corresponding identifiers, variable names, and operators.

In ?-representation all backslash notations are available.

The variable in Ruby programs can be distinguished by the first character of its name. They are either global variables, instance variables, local variables, and class constants. There are no restriction for variable name length (except heap size).



The variable which name begins with the character `$', has global scope, and can be accessed from any location of the program. Global variables are available as long as the program lives. Non-initialized global variables has value nil.



The variable which name begins which the character `@', is an instance variable of self. Instance variables are belong to the certain object. Non-initialized instance variables has value nil.



The identifier which name begins with upper case letters ([A-Z]) is an constant. The constant definitions are done by assignment in the class definition body. Assignment to the constants must be done once. Changing the constant value or accessing to the non-initialized constants raises a NameError exception.

The constants can be accessed from:

  • the class or module body in which the constant is defined, including the method body and the nested module/class definition body.
  • the class which inherit the constant defining class.
  • the class or module which includes the constant defining module.

Class definition defines the constant automatically, all class names are constants.

To access constants defined in certain class/module, operator :: can be used.

To access constants defined in the Object class, operator :: without the left hand side operand can be used.



No assignment using operator `::' is permitted.



The identifier which name begins with lower case character or underscore, is a local variable or a method invocation. The first assignment in the local scope (bodies of class, module, method definition) to such identifiers are declarations of the local variables. Non-declared identifiers are method invocation without arguments.

The local variables assigned first time in the blocks are only valid in that block. They are called `dynamic variables.' For example:

	i0 = 1
	loop {
	  i1 = 2
	  print defined?(i0), "\n"	# true
	  print defined?(i1), "\n"	# true
	print defined?(i0), "\n"	# true
	print defined?(i1), "\n"	# false

There are special variables called `pseudo variables'.

the receiver of the current method
the sole instance of the Class NilClass(represents false)
the sole instance of the Class TrueClass(typical true value)
the sole instance of the Class FalseClass(represents false)
the current source file name.
the current line number in the source file.

The values of the pseudo variables cannot be changed. Assignment to these variables causes exceptions.


	[1, 2, 3]


	`[' expr,...`]'

Returns an array, which contains result of each expressions. Arrays are instances of the class Array.

%w expressions make creation of the arrays of strings easier. They are equivalent to the single quoted strings split by the whitespaces. For example:

	%w(foo bar baz)

is equivalent to ["foo", "bar", "baz"]. Note that parenthesis right after %s is the quote delimiter, not usual parenthesis.


	{1=>2, 2=>4, 3=>6}


	{ expr => expr...}

Returns a new Hash object, which maps each key to corresponding value. Hashes are instances of the class Hash.


	print "hello world\n"


[expr `.'] identifier [`(' expr...[`*' [expr]],[`&' ] expr`)']
[expr `::'] identifier [`(' expr...[`*' [expr]],[`&' expr] `)']

Method invocation expression invokes the method of the receiver (right hand side expression of the dot) specified by the identifier. If no receiver specified, self is used as a receiver.

Identifier names are normal identifiers and identifier suffixed by character ? or !. As a convention, identifier? are used as predicate names, and identifier! are used for the more destructive (or more dangerous) methods than the method which have same name without !.

If the last argument expression preceded by *, the value of the expression expanded to arguments, that means


If the last argument expression preceded by &, the value of the expression, which must be a Proc object, is set as the block for the calling method.

Some methods are private, and can be called from function form invocations (the forms that omits receiver).





the super invokes the method which the current method overrides. If no arguments given, arguments to the current method passed to the method.


	foo = bar
	foo[0] = bar
	foo.bar = baz


	variable '=' expr
	constant '=' expr
	expr`['expr..`]' '=' expr
	expr`.'identifier '=' expr

Assignment expression are used to assign objects to the variables or such. Assignments sometimes work as declarations for local variables or class constants. The left hand side of the assignment expressions can be either:

  • variables
    	variables `=' expression

    If the left hand side is a variables, then assignment is directly performed.

  • array reference
    	expr1`[' expr2...`]' `=' exprN

    This from is evaluated to the invocation of the method named []=, with expr1 as the receiver, and values expr2 to exprN as arguments.

  • attribute reference
    	expr `.' identifier `=' expr

    This from is evaluated to the invocation of the method named identifier= with the right hand side expression as a argument.

self assignment   (top▲)


	foo += 12


	expr op= expr     # left hand side must be assignable.

This form evaluated as expr = expr op expr. But right hand side expression evaluated once. op can be one of:

	+, -, *, /, %, **, &, |, ^, <<, >>, &&, ||

There may be no space between operators and =.

Multiple assignment   (top▲)


	foo, bar, baz = 1, 2, 3
	foo, = list()
	foo, *rest = list2()


	expr `,' [expr `,'...] [`*' expr] = expr [, expr...][`*' [expr]]
	`*' expr = expr [, expr...][`*' expr]

Multiple assignment form performs multiple assignment from expressions or an array. Each left hand side expression must be assignable. If single right hand side expression given, the value of the expression converted into an array, then each element in array assigned one by one to the left hand side expressions. If number of elements in the array is greater than left hand sides, they are just ignored. If left hand sides are longer than the array, nil will be added to the locations.

Multiple assignment acts like this:

	foo, bar = [1, 2]	# foo = 1; bar = 2
	foo, bar = 1, 2		# foo = 1; bar = 2
	foo, bar = 1		# foo = 1; bar = nil

	foo, bar, baz = 1, 2	# foo = 1; bar = 2; baz = nil
	foo, bar = 1, 2, 3	# foo = 1; bar = 2
	foo,*bar = 1, 2, 3	# foo = 1; bar = [2, 3]

The value of the multiple assignment expressions are the array used to assign.



As a syntax sugar, several methods and control structures has operator form. Ruby has operators show below:

	high   ::
	       -(unary)  +(unary)  !  ~
	       *  /  %
	       +  -
	       <<  >>
	       |  ^
	       >  >=  <  <=
	       <=> ==  === !=  =~  !~
	       .. ...
	       =(+=, -=...)
	low    and or

Most of operators are just method invocation in special form. But some operators are not methods, but built in to the syntax:

	=, .., ..., !, not, &&, and, ||, or, !=, !~ 

In addition, assignment operators(+= etc.) are not user-definable.

Control structures in Ruby are expressions, and have some value. Ruby has the loop abstraction feature called iterators. Iterators are user-definable loop structure.

if   (top▲)


	if age >= 12 then
	  print "adult fee\n"
	  print "child fee\n"
	gender = if foo.gender == "male" then "male" else "female" end


	if expr [then]
	[elsif expr [then]

if expressions are used for conditional execution. The values false and nil are false, and everything else are true. Notice Ruby uses elsif, not else if nor elif.

If conditional part of if is the regular expression literal, then it evaluated like:

	$_ =~ /re/

if modifier


	print "debug\n" if $debug


	expr if expr

executes left hand side expression, if right hand side expression is true.


	unless $baby


	unless expr [then]

unless expressions are used for reverse conditional execution. It is equivalent to:

	if !(cond)

unless modifier


	print "stop\n" unless valid($passwd)


	expr unless expr

executes left hand side expression, if right hand side expression is false.

case   (top▲)


	case $age
	when 0 .. 2
	when 3 .. 6
	  "little child"
	when 7 .. 12
	when 12 .. 18
	  # Note: 12 already matched by "child"


	case expr
	[when expr [, expr]...[then]

the case expressions are also for conditional execution. Comparisons are done by operator ===. Thus:

	case expr0
	when expr1, expr2
	when expr3, expr4

is basically same to below:

	_tmp = expr0
	if expr1 === _tmp || expr2 === _tmp
	elsif expr3 === _tmp || expr4 === _tmp

Behavior of the === method varies for each Object. See docutmentation for each class.

and   (top▲)


	test && set
	test and set


	expr `&&' expr
	expr `and' expr

Evaluates left hand side, then if the result is true, evaluates right hand side. and is lower precedence alias.

or   (top▲)


	demo || die
	demo or die


	expr `||' expr
	expr or expr

Evaluates left hand side, then if the result is false, evaluates right hand side. or is lower precedence alias.

not   (top▲)


	! me
	not me
	i != you


	`!' expr
	not expr

Returns true if false, false if true.

	expr `!=' expr

Syntax sugar for !(expr == expr).

	expr `!~' expr

Syntax sugar for !(expr =~ expr).


	1 .. 20
	/first/ ... /second/


	expr `..' expr
	expr `...' expr

If range expression appears in any other place than conditional expression, it returns range object from left hand side to right hand side.

If range expression appears in conditional expression, it gives false until left hand side returns true, it stays true until right hand side is true. .. acts like awk, ... acts like sed.

while    (top▲)


	while sunshine


	while expr [do]

Executes body while condition expression returns true.

while modifier


	sleep while idle


	expr while expr

Repeats evaluation of left hand side expression, while right hand side is true. If left hand side is begin expression, while evaluates that expression at lease once.


	until sunrise


	until expr [do]

Executes body until condition expression returns true.

until modifier


	work until tired


	expr until expr

Repeats evaluation of left hand side expression, until right hand side is true. If left hand side is begin expression, until evaluates that expression at lease once.


	[1,2,3].each do |i| print i*2, "\n" end
	[1,2,3].each{|i| print i*2, "\n"}


	method_call do [`|' expr...`|'] expr...end
	method_call `{' [`|' expr...`|'] expr...`}'

The method may be invoked with the block (do .. end or {..}). The method may be evaluate back that block from inside of the invocation. The methods that calls back the blocks are sometimes called as iterators. The evaluation of the block from iterator is done by yield.

The difference between do and braces are:

  • Braces has stronger precedence. For example:
    	foobar a, b do .. end	# foobar will be called with the block.
    	foobar a, b { .. }	# b will be called with the block.
  • Braces introduce the nested local scopes, that is newly declared local variables in the braces are valid only in the blocks. For example:
    	foobar {
    	  i = 20		# local variable `i' declared in the block.
    	print defined? i	# `i' is not defined here.     
    	foobar a, b { .. }	# it is not valid outside of the block

for   (top▲)


	for i in [1, 2, 3]
	  print i*2, "\n"


	for lhs... in expr [do]

Executes body for each element in the result of expression. for is the syntax sugar for:

	(expr).each `{' `|' lhs..`|' expr.. `}'


	yield data


	yield `(' [expr [`,' expr...]])
	yield [expr [`,' expr...]]

Evaluates the block given to the current method with arguments, if no argument is given, nil is used as an argument. The argument assignment to the block prameter is done just like multiple assignment. If the block is not supplied for the current method, the exception is raised.


	raise "you lose"  # raise RuntimeError
	# both raises SyntaxError
	raise SyntaxError, "invalid syntax"
	raise SyntaxError.new("invalid syntax")
	raise		  # re-raise last exception


	raise message_or_exception
	raise error_type, message
	raise error_type, message, traceback

Raises a exception. In the first form, re-raises last exception. In second form, if the argument is the string, creates a new RuntimeError exception, and raises it. If the argument is the exception, raise raises it. In the third form, raise creates a new exception of type error_type, and raises it. In the last form, the third argument is the traceback information for the raising exception in the format given by variable $@ or caller function.

The exception is assigned to the variable $!, and the position in the source file is assigned to the $@.

The word `raise' is not the reserved word in Ruby. raise is the method of the Kernel module. There is an alias named fail.




	[rescue [error_type,..]

begin expression executes its body and returns the value of the last evaluated expression.

If an exception occurs in the begin body, the rescue clause with the matching exception type is executed (if any). The match is done by the kind_of?. The default value of the rescue clause argument is the StandardError, which is the superclass of most built-in exceptions. Non-local jumps like SystemExit or Interrupt are not subclass of the StandardError.

The begin statement has an optional else clause, which must follow all rescue clauses. It is executed if the begin body does not raise any exception.

For the rescue clauses, the error_type is evaluated just like the arguments to the method call, and the clause matches if the value of the variable $! is the instance of any one of the error_type of its subclass. If error_type is not class nor module, the rescue clause raises TypeError exception.

If ensure clause given, its clause body executed whenever beginbody exits.





If retry appears in rescue clause of begin expression, restart from the beginning of the 1begin body.

	  do_something # exception raised
	  # handles error
	  retry  # restart from beginning

If retry appears in the iterator, the block, or the body of the for expression, restarts the invocation of the iterator call. Arguments to the iterator is re-evaluated.

	for i in 1..5
	  retry if some_condition # restart from i == 1
	# user defined "until loop"
	def UNTIL(cond)
	  retry if not cond

retry out of rescue clause or iterators raises exception.


	return 12
	return 1,2,3


	return [expr[`,' expr...]]

Exits from method with the return value. If more than two expressions are given, the array contains these values will be the return value. If no expression given, nil will be the return value.


	while i<3
	  print i, "\n"



Exits from the most internal loop. Notice break does not exit from case expression like C.

next    (top▲)





Jumps to next iteration of the most internal loop.

redo   (top▲)





Restarts this iteration of the most internal loop, without checking loop condition.




	BEGIN '{'

Registers the initialize routine. The block followed after BEGIN is evaluated before any other statement in that file (or string). If multiple BEGIN blocks are given, they are evaluated in the appearing order.

The BEGIN block introduce new local-variable scope. They don't share local variables with outer statements.

The BEGIN statement can only appear at the toplevel.


	END {


	END '{' expr.. '}'

Registers finalize routine. The block followed after END is evaluated just before the interpreter termination. Unlike BEGIN, END blocks shares their local variables, just like blocks.

The END statement registers its block only once at the first execution. If you want to register finalize routines many times, use at_exit.

The END statement can only appear at the toplevel. Also you cannot cancel finalize routine registered by END.


	class Foo < Super
	  def test


	class identifier [`<' superclass ]

Defines the new class. The class names are identifiers begin with uppercase character.


	class << obj
	  def test


	class `<<' expr

Defines the class attribute for certain object. The definitions within this syntax only affect the specified object.


	module Foo
	  def test


	module identifier

Defines the new module The module names are identifiers begin with uppercase character.


	def fact(n)
	  if n == 1 then
	    n * fact(n-1)


	def method_name [`(' [arg ['=' default]]...[`,' `*' arg ]`)']

Defines the new method. Method_name should be either identifier or re-definable operators (e.g. ==, +, -, etc.). Notice the method is not available before the definition. For example:

	def foo
	  print "foo\n"
will raise an exception for undefined method invoking.

The argument with default expression is optional. The evaluation of the default expression is done at the method invocation time. If the last argument preceded by *, actual parameters which don't have corresponding formal arguments are assigned in this argument as an array.

If the last argument preceded by &, the block given to the method is converted into the Proc object, and assigned in this argument. In case both * and & are present in the argument list, & should come later.

The method definitions can not be nested.

The return value of the method is the value given to the return, or that of the last evaluated expression.

Some methods are marked as `private', and must be called in the function form.

When the method is defined outside of the class definition, the method is marked as private by default. On the other hand, the methods defined in the class definition are marked as public by default. The default visibility and the `private' mark of the methods can be changed by public or private of the Module.

In addition, the methods named initialize are always defined as private methods.


	def foo.test
	  print "this is foo\n"


	def expr `.' identifier [`(' [arg [`=' default]]...[`,' `*' arg ]`)']

The singleton-method is the method which belongs to certain object. The singleton-method definitions can be nested.

The singleton-methods of classes inherited to its subclasses. The singleton-methods of classes are acts like class methods in other object-oriented languages.


	alias foo bar
	alias $MATCH $&


	alias method-name method-name
	alias global-variable-name global-variable-name

Gives alias to methods or global variables. Aliases can not be defined within the method body.

The aliase of the method keep the current definition of the method, even when methods are overridden.

Making aliases for the numbered global variables ($1, $2,...) is prohibited. Overriding the builtin global variables may cause serious problems.


	undef bar


	undef method-name

Cancels the method definition. Undef can not appear in the method body. By using undef and alias, the interface of the class can be modified independently from the superclass, but notice it may be broke programs by the internal method call to self.


	defined? print
	defined? File.print


	defined? expr

Returns false if the expression is not defined. Returns the string that describes a kind of the expression.


요리법을 분류 체계별로 나누기

우리가 만든 요리책은 요리법(recipe)과 분류 체계(categories)를 갖게 되었다. 지금은 두개의 테이블이 연결되어 있지 않기 때문에 요리법에 분류 체계를 지정해 주어야 한다. 이것을 하기 위해서는 recipe 테이블에 category id를 추가해야 한다. 또한 요리법 수정 화면에 분류 체계를 선택할 수 있는 drop-down list를 추가해야 한다.

recipe 테이블에 category 테이블의 id와 맵핑하는 int(11) 타입의 category_id 필드를 추가한다.(역자 주 : 원문에서는 int(6) 이나 이 글에서 사용하는 MySQL-Front에서는 int(11) 타입을 id의 기본형으로 만들어 준다.)

그림 48. category_id 필드가 추가된 recipe 테이블

이제는 recipe과 category model을 수정하자 . 각각 c:\rails\cookbook\app\models\recipe.rb 파일과 c:\rails\cookbook\app\models\category.rb 파일을 열어서 아래의 코드를 추가하자. 그림 49, 50을 참조하자.

그림 49. recipe 모델 수정

그림 50. category 모델 수정

위에 추가한 코드는 Rails에게 recipe 테이블은 category 테이블의 하나의 row에 속해야 하며, category 테이블의 row는 n개의 recipe 테이블 row와 관련된다는 것을 알려 준다.

예를 들어 recipe 모델에 해당하는 @recipe 객체를 만들고, @recipe.category.name으로 recipe이 속한 category의 이름을 참조할 수 있다. 반대로 category 모델에 해당하는 @category 객체를 만들고, @category.recipes으로 category에 속한 recipes 집합을 참조할 수도 있다.

recipe 수정 화면에서 category를 선택하려면, recipe action 중에 하나인 edit 함수와 edit 템플릿을 수정해야 한다. 우선 c:\rails\cookbook\app\controllers\recipe_controller.rb 파일을 열어서 그림 51과 같이 수정하자.

그림 51. recipe controller의 새로운 edit 함수

위의 함수에 추가된 두 줄의 코드는 수정할 recipe을 담고 있는 @recipe 객체와, recipe에 부여할 category를 담고 있는 @categories 집합을 생성한다. 여기서 생성된 객체는 view template에 전달되고, html 렌더링에 사용된다.

edit 함수를 작성했으니, 수정에 사용될 edit template을 만들어 보자. c:\rails\cookbook\app\views\recipe 폴더를 열고 edit.rhtml 파일을 만들어서 아래의 내용을 입력하자.

<title>Edit Recipe</title>
<h1>Edit Recipe</h1>

<form action=”../update/<%= @recipe.id %>” method=”POST”">
<input id=”recipe_id” name=”recipe[id]” size=”30″
type=”hidden” value=”<%= @recipe.id %>” />
<input id=”recipe_title” name=”recipe[title]” size=”30″
type=”text” value=”<%= @recipe.title %>” />
<input id=”recipe_description” name=”recipe[description]”
size=”30″ type=”text”
value=”<%= @recipe.description %>” />

<select name=”recipe[category_id]”>
<% @categories.each do |category| %>
<option value=”<%= category.id %>”
<%= ‘ selected’ if category.id == @recipe.category_id %>>
<%= category.name %>
<% end %>

<textarea cols=”40″ id=”recipe_instructions”
rows=”20″ wrap=”virtual”>
<%= @recipe.instructions %>
</textarea> </p>
<input type=”submit” value=”Update” />

<a href=”/recipe/show/<%= @recipe.id %>”>
</a> |
<a href=”/recipe/list” mce_href=”/recipe/list” >


edit 함수에서 만든 @recipe, @categories 객체가 사용되는 방법을 알 수 있을 것이다. <select/> 태그 안에서 사용되는 loop를 살펴 보면, option 태그에서 recipe에 지정된 category를 찾는 방법을 알 수 있다.

웹 브라우저에 입력하고, 분류 항목을 “Ice waters”에서 “Beverages”로 바꾸어 보자.

그림 52. 요리법 항목 바꾸기

다음 단계로 넘어 가기 전에 모든 요리법의 category를 갱신해야 한다. category가 지정되지 않은 요리법이 있으면, 다음 단계에서 에러가 발생하기 때문이다.

요리법 목록에 분류 체계 보여 주기

c:\rails\cookbook\app\views\recipe\list.rhtml 파일을 아래와 같이 수정하자.

<title>All Recipes</title>

<h1>Online Cookbook - All Recipes</h1>
<table border=”1″>
<td width=”40%”><p align=”center”><i><b>Recipe</b></i></td>
<td width=”20%”><p align=”center”><i><b>Category</b></i></td>
<td width=”20%”><p align=”center”><i><b>Date</b></i></td>

<% @recipes.each do |recipe| %>
<td><%= link_to recipe.title, :action => “show”, :id => recipe.id %></td>
<td><%= recipe.category.name %></td>
<td><%= recipe.date %></td>
<% end %>
<p><%= link_to “Create new recipe”, :action => “new” %></p>


웹 브라우저에를 입력하자. 아래의 그림과 같이 출력되는가?

그림 53. 분류 체계가 표시되는 요리법 리스트


뭔일이 생긴겨?

scaffold :recipe 이 한 줄이 모든 걸 가능하게 만들었다. 이 코드는 데이터 모델과 작동하고, show 내용 출력, list 목록 출력, create 새로 만들기, delete 삭제 action을 만들었다. 또한 각각의 action(show, list, create, delete)의 view 템플릿을 만들었다.

물론 자동 생성된 action과 view는 여러분의 마음에 들지 않겠지만, 액션을 하나씩 추가할 때마다 기본으로 제공되는 scaffold 액션을 대신한다. 마지막으로 모든 action을 추가했을 때, scaffold를 코드에서 지우면 된다.

Rails에서 사용하는 URL에 눈여겨 보았는가? 매우 단순하지 않은가? Rails는 URL을 보기 좋게 만들기 위해서 많은 신경을 썼다.

Action과 View 만들기

우선 요리 목록을 출력하는 action을 수정해 보자. 목록 출려과 관계된 action은 list이다.

recipe_controller.rb를 열어서 list 함수를 추가하자(그림 40)

그림 40. list 함수 추가

함수를 추가한 후를 웹 브라우저에 입력해 보자. 그림 41과 같이 보이나?

그림 41. list 함수 추가 후 목록 action 수행 결과(역주 : Rails 버전이 다르기 때문에 에러 메시지가 다소 다르게 보임)

list 액션을 추가했기 때문에 Rails는 더 이상 list scaffold를 사용하지 않는다. 따라서 Rails는 새로 만든 list 함수를 호출하고 여기에 대응하는 view 템플릿을 부른다. 하지만 list함수만 만들고 view 템플릿을 만들지 않았기 때문에 “Template is missing”이라는 에러 메시지를 출력한다.

list.rhtml 파일을 c:\rails\cookbook\app\views\recipe 폴더에 만든다. JSP나 ASP에 경험이 있다면 <% %>, <%= %> 태그 안에 Ruby 코드가 들어가는 걸 눈치 챘을 것이다. list.rhtml에 아래의 내용을 입력한다.

<title>All Recipes</title>

<h1>Online Cookbook - All Recipes</h1>
<table border=”1″>
<td width=”80%”><p align=”center”><i><b>Recipe</b></i></td>
<td width=”20%”><p align=”center”><i><b>Date</b></i></td>

<% @recipes.each do |recipe| %>
<td><%= link_to recipe.title, :action => “show”, :id => recipe.id %></td>
<td><%= recipe.date %></td>
<% end %>
<p><%= link_to “Create new recipe”, :action => “new” %></p>


recipe_controller.rb 파일에 그림 42의 코드 한 줄을 추가한다.

그림 42. 모든 요리법 목록을 출력

웹 브라우저를 Refresh하면 그림 43이 출력된다.

그림 43. 더 나아진 요리법 출력 목록

잘 어떻게 잘 작동하는지 알아 보자.

def list
@recipes = Recipe.find_all

웹 브라우저에를 입력하면, Rails는 방금 만든 list 함수를 호출한다. 위에 추가한 코드는 recipes 테이블에 있는 모든 row를 Recipe 클래스로 가지고 와서 @recipes 변수에 저장한다.

그 다음으로 Rails는 템플릿을 찾고, 우리가 만든 템플릿에 데이터를 넘겨준다. 템플릿은 대부분 HTML이다. 아래의 태그에서 작업이 이루어진다.

<% @recipes.each do |recipe| %>
<td><%= link_to recipe.title, :action => “show”, :id => recipe.id %></td>
<td><%= recipe.date %></td>
<% end %>

삽입된 Ruby 코드는 controller에서 얻은 배열의 값을 하나씩 가지고 온다. 각 열의 첫 번째 cell은 요리법의 show, 세부 내용 조회 페이지에 연결된다.

요리책에 분류 체계 추가 하기

요리책에 분류 체계를 추가하고 싶다. 이를 위해서 데이터 베이스에 categories, 분류 체계 테이블을 추가한다. 모든 요리법은 하나의 분류 체계에 속하게 된다.

MySQL-Front에 categories 테이블을 추가하고, varchar(50)의 name 필드를 추가한다.(그림 44)

그림 44. categories 테이블

categories 테이블에 맵핑되는 controller와 model을 만들자.

ruby script\generate controller Category
ruby script\generate model Category

그림 45. category controller와 model 만들기

마지막으로, category controller에 scaffold 코드를 추가하자. 그림 46을 참조하자.

그림 46. scaffold 코드 추가

웹 브라우저에를 입력하고, Snacks와 Beverages 분류 체계를 추가하자. 그림 47와 같은 결과를 얻을 수 있다.

그림 47. 분류 체계 항목 목록

recipes(요리법) 테이블 만들기

요리법을 담고 있는 데이터 테이블을 만들자.

MySQL-Front의 왼쪽 창에 마우스 오른쪽 버튼을 클릭한다. 팝업 메뉴의 New>Table… 메뉴를 선택한다. (그림 21, 역주 : MySQL-Front 버전에 따라서 다른 그림일 수 있음.)

그림 21. 신규 테이블 생성

테이블 이름을 recipes으로 입력(그림 22)

그림 22. 신규 테이블 추가 다이얼로그

주의 사항 : MySQL-Front는 Id라는 이름으로 프라이머리 키를 생성한다. 그러나, Rails에서는 id로 인식하기 때문에 프라이머리 키 값을 변경해야 한다. 왼쪽 창에서 recipes 테이블을 선택한 후 오른쪽 창에서 Id 프라이머리 키 값을 id로 바꿔 준다.(그림 23 참조)

역자 주 : 그러나 번역 시 설치한 MySQL-Front 버전(3.2 빌드 9.14)에서는 프라이머리 키 이름을 id로 생성하기 때문에 위 문단은 생략해도 무방하다.

그림 23. 프라이머리 키 이름 바꾸기

Recipes 테이블에 필드 추가하기

여러가지 필드를 추가해야 하나, 여기서는 요리법의 이름과 방법(title, instructions) 필드만 추가하자. 뒤에서 다른 나머지 필드를 추가할 것이다.

recipes 테이블을 선택한 상태에서, 오른쪽 창에서 마우스 오른쪽 버튼을 클릭한 후 메뉴 New>Field…를 선택하자.(그림 24)

그림 24. 새 필드 추가하기

새로 추가하는 필드는 요리법 title(제목)으로 varchar(255)에 null을 허용하지 않는다.(그림 25 참조)

그림 25. title 필드 추가하기

동일한 방법으로 text 타입의 instructions(요리 방법) 필드를 생성한다.(그림 26)

그림 26. instructions 필드 추가하기

두 개의 필드를 추가된 recipes 테이블은 그림 27과 같다.

그림 27. recipe 테이블

즐거움이 시작되다~

다소 지루한 데이터베이스 작업은 이제 끝났다. 이제 요리책 application을 가동시켜서 요리법을 작성할 시간이다.

모델 만들기

우선 Recipe(요리법) 모델을 만들어야 한다. 이 Recipe모델은 recipes 테이블의 데이터를 가지고 올 것이다. 그림 28에서 Recipe 모델이 위치한 곳을 확인할 수 있다.

역자 주 : models 클래스는 application 폴더(여기서는 c:/rails/cookbook)의 app/models 폴더에 위치한다.

그림 28. Recipe 모델 클래스

새로운 명령창(Command window)를 열고 c:/rails/cookbook에서 아래의 명령어를 입력한다.

ruby script\generate model Recipe

위의 명령어는 recipe.rb 파일을 생성하는데, 이 파일은 Recipe 클래스를 정의하는 뼈대를 담고 있다. 이 파일에 마우스 오른쪽 버튼을 클릭한 후 edit 메뉴를 선택하면 그림 29의 클래스 정의를 확인할 수 있다.

그림 29. recipe.rb 파일의 내용

뭔가 이상한걸 눈치 채지 못했는가? 여기서 만든 테이블 이름은 recipes 였다. 그런데 모델로 만들 클래스의 이름은 Recipe이였다. 즉 테이블은 요리법들(역자 주 : recipes이기 때문에 복수형이다. 구지 원어 가깝게 표현하면)이고 테이블의 하나의 데이터를 가지고 오는 모델은 요리법(역자 주 : Recipe 단수형이다.)이다. 즉 Rails는 똑똑해서 이런 영어의 단수와 복수의 차이를 테이블과 모델 클래스에 연결해 준다. 즉 Company(클래스)는 companies(테이블)에 연결 시키고, person(모델)은 people 테이블에 연결 시킨다.

데이블과 모델 클래스와 어떻게 작동하는지 살펴 보기 위해서, controller를 만들어야 한다. 이 controller는 CRUD(create 생성, read 읽기, update 수정, delete 삭제) 작업을 하다. Rails는 이 controller도 무지 간단하게 만들어 준다.

그림 30. Recipe controller를 확인할 수 있다.

다시 명령창을 하나 띄워서, 아래의 명령을 입력하자.

ruby script\generate controller Recipe

위 명령은 RecipeController 클래스를 담고 있는 recipe_controller.rb 파일을 생성해 준다. 이 파일을 열고 그림 31과 같이 scaffold :recipe를 입력하자.

그림 31. RecipeController의 한 줄 코드

이 한 줄의 코드가 테이블에 생명을 불어 넣는다. 너무나 신기하다. 그럼 즉시 확인해 보도록 하자!

웹 브라우저를 열고, 입력해 보자. 그럼 그림 32와 같은 화면을 볼 수 있다.

그림 32. 새로운 요리법을 입력 받는 Page

죽이지 않는가? 한 것도 별로 없는데 데이터베이스에 값을 입력할 수 있다. 잠깐~ 여기서 두 개의 필드를 더 추가해 보도록 하겠다.

MySQL-Front를 이용해서, title과 instructions 사이에 description과 date 필드를 추가하자.

그림 33. description 필드 추가

그림 34. date 필드 추가

필드 추가 후, 웹 브라우저를 refresh하면 아래의 그림 35의 결과를 얻을 수 있다.

그림 35. 신규 필드 추가 후, 변화된 요리법 입력 화면

다시 한번 죽이지 않는가? 단지 테이블에 필드만 추가했을 뿐인데 말이야…

자! 진정하고 좋아하는 요리법을 입력하고 create 버튼을 눌러 보자.(그림 36)

그림 36. 신규 필드 추가 후, 변화된 요리법 입력 화면

그럼 37의 화면을 볼 수 있다.

그림 37. 모든 요리법 출력 화면

New recipe 링크를 클릭해서, 다른 요리법을 입력할 수 있다.

그림 38. 또 다른 요리법 입력하기

create 버튼을 누르면 방금 입력한 요리법이 추가된 것을 알 수 있다.(그림 39)

그림 39. 요리법 리스트

자~ 정리하면. 우리가 지금까지 했던 작업은 테이블 만들기, 스크립트 실행하기(두 개) 그리고 한 줄의 코드 추가 하기 였다. 이 작업만으로도 우리는 요리법을 추가, 조회, 삭제할 수 있는 이 모든 코드를 얻었다.

진짜~ 놀랍지 않은가?

코딩 하기

모든 사람들이 좋아하는 요리법을 공유하는 온라인 요리책을 만들 것이다. 온라인 요리책은 다음과 같은 기능을 가지고 있다.

  • 요리법 리스트 출력
  • 새로운 요리법을 만들거나, 기존의 요리법을 수정함
  • 요리법을 분류함

    지금 만들 요리책 application은 아무 directory에나 만들어도 된다. 여기서는 c:\rails\cookbook에 만든다.

    여기서 이 예제의 모든 파일을 다운로드 할 수 있다. cookbook/db/ directory에는 데이터베이스를 다시 생성할 수 있는 파일이 있다.

    비어 있는 Rails Web Application 만들기

    Rails는 runtime 웹 어플리케이션 프레임웍과 자동화 helper script의 집합이다. 요리책 어필리케이션을 시작하기 위해서, 첫번째로 전체 디렉토리와 파일을 만드는 helper script를 사용한다.

    1. 명령창(Command Window)을 열고 요리책을 만들 디렉토리로 이동한다. 여기서는 c:\rails를 사용한다.
    2. 다음 명령을 실행시킨다.

    rails cookbook

    역자 주 : rails cookbook을 실행 시켰을 때 “‘rails’은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는 배치 파일이 아닙니다.”라는 에러가 발생할 때는 아래의 순서로 조치하시면 됩니다.
    1. “set path” 명령을 쳐서 path에 “c:/ruby/bin” 디렉토리가 추가 되어 있나 확인한다.
    2.”c:/ruby/bin” 디렉토리가 없을 때는 “내컴퓨터→속성→고급→환경변수→시스템” path 환경변수에 디렉토리를 추가한다.
    3. 명령창을 다시 띄워서 “rails cookbook”을 입력한다.
    4. 그래도 안되는 경우 rebooting한다. 윈도우즈 버전에 따라서 reboot해야 환경 변수가 반영된다.
    5. rebooting 후에도 안되면 “c:/ruby/bin” 폴더에 rails.cmd 파일이 있는지 확인한다. 1~4의 과정을 밟아 왔는데도 rails.cmd 파일이 있다면 역자도 그 원인을 모르겠다.
    6. rails.cmd가 없다면 다행이다. rails.cmd가 없다는 것은 install이 잘못된 것이다. “gem uninstall rails” 명령어를 입력하면 uninstall된다. uninstall 후 “gem install rails” 입력해서 다시 설치한다.
    7. 재설치 후 rails.cmd 파일이 있는지 확인한다. 이래도 rails.cmd 파일이 없는 경우에는 필시 Ruby 버전이 1.8.2-15 아니라 그 이하 버전이 설치되었기 때문이다. 으~ 어쩌라~ 역자가 앞의 post에서 반드시 1.8.2-15 설치하라고 얘기했음을 잘 안 본 것이다. 설치된 Ruby 버전을 삭제하고 1.8.2-15를 설치하도록!

    이 명령어는 rails 폴더 아래에 cookbook이라는 하위 폴더를 만들고, 비어있는 application을 생성한다.

    그림 6. 생성된 Rails application 폴더

    새로 만든 application을 테스트 하기 위해서 web server를 실행해야 한다. Rails는 어떤 웹서버에서도 실행이 된다. 여기서는 내장되어 있는 WEBrick web server를 사용한다.

    1. 명령창을 띄우고, 해당 application 폴더로 이동한다.
    2. 아래의 명령을 실행한다.

    ruby script\server

    그림 7과 같이 web server가 실행되는 것을 확인할 수 있다.

    웹 브라우저를 실행시키고 주소창에 입력한다. 그림 8의 내용이 브라우저에 출력되면 일단은 성공.

    그림 7. WEBrick web server 실행 상태

    명령창이 열려 있는 한 웹 서버가 동작한다. 진행을 위해서 명령창을 그대로 두도록.

    그림 8. Rails의 기본 페이지

    Rails 어플리케이션의 디렉토리 구조

    Rails는 개발자의 불필요한 작업과 결정 사항을 최소화하기 위해서 매우 노력했다. Rails의 helper 스크립트를 사용하면 그림 9.의 디렉토리 구조가 생성된다. 설정 파일이 필요 없음을 명심 해라!

    그림 9. Rails 어플리케이션의 디렉토리 구조

    c:\rails\cookbook\app 하위 폴더에서 파일을 만들거나 수정한다. 각 폴더마다 어떻게 사용되는 간략히 살펴 보자

  • controllers 폴더 : Rails는 사용자의 요청을 다루는 controller 클래스를 이 폴더에서 찾는다.
  • views 폴더 : 템플릿 보관했다가 application 데이터를 이용해서 HTML로 변환한다.
  • models 폴더 : application의 데이터베이스에 데이터를 저장해 둔다. 대부분의 프레임웍에서 model에 해당하는 클래스는 매우지저분하고 정신없지만, Rails는 너무나도 간단하다.
  • helpers 폴더 : model, view, controller를 도와주는 helper 클래스를 담고 있다.

    Controllers와 URLs

    곧, 요리책 데이터베이스와 Application을 만들 것이다. 그 전에 controller와 URL이 어떻에 mapping되서 작동하는지 알아 보자.

    Controller는 사용자로부터 요청을 처리한다. URL의 요청은 controller 클래스와 클래스 안의 함수와 연결되어 있다. 그런데 어떻게 작동하지?

    일단 웹서버가 작동하는 명령창은 가만히 두고, 새로운 명령창을 실행 시키자. application 폴더의 controllers 폴더를 열어 보면 그림 10과 같은 두 개의 파일이 존재하는 것을 확인할 수 있다.

    그림 10. 요리책의 controller 폴더(역자 주 : 번역하는 시점에 Rails 최신 버전은 rails (0.14.3)이다. 따라서 그림의 abstract_application.rb 파일은 application.rb 파일로 이름이 바뀌었다.)

    controller 클래스를 만들기 위해서는 helper script를 사용해야 한다. 명령창에 아래 명령을 실행 시키자.

    ruby script\generate controller MyTest

    역자 주 : 위의 명령어는 c:\rails\cookbook 폴더에서 실행해야 한다.

    이 명령은 my_test_controller.rb 이름의 파일이 생성된다. 이 파일은 MyTestController 클래스의 skeleton이다.

    앞에서 만들어진 파일을 오른쪽 마우스 버튼을 클릭하면, 그림 11과 같은 편집기가 출력된다.

    그림 11. MyTestController 수정하기

    존재 하지 않는 페이지를 입력해 보자. 예를 들어 입력해 보자. 아래의 그림과 같은 메시지를 확인할 수 있다.

    그림 12. 존재하지 않는 controller를 브라우징 할 때(역자 주 : rails (0.14.3) 버전에서는 다른 메시지가 출력된다.)

    방금 만든 controller를 입력해 보자. 입력해 보자. 아래의 그림과 같은 메시지를 확인할 수 있다.

    그림 13. 새로 만든 controller를 브라우징 할 때

    URL의 MyTest 부분이 새로 만든 controller와 연결된다. 그림 13의 메시지를 확인해 보면 index라는 액션을 찾지 못한다는 뜻인거 같다.

    자~ index라는 액션을 추가해 보자. 그림 14와 같다.

    그림 14. MyTestController의 index 함수

    웹 브라우저를 refresh해 보자. 그럼 그림 15와 같은 내용이 출력될 것이다.

    그림 15. index 함수의 결과를 입력해도 그림 15와 같은 동일한 결과를 얻을 수 있다.

    새로운 dilbert라는 새로운 함수를 추가해 보자. 그림 16과 같다.

    그림 16. dilbert 함수

    웹 브라우저에를 입력해 보자. 그림 17의 결과를 얻을 수 있다.

    그림 17. dilbert 함수의 결과

    요리책 데이터베이스 만들기

    요리책에 사용할 데이터베이스를 만들고, Rails에 데이터베이스 연결을 설정해야 한다.(Rails에서 사용하는 유일한 설정 부분이다.)

    1. MySQL-Front를 실행하자. MySQL 서버에 root 계정(비밀번호 없음)으로 로그인하자. 그림 18과 동일한 화면을 확인할 수 있다.

    그림 18. MySQL-Front(역자 주 : MySQL-Front의 버전에 따라서 그림이 다소 다름.)

    2. 두 개의 데이터베이스가 있는 것을 확인할 수 있다. (mysql, test) cookbook에 사용할 새로운 데이터베이스를 만든다. 메뉴 Database>New>Database… 를 선택하면 그림 19의 신규 데이터베이스 생성 창이 생성된다.

    그림 19. 신규 데이터베이스 생성

    OK버튼을 클릭하면, 신규 데이터베이스가 생성된다.

    3. 데이터베이스 연결 설정을 해주어야 한다. c:\rails\cookbook\config\database.yml 파일을 열고, 그림 20과 같은 설정을 입력하자.

    그림 20. database.yml에 DB 설정(역자 주 : Rails 버전에 따라서 세부적인 설정내용이 차이날 수 있음. 대세에는 지장이 없음.)

    Rails는 development, test, production 모드를 다르게 설정할 수 있지만, 여기서는 모두 동일하게 설정한다. 신규 데이터베이스를 반영하기 위해서는 기존 웹서버를 종료하고, 다시 시작해야 한다

  • Ruby란?

    Ruby의 장점

  • Smalltalk의 우아함(개념 측면에서)
  • Pytohon처럼 쉽게 배우고, 쓸 수 있음
  • Perl의 실용성


    Rails는 데이터베이스 지원하는 웹 프로그램 개발용 Open source다. Java 프레임웍을 사용하는 것보다 10배 정도 빠르게 개발할 수 있다고 생각한다. 그럼에도 불구하고, 동일한 품질 수준을 달성할 수 있다.

    역자 주 : 이 10배라는 문장에 주목해야 합니다. Rails 글을 읽다 보면 항상 나오는 문구입니다만, 진짜 10배 정도 빨라진다고 합니다. 그러나 제 생각엔 Rails에 어느 정도 익숙해진 다음에 가능한 수치인거 같습니다. 느껴 보시길…

    Ruby는 다른 언어와 비교해 보았을 때 보다 더 쉽게 프로그램을 개발할 수 있다. Rails는 이런 Ruby의 장점을 모두 포함한다. Rails는 두가지 정도의 장점이 있다.

    Less Software : 훨씬 적은 코드로 applcation을 구축할 수 있다. 즉 더 적은 버그를 가지고 있는 더 작고(코드 크기) 더 빠르게 만들 수 있다. 따라서 코드도 작고 버그도 적기 때문에 유지보수도 매우 쉬워진다.

    Convention over configuration : XML 설정 파일을 설정할 필요가 없다. 즉 Rails에서는 설정 파일 대신, 간단한 프로그래밍 규칙을 이용한다.


    새로운 기술이 선보일 때마다 과대 선전을 하기 때문에, 이 글을 읽는 개발자들은 거짓말이라고 생각할 수 있다. 그러나 진짜로 10배 빨리 개발할 수 있다. 맹신 하라는게 아니다. 일단 보고 나서 믿도록!

    소프트웨어 설치

    우선 필요한 프로그램을 설치하자. 윈도우즈 기준으로 예제를 설명할 것이기 때문에 리눅스나 맥은 설명하는 것과는 다른 화면이 출력될 수 있다. 다른 os관련 resource는 예제의 끝머리에 링크를 달아 둘 것이다.

    Step 1 : Ruby 설치하기

    그림 1. Ruby 윈도우 설치 프로그램

    Ruby를 설치하는 것은 매우 간단하다.

    1. 윈도우즈용 One-Click Ruby 설치 프로그램(그림 1)을 다운로드 한다.

    역자 주 : 반드시 1.8.2-15 버전을 설치해야 한다. 1.8.2-15 아래 버전에서는 Rails가 제대로 설치 안된다. 반드시 1.8.2-15 버전을 설치하도록~

    2. 다운로드 파일을 더블 클릭해서 실행시킵니다. 별다른 설정없이 계속 enter키를 입력하면 설치가 완료 된다.

    Note : 윈도우즈 버전인 경우 RubyGems 패키지도 설치되나, 리눅스와 OS X 사용자는 RubyGems도 설치해야 한다.

    Step 2 : Rails 설치하기

    그림 2. RubyGems를 이용하여 Rails 설치함

    1. 작업창(Command Window)를 실행한 후, prompt 상에 gem install rails - -remote를 입력한다.
    2. RubyGems는 Rails와 관련된 library를 설치한다. RubyGems는 각 단계마 설치를 물어볼텐데, 이 때 항상 “y”(Yes)를 입력한다.

    Step 3 : MySQL 설치하기

    그림 3. MySQL 서버 설정 마법사

    Rail은 여러 종류의 데이터베이스를 지원하나, 여기서는 MySQL을 사용하겠다.

    1. MySQL 윈도우즈 설치 프로그램을 다운로드한다. 여기서는 “essential” 버전을 다운로드 한다.(이 글을 쓰는 시점의 최신 버전은 4.1.7이다. 역자 주:번역하는 시점에는 4.1.15가 최신 버전이다.)
    2. 그림 3의 설치 프로그램을 더블 클릭한다. 기본 설정을 선택한다. mysql.com의 계정 생성은 생략한다.
    3. 설치 마법사가 완료되면 ‘Finish’ 버튼을 클릭한다. 설정 마법사가 생성된다.
    4. 보안 창에서 “Modify Security Settings” 항목을 체크하지 않는다.(그림 4) 나머지 탭에서는 기본 설정을 유지한다. “Modfiy Security Settings” 항목을 체크하지 않는 이유는, 4.1.7버전이 새로운 권한 알고리즘을 채용해서, 하위 클라이언트 버전과 호환되지 않기 때문이다. (Rails도 여기에 해당함) 항목을 체크하지 않으면 패스워드 없이 MySQL에 접근할 수 있다.

    그림 4. MySQL 설정 마법사

    Step 4 : MySQL-Front 설치하기

    MySQL-Front는 MySQL GUI 툴이다. 비싸지는 않지만 상업용 프로그램이기 때문에 30일 동안만 무료로 사용할 수 있다. 30일 이후에는 돈을 내고 사용해야 한다. 이 문서에서는 데이터베이스 구축용 툴로써 MySQL-Front를 사용할 것이다.

    역자 주 : SQLyog라는 툴은 공짜임. 여기서 다운로드 할 수 있습니다.

    1. MySQL-Front 최신 버전을 다운로드한다.(현재 최신 버전은 3.1, 역자 주 : 번역 시 최신 버전은 3.2)
    2. 다운로드한 설치 프로그램을 더블클릭하면, 그림 5 MySQL-Front 설치 프로그램이 실행된다. 별 다른 설정 사항이 없는 한 기본 설정으로 설치한다.

    그림 5. MySQL-Front 설치 프로그램

  • 설치순서

    1) Cygwin 설치하기 루비 버전 포함해서 설치
    daum@KOyoungmin ~/cookbook
        $ ruby -v
        ruby 1.8.5 (2006-08-25) [i386-cygwin]

    $ tar xzvf rubygems-0.9.0.tar.gz
    $ cd rubygems-0.9.0
    $ su -
    # ruby setup.rb

    2) gem을 이용한 rails 설치하기   (온라인이 안되는곳 에서 다른방법 있음.)
    daum@KOyoungmin ~/cookbook$ cd c:\temp
    daum@KOyoungmin ~/cookbook$ gem install rails
             Successfully installed rails-1.1.6
    daum@KOyoungmin ~/cookbook$ rails -v
             Rails 1.1.6

    3) gem을 이용한 mysql 설치하기
    daum@KOyoungmin ~/cookbook$ cd c:\temp
    daum@KOyoungmin ~/cookbook$  gem install mysql
     Need to update 15 gems from
     Select which gem to install for your platform (i386-cygwin)
      1. mysql 2.7.1 (mswin32)
      2. mysql 2.7 (ruby)
      3. mysql 2.6 (ruby)
      4. mysql 2.5.1 (ruby)
      5. Cancel installation
     > 2
     Building native extensions.  This could take a while...
     *** extconf.rb failed ***
     Could not create Makefile due to some reason, probably lack of
     necessary libraries and/or headers.  Check the mkmf.log file for more
     details.  You may need configuration options.

     Provided configuration options:
                        중략!! 중략!!! 중략!! 중략!!

     ERROR:  While executing gem ... (RuntimeError)
         ERROR: Failed to build gem native extension.
     Gem files will remain installed in /usr/lib/ruby/gems/1.8/gems/mysql-2.7 for ins

     Results logged to /usr/lib/ruby/gems/1.8/gems/mysql-2.7/gem_make.out
    daum@KOyoungmin /var/run$

    4) 신규 rails package생성하기
    daum@KOyoungmin ~$ rails blogtest
          create  app/controllers
          create  app/helpers
          create  app/models
          create  app/views/layouts
          create  config/environments
          create  components
            중략!! 중략!!! 중략!! 중략!!
          create  doc/README_FOR_APP
          create  log/server.log
          create  log/production.log
          create  log/development.log
          create  log/test.log

    5) rails package 구동하기
    daum@KOyoungmin ~/$ cd neouserTest
    daum@KOyoungmin ~/neouserTest$ script/server (서비스 3000번 포트로 구동!!)
          => Booting WEBrick...
          => Rails application started on ttp://
          => Ctrl-C to shutdown server; call with --help for options
         [2006-12-18 18:22:20] INFO  WEBrick 1.3.1
         [2006-12-18 18:22:20] INFO  ruby 1.8.5 (2006-08-25) [i386-cygwin]
         [2006-12-18 18:22:20] INFO  WEBrick::HTTPServer#start: pid=4948 port=3000

        브라우져에서 확인 가능 (

    6) 모델 / 컨트롤러 생성하기
     > script/generate model article
     > script/generate controller  article

    잘 모르면 하루작업이지만 글쎄.. 가이드데로 한다면 10분안에도 끝날 수 있을것 같다.

    Cygwin (http://www.cygwin.com/)
      > 본 파일은 windows상에서 유닉스와 같은 명령어를 입력 할 수있도록 하는 tool에 해당한다.
      > 루비작업을 원할하게 하기 위해서는 본 파일을 다운로드 하도록 한다.
      > 설치할때 설치할 package에 대해서 물어보는데 이때 루비와 gcc를 꼭 설치하도록 한다.

    gVim (http://vim.sourceforge.net/)
      > 본 파일은 viEdit를 가능하게 하는 파일이다.  (text edit 도구)
      > 루비에서 생성되는 파일에 대해서 vi로 편집을 수행하도록 한다.

    gem (http://rubyforge.org/frs/?group_id=126&release_id=5803) rubygems-0.9.0.zip
      > gem은 루비 팩키지를 제공하는 사이트이다.
      > 이점에 있어 gem을 다운받아 설치한다는것은 루비의 모든 팩키지를 지원 받을 수 있다.
      > 본 과정의 목적은 gem을 통해 레일즈 (rails)를 설치하는데 그 목적이 있다.

    2007년01 버전이라 또 얼마나 향상된 버전이 나와있을지 모르지만 이정도도 가쁜하다.

    글 보관함


    Total : 600,029 / Today : 5 / Yesterday : 114
    get rsstistory!