Skip to content

Instantly share code, notes, and snippets.

@kbs4674
Last active August 15, 2021 08:04
Show Gist options
  • Save kbs4674/cb207dcc405cf18116680f7b6d985bb2 to your computer and use it in GitHub Desktop.
Save kbs4674/cb207dcc405cf18116680f7b6d985bb2 to your computer and use it in GitHub Desktop.

Ruby

  1. symbol과 string의 차이는 무엇인가요?
  • symbol은 한번 정해진 값에 대해선 바꿀 수 없으나, (그렇다고, symbol로 초기화된 변수를 아예 건들지 못하는건 아님, :other_symbol과 같이다른 symbol 혹은 type으로 덮어쓰기가 가능) string은 중간에 내용을 바꿀 수 있다는 차이점이 있음.
a = :something_symbol
=> :something_symbol
a += "hello, world"
NoMethodError: undefined method `+' for :something_symbol:Symbol
a = :other_symbol
=> :other_symbol
a = "great job"
=> "great job"

b = "hello"
b += " world"
=> "hello world"
  • 같은 이름의 symbol에 대해선 메모리를 서로 공유하다 보니 string에 비해 접근성이 빠름.
## symbol
:good.object_id
=> 1208988
:good.object_id
=> 1208988

## string
"hello".object_id
=> 70178679894640
"hello".object_id
=> 70178667293320
  1. self 는 무엇인가요?

class 내에 클래스 메소드로서 쓰이는 개념, 사전에 something = Cal.new 와 같이 객체를 생성하지 않아줘도 됨.

class Cal
  def self.plus(a, b)
    return a+b
  end
end

Cal.plus(3, 5)
=> 8
  1. 생성자(constructor)을 사용하는 방법은 무엇인가요? initialize 메소드를 정의해주면 됩니다.
class Cal
  def initialize
    @init_number = 32
  end
  
  def plus(b)
    return @init_number+b
  end
end

data = Cal.new
data.plus(2)
=> 34
  1. Ruby가 dynamic programming language 임을 나타내는 특징들은 무엇인가요.

프로그램이 실행중에 다른프로그래밍 코드를 읽고, 생성하고, 변경할 수 있게 하며 심지어는 자신의 구조도 스스로 수정이 가능하게 하는 프로그래밍 방법입니다. 루비의 동적 프로그래밍 특성을 위 설명 그대로 확인할 수 있는 대표적인 예시는 eval 메소드로, string을 코드로 인식시키는 메소드 입니다.

# 아무 함수도 없는 EvalClass를 정의 한다.
class EvalClass
end
instance = EvalClass.new
 
# hello 라는 함수가 없는 것을 확인 한다.
instance.hello # undefined method 'hello' for #<EvalClass ....>
 
# 실행중 class_eval  을 이용해서 없던 함수를 추가한다.
EvalClass.class_eval do
  def hello
    puts 'class_eval bind method'
  end
end
instance.hello # => class_eval bind method
 
# 실행중 class_eval 을 이용해서 방금 추가했던 함수를 같은이름의 새로운함수로 교체한다!'
EvalClass.class_eval do
  def hello
    puts 'class_eval modify method'
  end
end

instance.hello # => class_eval modify method
  1. 동적인 함수명을 실행(invoke) 하는 방법을 설명하세요.

send 메소드를 활용하면 됩니다.

class Cal
  def self.plus(a, b)
    puts "a+b = #{a+b}"
    return a+b
  end

  Cal.send(:plus, 2, 3)
end
  1. ||= 의 역할은 무엇인가요?

변수가 nil 혹은 false일 경우 ||= 이 가리키는 value로 다시 초기화 합니다.

## nil 케이스
@flower = nil
@flower ||= "rose"
=> "rose"

@fruit = "melon"
@fruit ||= "orange"
=> "melon"

## boolean 케이스
@is_solved = false
@is_solved ||= true
=> true

@is_copied = true
@is_copied ||= false
=> true
  1. Class와 Module 의 차이는 무엇인가요?
  • 여기 내용을 참고해서 공부 및 작성했습니다. diff_class_module
  1. 조건연산자 중 and 와 && 의 차이는 무엇인가요?

기능으로선 'and(그리고)'를 표현한다는 공통점이 있으나, 우선순위가 다릅니다. &&and보다 우선순위가 높습니다.

foo = :foo
bar = nil

a = foo and bar
# => nil
a
# => :foo

a = foo && bar
# => nil
a
# => nil

a = (foo and bar)
# => nil
a
# => nil

(a = foo) && bar
# => nil
a
# => :foo

또한, 위 표현을 보면 and 표현은 = 표현 보다 약하단 것도 볼 수 있습니다.

a = foo and bar
# => nil
a
# => :foo

and 표현 같은 경우,= 이 먼저 실행된 후, 비교가 진행이 되는 반면 &&는 비교 먼저가 진행되는게 보입니다.

a = foo && bar
# => nil
a
# => nil
  1. Block, Proc, Lambda 의 차이가 무엇인가요?
  • block

· block은 중괄호({ ... }) 혹은 do-end 사이에 문법을 표현하는 방법입니다.
· block 코드를 만나는 즉시 실행됩니다.

for i in 0..3 do
  puts i
end

4.times { |count| puts "#{count}" }
  • Proc

· block 형태로 코드를 사전에 입력 후(이 때는 Proc 내부 코드 동작 안함; unactive), 나중에 Proc 변수가 호출되면 내부 코드가 동작(active)됩니다.
· 코드 재사용이 가능합니다.

arr = [1,2,3]

plus = Proc.new do |t|
  t+t
end
=> #<Proc:0x007fba87392300@(irb):289>

result = Array.new
arr.each { |num| result << plus.call(num) }
=> [1, 2, 3]

result
=> [2, 4, 6]

· argument 갯수가 엄격하지 않습니다. (인자가 부족할 시, 해당 자리는 nil로 처리)

test_proc = Proc.new { |a,b,c| puts "#{a} #{b} #{c.class}" }

test_proc.call(1, 2, 3)
1 2 3
=> nil

test_proc.call(1, 2)
1 2 NilClass
=> nil

· Proc 내에서 return문을 만날 시, proc 내 return문이 반환됩니다. (아래 메서드는 결국 Proc의 return문을 반환)

def proc_return
  Proc.new { return "Proc.new" }.call
  return "proc_return method finished"    # 실행하지 않는다.
end

puts proc_return
=> "Proc.new"
def generic_return(code)
  one, two    = 1, 2
  three, four = code.call(one, two)
  return "Give me a #{three} and a #{four}"
end

puts generic_return(lambda { |x, y| return x + 2, y + 2 })   #=> Give me a 3 and a 4
puts generic_return(Proc.new { |x, y| return x + 2, y + 2 }) #=> LocalJumpError: unexpected return
  • Lambda

· block 형태로 코드를 사전에 입력 후(이 때는 Lambda 내부 코드 동작 안함; unactive), 나중에 Lambda 변수가 호출되면 내부 코드가 동작(active)됩니다.
· 코드 재사용이 가능합니다.

ex = lambda { |num| num - 30}

ex.call(40)
=> 10

· argument 갯수에 대해 엄격히 지킵니다. (argument 부족 시 ArgumentError: wrong number of arguments (given n, expected m))

test2 = lambda { |a,b,c| puts "#{a} #{b} #{c}" }

· Lambda 내에서 return문을 만나더라도 lambda는 계속 내부적으로 실행됩니다.

def lambda_return
  lambda { return "lambda" }.call
  return "lambda_return method finished" # 실행된다.
end

puts lambda_return
=> "lambda_return method finished"
def generic_return(code)
  one, two    = 1, 2
  three, four = code.call(one, two)
  return "Give me a #{three} and a #{four}"
end

puts generic_return(lambda { |x, y| return x + 2, y + 2 })   #=> Give me a 3 and a 4
puts generic_return(Proc.new { |x, y| return x + 2, y + 2 }) #=> LocalJumpError: unexpected return
  1. 외부 파일을 참조하는 require, load, include, extend의 차이는 무엇인가요?
  • require : 최초 한번만 외부파일을 부르면 memory에 기록되고 계속 재사용 가능
  • load : 한번 외부파일을 부르고, 코드가 종료되면 해당 파일도 종료 (일회성)
  • include : Module 메소드를 인스턴스 메소드로 상속받습니다.
  • extend : Module 메소드를 클래스 메소드(self.*)로 상속받습니다.
## include와 extend의 차이점을 보여주는 코드

module Foo
  def foo
    puts 'heyyyyoooo!'
  end
end

# include : 모듈메서드를 인스턴스 메서드로 상속받게 됨
class Bar
  include Foo
end

Bar.new.foo # heyyyyoooo!
Bar.foo # NoMethodError: undefined method ‘foo’ for Bar:Class

# extend : 모듈메서드를 클래스 메서드로 상속받게 됨
class Baz
  extend Foo
end

Baz.foo # heyyyyoooo!
Baz.new.foo # NoMethodError: undefined method ‘foo’ for #<Baz:0x1e708>
  1. clone과 dup, deep_dup의 차이는 무엇인가요?
  • [Ruby] Clone VS dup

· clone은 원본 변수의 freeze 메소드 속성에 대해 가지고 있는 반면, dup은 아닙니다.
* freeze 메소드 : 해시의 값(value)이 변경되지 못하도록 명령하는 메소드

a = {'key1' => 1, 'key2' => {'key3' => 3, 'key4' => 4}}.freeze
b = a.clone
c = a.dup

a['key1'] = 32
=> RuntimeError: can't modify frozen Hash

b['key1'] = 32
=> RuntimeError: can't modify frozen Hash

c['key1'] = 32
=> 32

· 싱글톤 메소드에 대해서는 copy가 안됩니다.
* 싱글톤(singleton) 메소드 : 특정 객체에만 주어진 메소드

o = Object.new
def o.foo
  42
end

o.dup.foo
=> NoMethodError: undefined method `foo'

o.clone.foo
=> 42
  • [Rails] dup VS deep_dup
    · deep_dup은 원본 데이터와 메모리 공유를 하지 않습니다.
a = {'key1' => 1, 'key2' => {'key3' => 3, 'key4' => 4}}
b = a.dup
c = a.deep_dup

a['key2'].object_id == b['key2'].object_id
=> true

a['key2'].object_id == c['key2'].object_id
=> false

[개인적인 의문] clone 메소드는 freeze 속성에 대해 그대로 가져간다는 특징이 있다보니, 아래와 같이 원본 Hash를 담고 있는 a 변수와 a의 freeze 속성까지 그대로 copy해낸 b 변수는 Hash 값 변경을 시도 시 변경이 안되는 것을 확인할 수 있었습니다.

a = {'key1' => 1, 'key2' => {'key3' => 3, 'key4' => 4}}.freeze
b = a.clone
c = a.dup

a['key1'] = 32
# => RuntimeError: can't modify frozen Hash

b['key1'] = 32
# => RuntimeError: can't modify frozen Hash

c['key1'] = 32
# => 32

하지만 a와 b의 메모리에 대해서도 공유하는지 궁금해서 이를 조회해 보면 변수 자체는 서로 다른 값을 가지나, hash 내 key는 메모리를 공유한다는 것을 알 수 있습니다.

a.object_id ## original
=> 70219554622880
b.object_id ## clone
=> 70219554589820

a['key1'].object_id ## original
=> 3
b['key1'].object_id ## clone
=> 3
c['key1'].object_id ## dup
=> 65

'아니, 변수에 대한 주소값을 공유한다며??' 저는 여기서 혼동을 느꼈습니다.

그래서 저는 스택오버플로우를 통해 이에대해 질문을 넣었고, 여기서 답을 얻을 수 있었습니다.

[의문에 대한 정답] integer 형태의 value는 값만 동일하다면 서로 메모리를 공유한다는 특징이 있었습니다.

x = 3
y = 3
x.object_id == y.object_id # true
x = "a"
y = "a"
x.object_id == y.object_id # false

하지만 만약 아래와 같이 범위가 매우 큰 숫자를 초기화 할 경우, 아래 숫자는 메모리를 서로 공유하지 않습니다.

x = 11111111111111111111111111111111
y = 11111111111111111111111111111111
x.object_id == y.object_id # false

Ruby on Rails

  1. Rails의 2가지 주요 철학이 무엇이며 각 철학의 예시가 무엇인가요?
  • DRY(Don't Repeat Your Self): '코드를 반복적으로 쓰지 마라' 라는 일환으로서 코드의 재사용을 강조합니다.
    [예시] 동일한 SQL 역할을 수행하는 메소드에 대해 Model에서 scope를 통해 별도의 메소드를 정의 및 이를 재사용 함으로서 코드의 반복을 줄임.
class Bulletin < ApplicationRecord
  scope :find_bulletin, -> (bulletinId) { find(bulletinId) }
end
  • COC(Convention Over Configuration): '설정보단 규약' 이란 조건으로서, 최대한 Rails에서 정해진 규칙을 활용하는 것
    [예시] MVC의 패턴에 있어 Model과 Controller의 이름을 정의함에 있어 다음 규칙이 (암묵적으로) Rails 내에서 지켜지고 있습니다.
1) Controller : bulletins_controller.rb
2) Model : bulletin.rb
  1. --api 옵션을 사용하여 Rails 프로젝트를 만들었을 때 어떤 middleware 변화가 있나요?
  • 기존의 Browser Application에 사용됐던 미들웨어 생성이 안됩니다. (쿠키 관리 미들웨어 생성 x 등)
  • view, helper, asset 생성이 제한됩니다.
  • Controller에서는 기존의 view가 함께 쓰였던 때 당시 ActionController::Base가 아닌 ActionController::API을 상속받습니다.
  • API 환경의 프로젝트 생성 시, 아래의 Middleware가 기본으로 적용됩니다.
    (view에서 쓰였던 미들웨어는 배제된 채로 생성됩니다.)
Rack::Sendfile
ActionDispatch::Static
ActionDispatch::Executor
ActiveSupport::Cache::Strategy::LocalCache::Middleware
Rack::Runtime
ActionDispatch::RequestId
Rails::Rack::Logger
ActionDispatch::ShowExceptions
ActionDispatch::DebugExceptions
ActionDispatch::RemoteIp
ActionDispatch::Reloader
ActionDispatch::Callbacks
Rack::Head
Rack::ConditionalGet
Rack::ETag
  1. Rails(ActiveSupport Extensions) 에서 추가된 Array, Hash Class의 함수는 어떤 것들이 있나요?
  • Array
    • Accessing

      • from : n을 skip한 이후로 부터 배열 조회
      • to : m까지의 배열을 조회
      • second, third, fourth, fifth, second_to_last : n번 째 혹은 n부터 m까지 범위의 배열 조회
    • Extracting

      • extract! : block 내에 표현된 코드를 기반으로 배열 추출
      numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
      numbers # => [0, 2, 4, 6, 8]
      
    • Conversions

      • to_sentence : 배열 항목을 열거하는 문장을 포함하는 문자열로 바꿉니다.
      %w().to_sentence                # => ""
      %w(Earth).to_sentence           # => "Earth"
      %w(Earth Wind).to_sentence      # => "Earth and Wind"
      %w(Earth Wind Fire).to_sentence # => "Earth, Wind, and Fire"
      
      • to_formatted_s : 문자가 formatting 될 형식을 지정합니다, default는 to_s 입니다.
      • to_xml : 배열을 XML 형식으로 반환합니다.
    • Wrapping

      • Array.wrap : Array가 아닌 문자를 배열 type으로 감싸줍니다.
      Array.wrap(nil)       # => []
      Array.wrap([1, 2, 3]) # => [1, 2, 3]
      Array.wrap(0)         # => [0]
      
    • Duplicating

      • deep_dup : Active Support를 통해 자체 및 모든 객체를 재귀적으로 복제합니다. 내부의 각 객체에 메소드를 Array#map으로 보내는 방식과 동일합니다. (변수 간 메모리 공유를 안합니다.)
      array = [1, [2, 3]]
      dup = array.deep_dup
      dup[1][2] = 4
      array[1][2] == nil   # => true
      
    • Grouping

      • in_groups_of(number, fill_with = nil) : 배열을 size을 기준으로 분할, 그룹화 된 배열을 반환합니다.
      [1, 2, 3].in_groups_of(2) # => [[1, 2], [3, nil]]
      [1, 2, 3].in_groups_of(2, 0) # => [[1, 2], [3, 0]]
      [1, 2, 3].in_groups_of(2, false) # => [[1, 2], [3]]
      
      • in_groups(number, fill_with = nil) : %w(괄호안에 있는 다수의 문자열을 배열로 변환) 표현식을 활용해서 특정 수의 그룹으로 분할, 그룹화 된 배열을 반환합니다.
      %w(1 2 3 4 5 6 7).in_groups(3)
      # => [["1", "2", "3"], ["4", "5", nil], ["6", "7", nil]]
      
      %w(1 2 3 4 5 6 7).in_groups(3) {|group| p group}
      ["1", "2", "3"]
      ["4", "5", nil]
      ["6", "7", nil]
      
      • split(value = nil) : split value를 기준으로 배열 내 element를 분할합니다.
      [0, 1, -5, 1, 1, "foo", "bar"].split(1)
      # => [[0], [-5], [], ["foo", "bar"]]
      
      (-5..5).to_a.split { |i| i.multiple_of?(4) }
      # => [[-5], [-3, -2, -1], [1, 2, 3], [5]]
      
  • Hash
    • Conversions
      • to_xml : 해시를 XML 형식으로 반환합니다.
    • Merging : 서로 다른 Hash를 합칩니다.
      • reverse_merge and reverse_merge! and reverse_update
      • deep_merge and deep_merge! : 기존의 해시에서 key를 찾아내고, 이미 Key가 존재할 경우 기존의 객체를 유지하고 또다른 Hash와 합병됩니다.
      {a: {b: 1}}.deep_merge(a: {c: 2})
      # => {:a=>{:b=>1, :c=>2}}
      
      {a: {b: 1}}.merge(a: {c: 2})
      # => {:a=>{:c=>2}}
      
    • Deep duplicating
      • deep_dup : Active Support를 통해 자체 및 모든 객체를 재귀적으로 복제합니다. 내부의 각 객체에 메소드를 Enumerator#each_with_object 으로 보내는 방식과 동일합니다. (변수 간 메모리 공유를 안합니다.)
      hash = { a: 1, b: { c: 2, d: [3, 4] } }
      
      dup = hash.deep_dup
      dup[:b][:e] = 5
      dup[:b][:d] << 5
      
      hash[:b][:e] == nil      # => true
      hash[:b][:d] == [3, 4]   # => true
      
  1. save, save! 함수의 동작 차이는 무엇이며 각각 어떤 상황에서 사용하나요?
  • save : 데이터 저장과정 도중 오류(invalid) 발생 시, 결과에 대해 boolean으로 반환합니다.
  • save! : 데이터 저장과정 도중 오류(invalid) 발생 시, 에러를 일으키고, raise error 메세지를 반환합니다.
  1. find_by!(a: ‘b’) 와 where(a: ‘b’)의 차이는 무엇인가요?
  • find_by! : 데이터를 탐색 후 여러개 나온 결과물 중 하나만을 반환합니다. 탐색 결과물이 없을 시 에러를 일으킵니다.
  • where : 데이터를 탐색 후 여러개 나온 결과물 전체를 반환합니다. 탐색 결과물이 없을 시 nil을 반환합니다.
  1. update, update_all, update_attributes, update_columns 의 차이는 무엇인가요?
  • update_attributes : Rails 4.0.2 부터 update 메소드로 alias 처리되었습니다.
  • update : 1개 단위로 데이터 수정이 이루어지며, validation 검증이 통과되면 데이터가 수정됩니다.
  • update_columns : 1개 단위로 데이터 수정이 이루어지며, 콜백검증 없이 데이터베이스에 바로 데이터가 수정됩니다.
  • update_all : n개 단위로 데이터 수정이 이루어지며, 콜백검증 없이 데이터베이스에 바로 데이터가 수정됩니다.
  1. destroy, delete의 차이는 무엇인가요?
  • 데이터가 삭제되기 전 destroy은 콜백 검사를 하나, delete는 콜백 검사를 생략합니다.
  • destroy 메소드를 통해 삭제 시, 외래키로 연계된 자식(child) 데이터도 삭제됩니다.
  1. ActiveRecord Validation 함수들의 공통 옵션은 어떤게 있나요?
  • allow_nil : nil 값 검사
  • allow_blank : 공백('') 및 nil 값 검사
  • message : Exception 상황 발생 시 에러메세지를 띄웁니다.
  1. has_many :thorugh 와 has_and_belongs_to 의 차이는 무엇인가요?
  • has_many :thorugh : 2개의 Model 사이에 Join테이블을 두고, join 테이블에 2개의 테이블 외래키 컬럼을 참조해서 타 테이블을 읽어내어 데이터를 읽어오는 방식
  • has_and_belongs_to : 2개의 Model과 또 다른 제 3자의 Model을 두고, 3자 모델에서는 2개의 테이블 외래키의 컬럼은 기본적으로 가지고있고, 더불어 추가적인 컬럼을 가지고 있을 수 있음. 제 3자 Model이 가진 2개의 외래키를 기반으로 M:N 참조 또한 가능
  1. Rails 서버 실행 시 우선적으로 자동 실행되어야 할 코드는 일반적으로 어디에 위치해야 하나요?

config 폴더 내에 위치되어있습니다.

  1. ActiveModel에 대해 length, count, size 각각의 차이는 무엇인가요?
  • length : 모든 Attribute(select *)를 탐색 후, 데이터 갯수를 알아냅니다.
  • count : Count 함수를 통해 데이터 갯수를 알아냅니다.
  • size : 테이블에 counter cache 컬럼을 먼저 찾아보구, 없을 경우 count 메소드와 동일한 역할을 수행합니다.
  1. HTTP GET 요청 시 ActionController에서 인식하는 Array 와 Hash 파라미터 구조는 어떻게 되나요?
  • Array
GET /users?ids[]=1&ids;[]=2&ids;[]=3
=> params[:ids] = ["1", "2", "3"]

** Hash

<form accept-charset="UTF-8" action="/users" method="post">
  <input type="text" name="user[name]" value="Auction" />
  <input type="text" name="user[phone]" value="201-867-5309" />
  <input type="text" name="user[address][postcode]" value="07001" />
  <input type="text" name="user[address][city]" value="New Jersey" />
</form>

=> params[:user] = { "name" => "Auction", "phone" => "201-867-5309", "address" => { "postcode" => "07001", "city" => "New Jersey" } }
  1. rescue와 rescue_from 의 차이는 무엇인가요?
  • rescue : 특정 Controller Action 내에서만 실행되는 에러 핸들러
  • rescue_from : Controller에서 사전에 에러를 다루는 Action을 생성 후, 모든 Action 내 코드에서 동작 중 에러 발생 시 rescue_from 규칙에 맞는 Action가 실행되는 에러 핸들러
  • rescue는 일부 Action만을 책임진다면, rescue_from은 Action 전체를 책임짐.
  1. Resource Routing 설정 시 resources 와 resource 의 결과가 어떻게 다른가요?
  • Browser 환경의 Application
    • resources : index, show, new, create, edit, update, destroy 7가지 규칙이 생성되며, show, edit, update, destroy에는 각각 특정 ID값을 가지고 있습니다.
    • resource : show, new, create, edit, update, destroy 6가지 규칙이 생성되며, 특정 ID값을 가지고 있지 않습니다.
  • API Only Application
    • resources : index, show, create, update, destroy 5가지 규칙이 생성되며, show, update, destroy에는 각각 특정 ID값을 가지고 있습니다.
    • resource : show, create, update, destroy 4가지 규칙이 생성되며, 특정 ID값을 가지고 있지 않습니다.
  1. Resource Routing 설정 시 namespace 와 scope, nested resources 각각의 차이는 무엇인가요?
  • namespace : 기존의 URL 패턴에 추가적으로 하위 Path가 생기고, Controller에 있어 하위 폴더를 거치게 됨.
namespace :admin do
  resources :articles, :comments
end

스크린샷 2020-07-31 오후 5 04 50

  • scope : Controller은 기존의 resource(s) 방식으로 가리키되, Path는 namespace 방식으로 변경하고 싶을 경우
scope '/admin' do
  resources :articles, :comments
end

## 위 표현과 동일한 문법
resources :articles, path: '/admin/articles'

스크린샷 2020-07-31 오후 4 56 51

  • nested resources : resources 안에 또 resources가 있는 개념으로서, RESTful API 규칙을 자동으로 생성해줍니다.
resources :magazines do
  resources :ads
end

스크린샷 2020-07-31 오후 5 08 20

  1. Resource Routing 설정 시 concern 은 어떤 용도로 사용하나요? 블록 내 공통되는 여러개의 라우터 설정을 하나로 묶어서 정의할 때 사용

스크린샷 2020-07-31 오후 5 09 19

  1. member route와 collection route 의 차이는 무엇인가요?
  • collection : 하나의 객체를 다루는 액션
  • member : 여러 개의 객체를 다루는 액션

스크린샷 2020-07-31 오후 5 10 23

  1. Active Job은 무엇이며 Global ID는 무엇인가요?
  • Active Job : 서버에서 Background Job으로 어떤 작업에 대한 실행이 이루어지며, 동기(perform_now) 및 비동기(perform_later) 방식이 있습니다.
  • Global ID : Active Job에서 지원되는 매개 변수, 이를 통해 class/ID 쌍 대신 작업중인 Active Record 개체를 Job에 전달할 수 있습니다.
  1. soft delete가 무엇이며 Rails에서 어떻게 구현할 수 있나요?
  • 기존의 테이블에서 deleted_at 과 같은 컬럼을 하나 추가 후, 데이터가 삭제되더라도 완전히 삭제되진 않고 deleted_at에 삭제 trigger가 발동된 날짜를 기록하고, deleted_at이 nil이 아닌 경우 사용자가 보는 화면에서는 해당 데이터를 (삭제된 것 처럼) 숨깁니다. (후에 데이터 복구 가능)
  • Gem을 통해 간단히 구현해낼 수 있습니다 : acts_as_paranoid
  1. counter_cache 옵션은 무엇인가요?

테이블이 가진 Association 데이터(자식 데이터)가 추가/제거될 때 마다 증감률에 대해 따로 부모테이블 컬럼에 기록을 하는 옵션입니다. (이를 size 메소드와 엮어서 활용할 수 있습니다.)

  1. 평소에 N+1 문제를 예방할 수 있는 방법은 무엇이 있을까요?

n개 이상의 테이블을 참고해야 함에 있어, 사전에 테이블을 참조하거나(preload 혹은 includes), Join 처리(eager_load 혹은 includes)

  1. includes, preload, eager_load 는 각각 어떤 차이가 있나요?
  • preload : (테이블이 n개일 때) 사전에 참조해야 하는 테이블 n개를 조회 및 탐색 수행
  • eager_load : 1개의 쿼리만을 가지고 Left Outer Join을 통해 SQL 쿼리 탐색을 수행
  • includes : eager_load, preload 둘 다의 속성을 가지고 있습니다 / SQL에서 WHERE Query 사용 시 eager_load 방식으로 탐색
  1. ActiveSupport::Concern은 어떤 용도로 사용하나요?
  • 클래스메소드 → 인스턴스 메소드로 할당됩니다.
  • 모듈을 상속합니다.
  • 문법이 코드 의존성을 강하게 하다보니 효율이 떨어진다는 의견이 있습니다.
module M
  def self.included(base)
    base.extend ClassMethods
    base.class_eval do
      scope :disabled, -> { where(disabled: true) }
    end
  end

  module ClassMethods
    ...
  end
end

require 'active_support/concern'

module M
  extend ActiveSupport::Concern

  included do
    scope :disabled, -> { where(disabled: true) }
  end

  class_methods do
    ...
  end
end

공부 참고자료

  1. 알아두면 도움이 되는 55가지 루비 기법
  2. ActiveRecord는 어떻게 Database의 컬럼과 매핑할까?
  3. Ruby Metaprogramming Is Even Cooler Than It Sounds
  4. 루비 메타프로그래밍(1) - Object Model
  5. Ruby Meta-programming
  6. Class와 Module의 차이점
  7. ||= 문법 개념
  8. PROCS, LAMBDA, BLOCKS
  9. 외부 파일을 참조하는 require, load, include, extend의 차이
  10. Ruby Methods: differences between load, require, include and extend in Ruby
  11. What's the difference between Ruby's dup and clone methods?
  12. (루비 사용자 가이드) 싱글턴 메소드
  13. Active Support Core Extensions
  14. Rails Paperclip: update vs. update_attributes
  15. Difference between update, update_columns, update_column, update_attributes, assign_attributes
  16. ActiveSupport::Concern code placed inside the included block or in the module body
  17. How to use concerns in Rails 4
  18. (제타위키) N+1 쿼리 문제
@rationality6
Copy link

안녕하세요
collection : 하나의 객체를 다루는 액션
member : 여러 개의 객체를 다루는 액션
가 반대로 써져있어서 씁니다~
https://tadhao.medium.com/member-vs-collection-in-rails-routes-ade10c8c5d19
여튼 너무 잘 봤어요. 많이 배웠습니다. 감사합니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment