[RoR] Rails-flavored Ruby

Rails 에서는 Ruby 중 일부를 사용할 수 있다.

아래는 application.css 파일을 link하는 것이다. 일단 이건 뒤에서 다시 보자.

1
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>

String and Method

  • 주석은 # 으로 처리한다.
  • String은 "" 으로 처리하며 다음과 같은 연산들이 가능하다. '' 도 가능하지만 single quotation은 interpolation 기능을 지원하지 않는다.
  • interpolation은 #{ } 를 통해 변수를 따옴표 안에서 사용할 수 있는 기능이다.
    1
    2
    3
    4
    5
    6
    7
    8
    >> "foo" + "bar"
    >> first_name = "Michael"
    >> "#{first_name} Hartl" #interpolation
    >> first_name + "Hartl"
    >> "foobar".length #get length
    >> "foobar".empty? #true/false
    >> "foobar".nil? #true/false
  • print는 puts "foo" 의 방식으로 한다.
  • if문은 다음과 같은 방식으로 사용한다. &&, ||, ! 으로 논리식을 표현한다.
    1
    2
    3
    4
    5
    6
    7
    8
    if s.nil?
    "abc"
    elseif s.empty?
    "def"
    else
    "gkl"
    end
  • 아래 방식으로 출력문에 조건문을 더할 수도 있다.
    1
    2
    3
    x = "foo"
    puts x if !x.empty?
  • String으로 변환은 abc.to_s 으로 가능하다.
  • if문 대신 unless문을 사용할 수 있는데, if는 조건이 true일 때 실행되고 unless는 조건이 false일 때 실행된다.
    1
    2
    3
    x = "foo"
    puts x unless x.empty?

Method definitions

  • method 선언의 간단한 예이다. method 호출 시 parameter가 하나 있으면 str에 들어가고 없으면 기본 값으로 ''를 사용한다.

    1
    2
    3
    4
    5
    6
    7
    def string_message(str = '')
    if str.empty?
    "empty string"
    else
    "not empty string"
    end
  • Ruby 함수는 implicit return을 지원한다. 한 statement의 마지막에 있는 것을 return한다. return을 기입하는 explicit return 역시 지원한다.

    1
    2
    3
    4
    5
    def string_message(str = '')
    return "abc" if str.empty?
    return "nonempty"
    end
  • Array는 다음과 같이 편하게 생성할 수도 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    >> "foo bar baz".split # ["foo", "bar", "baz"]
    >> "fooxbarxbazx".split('x') # ["foo", "bar", "baz"]
    >> a = [42, 8, 17]
    >> a[0] # 42
    >> a[-1] # 17
    >> a.first
    >> a.second
    >> a.last
    >> a.length
    >> a.empty?
    >> a.include?(3) # true
    >> a.sort # [8, 17, 42]
    >> a.reverse # [17, 8, 42]
    >> a.shuffle # [17, 42, 8] 이건 랜덤으루다가.
    >> a # [42, 8, 17] 변하지 않음
    >> a.sort! # [8, 17, 42]
    >> a # [8, 17, 42] 변했음
    • 위에서 !Bang method라 한다.

    • << 연산자를 통해 배열에 새로운 아이템을 넣을 수 있다.

      1
      2
      3
      4
      >> a.push(5) # [42, 8, 17, 5]
      >> a << 7 # [42, 8, 17, 5, 7]
      >> a << "foo" << "bar" # [42, 8, 17, 5, 7, "foo", "bar"]
  • .. 을 통해 range를 나타낼 수 있다. to_a 는 array를 생성해 준다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >> 0..9
    >> 0..9.to_a # error. 이건 9.to_a 와 같다.
    >> (0..9).to_a # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >> a = %w[foo bar baz quux] # %w 는 string array를 만들어 준다.
    >> a[0..2] # ["foo", "bar", "baz"]
    >> a[2..(a.length-1)] # [2, 3, 4, 5, 6, 7, 8, 9]
    >> a[2..-1] # [2, 3, 4, 5, 6, 7, 8, 9]
    >> ('a'..'e').to_a # ["a", "b", "c", "d", "e"]
  • Ruby의 강력한 기능 중 하나인 Block은 다음과 같다.

    1
    2
    >> (1..5).each { |i| puts 2 * i } #2 4 6 8 10 이 출력된다.
  • |i|Block variable 이라고 부른다. { } 를 사용하지 않고도 같은 효과를 낼 수 있다.

    1
    2
    3
    4
    (1..5).each do |i|
    puts 2 * i
    end
  • 보통 Rails에서는 one-line일 때에는 block을 사용하고 multi-line일 때는 do..end 구문을 사용한다.

  • map 메소드를 통해 다음과 같은 변환도 가능하다.

    1
    2
    3
    4
    5
    >> 3.times { puts "abc" } # abc를 세 번 출력
    >> (1..5).map { |i| i**2 } # [1, 4, 9, 16, 25]
    >> %w[a b c].map { |char| char.upcase } # [A, B, C] 로 바뀜
    >>
  • join 메소드는 배열을 하나의 String으로 변환시켜준다. 아래 코드는 a ~ z 중 임의의 8가지 문자로 배열을 생성하고 이를 합쳐서 하나의 String으로 만들어준다.

    1
    2
    >> ('a'..'z').to_a.shuffle[0..7].join
  • 다음과 같이 hash를 사용할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >> user = {} # empty hash
    >> user["first"] = "Michael" # Key : first , Value : Michael
    >> user["last"] = "Hartl" # Key : last , Value : Hartl
    >> user["first"] # return "Michael"
    >> user # return {"last"=>"Hartl", "first"=>"Michael"}
    # 처음부터 이렇게 선언도 가능함. => 를 "hashrocket" 이라 부른다.
    >> useruser = {"first"=>"Michael", "last"=>"Hartl"}
  • Ruby에서의 symbol은 :name 처럼 콜론으로 시작한다. 숫자로 시작할 수 없고 dash ‘-‘ 를 사용할 수 없다. hash에서 다음과 같이 사용할 수 있다.

  • Ruby에서는 hash끼리의 비교도 가능하다. hash A, B 가 있을 때 ‘A == B’ 식으로…

    1
    2
    3
    4
    >> user = { :name=>"Michael Hartl", :email=>"michael@ex.com" }
    >> user[:name] # return "Michael Hartl"
    >> user[:passwd] # return nil
  • 다음과 같은 방식으로도 hash를 선언할 수 있으나 :name 과 다르게 name은 독자적으로 사용할 수 없다. 말이 좀 어려운데 아래처럼 선언해도 사용할 때는 user[:name] 형식이 된다는 말이다.

    1
    2
    >> user = { name: "abc", email: "asdf" }
  • Nested hash 형식도 가능하다.

    1
    2
    3
    4
    5
    >> params = {}
    >> params[:user] = {name: "asdf", age: "55"}
    >> params # return {:user=>{:name=>"asdf", :age=>"55"}}
    >> params[:user][:age] # "55"
  • inspect 메소드는 변수를 문자 그대로(literally) 출력한다.

  • puts + inspect 를 줄여서 p 로 쓸 수도 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >> puts :name, :name.inspect
    # name
    # :name
    >> puts "it worked", "it worked".inspect
    # it worked
    # "it worked"
    >> puts :name.inspect # :name
    >> p :name # :name

    위에서 나왔던 아래 소스를 살펴보자.
    ruby는 괄호(parentheses)( ) 및 중괄호(braces){ }를 생략할 수 있다.
    즉, 아래 소스는 stylesheet_link_tag 라는 이름의 함수이다.

    • stylesheet_link_tag 함수는 두 개의 인자를 갖는다.
      • string (stylesheet의 path)
      • hash
        • media type
        • Rails 4.0에 추가된 turbolinks 기능의 사용 여부
          1
          2
          3
          4
          5
          6
          <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
          # 아래와 같이 표현될 수 있다.
          <%= stylesheet_link_tag ('application', { media: 'all', 'data-turbolinks-track' => true } ) %>
          # 'data-turbolinks-track' 이 => (hashrocket) 을 사용한 이유는 변수명에 dash '-' 가 들어갈 수 없기 때문이다.
          # Ruby는 new line이나 space에 제한을 받지 않으므로 맘대로 끊어쓰면 된다. 보통 80 글자 기준으로 엔터 치는 듯 하다.

<%= %> 로 둘러싸여있는 구문은 ERb에 의해 HTML에 들어가게 된다. 브라우저의 소스 보기를 통해 보면 다음과 같이 보이게 된다.

:true
1
2
<link data-turbolinks-track="true" href="/assets/application.css" media="all" rel="stylesheet">

Ruby classes


Ruby는 객체 지향 언어이기 때문에 method의 집합인 class로 이루어져 있고, 초기화를 통해 object를 생성한다. 이로 인한 몇 가지 특성을 보자.

  • Constructor

    1
    2
    3
    4
    5
    6
    >> s = "foobar"
    >> s = String.new("foobar")
    >> a = Array.new([1,3,2])
    >> h = Hash.new
    >> h = Hash.new(0) # 인자들을 0으로 초기화
  • Class inheritance

    1
    2
    3
    4
    5
    6
    7
    8
    >> s = String.new("foobar")
    >> s.class # String
    >> s.class.superclass # Object
    >> s.class.superclass.superclass # BasicObject
    >> s.class.superclass.superclass.superclass # nil
    >> class ABC < String # 상속
  • build-in class 수정하기

    • JavaScript의 navigator와 비슷한 개념인가 싶은데… override는 아니고 직접 그 class를 다시 선언해서 native class의 method를 수정하여 사용할 수 있다.
      1
      2
      3
      4
      5
      6
      7
      >> class String
      >> # Returns true if the string is its own reverse.
      >> def palindrome?
      >> self == self.reverse
      >> end
      >> end
  • blankempty의 차이. (irb에서는 지원하지 않는다. ERb에서 되는지는 안해봤지만 되니까 써놓지 않았을까…)

    1
    2
    3
    4
    5
    >> "".blank? # true
    >> " ".empty? # false
    >> " ".blank? # true
    >> nil.blank? # true
  • Controller class

    • Controller class는 다음과 같은 상속 구조를 갖는다.
      • StaticPagesController < ApplicationController < ActionController::Base < ActionController::Metal < AbstractController::Base < Object
  • User model에 대해 살펴보자.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class User
    attr_accessor :name, :email
    def initialize(attributes = {})
    @name = attributes[:name]
    @email = attributes[:email]
    end
    def formatted_email
    "#{@name} <#{@email}>"
    end
    end
    • attribute accessors는 gettersetter 메소드를 만들겠다는 의미이다. @name, @email instance 변수에 대해 retrieve(get), assign(set)을 도와준다.
      instance 변수는 언제나 @로 시작하며, 정의하지 않을 시 nil 이 된다
    • 위의 initialize 메소드는 User.new 를 수행하면 호출된다. initializeattributs: 라는 하나의 인자만 갖는다. 위 코드를 통해 인자는 Hash값이라는 것을 알 수 있다.
    • 책의 예제에서는 console에서 위 파일을 가져와서 수행했는데 파일을 가져오기 위해서는 require 메소드를 사용한다. 파일명도 생략한다.
      • require './example_user'
Share