티스토리 뷰

프로그래밍 공부/Ruby on Rails : 이론

Ruby on Rails : C (Controller)

마음 따뜻한 개발자, 나른한 하루 2019. 10. 31. 21:50
class PostsController < ApplicationController
	## index 액션
	def index
		...
	end
    
	## show 액션
	def show
		...
	end
    
	## edit 액션
	def edit
		...
	end
end

C는 Controller의 줄임말로서, Model을 가공을 담당하는 친구라고 보시면 됩니다.

또한 Controller는 여러개의 액션을 가지고 있고, 액션 내부에는 액션 이름에 대응되는 view에서 활용되는 변수 및 데이터를 처리하는 알고리즘들이 존재합니다.

 

 

  • Controller은 Model과 View의 중간 경유지

Controller은 Model을 참고에서 테이블 내 데이터 탐색 정의를 하고, 이를 View에 넘기는 형식입니다.

 

 

  • Controller 생성법
# rails g controller [컨트롤러 이름] [액션 리스트들...]
rails g controller posts index show create

Controller 생성 명령어는 다음과 같습니다.

위 명령어에 있어선

  • posts : 컨트롤러 이름
  • index, show, create : 컨트롤러를 이루는 액션

입니다.

 

해당 명령어를 통해 Controller 및 View 구성 파일들이 동시에 생성이 되고, routes.rb에 자동으로 URI 정의가 이루어집니다.

 

더불어 Controller에는 암묵적인 규칙이 있는데, 이름을 지을 때 '복수'명 으로 짓는걸 선호합니다.

 

 

  • Controller 사용 유의사항

Controller 사용에 있어 다음 규칙을 따릅니다.

 

1) 액션과 view의 이름은 일치하며, view는 액션 내 코드를 참고합니다.

 

2) 액션에 정의된 변수는 다른 액션 및 view에서 사용이 불가능 합니다.

3) Controller 내에서는 다른 Model을 호출할 수 있습니다.

## Post Controller에서 Comment 모델을 불러옴.

class PostsController < ApplicationController
	def show
		@comment = Comment.where(post_id: params[:id])
	end
end

 

 

  • before_action

액션 내 동작되는 코드에 있어 가끔 공통적으로 사용되는 코드를 하나로 묶고 싶은 때가 있습니다.

이를테면 게시물 열람/수정/삭제 때 공통적으로 쓰이는 id 탐색 입니다.

@post = Post.find(params[:id])

사실 이 코드는 다음과 같이 짜도 되긴 합니다.

class PostsController < ApplicationController
	def index
		@posts = Post.all
	end
    
	def show
		@post = Post.find(params[:id])
	end
    
	def edit
		@post = Post.find(params[:id])
	end
    
	def update
		@post = Post.find(params[:id])
		@post.update(title: params[:title], content: params[:content])
	end
    
	def destroy
		@post = Post.find(params[:id])
		@post.destroy
	end
end

 

하지만 저희는  before_action  을 이용해서  @post = Post.find(params[:id])  코드를 하나로 묶어보겠습니다.

class PostsController < ApplicationController
	before_action :set_post, only: [:show, :edit, :update, :destroy]
    
	def index
		@posts = Post.all
	end
    
	def show
		@post = Post.find(params[:id])
	end
    
	def edit
		@post = Post.find(params[:id])
	end
    
	def update
		@post = Post.find(params[:id])
		@post.update(title: params[:title], content: params[:content])
	end
    
	def destroy
		@post = Post.find(params[:id])
		@post.destroy
	end
    
	private
	def set_post
		@post = Post.find(params[:id])
	end
end

위와같이 before_action을 이용해서 show, edit, update, destroy 액션만이 사전에 액션이 시작되기 전에 앞서 set_post 액션을 거치게 됩니다.

 

그런데 set_post 액션을 보면 특이하게 그 위에  private  이 있습니다.

private은 캡슐화를 정의한 것으로서,  before_action  을 거쳐간 경우가 아니면 외부에서 접근이 안되도록 막습니다.

* 참고 : JAVA로 보는 private 캡슐화 개념 [클릭]

 

 

  • View 파일 내 Ruby/Rails 문법 사용

View 파일 내에는 Ruby/Rails 문법을 사용할 수 있는데, 그냥 사용하는것은 아닙니다.

예를들어 순수하게 Controller 액션에서 정의했던 변수를 사용하려면 다음과 같이 사용하면 됩니다.

1) 문법 사용 예제 1

## app/controllers/lotties_controller.rb

class LottieController < ApplicationController
	def index
		@random = (1..45).to_a # 1~45의 숫자가 담긴 배열을 생성합니다 (C언어로 치면 for (int i=1;i<=45;i++) 개념), 참고로 .to_a는 일반 정수를 array 화 시키는 메소드
		@lotto = @random.sample(7).sort # random 변수 내 있는 1~45 숫자 중 .sample(n)를 통해 n개의 랜덤정수를 뽑아냅니다. 그리고 .sort를 통해 오름차순 정렬을 합니다.
	end
end


## app/views/lotties/index.html.erb
<%= @lotto %>

하지만 변수만 쓰면 심심하겠죠?

view에서는 if문과 같은 전문적인 문법 사용에 대해서도 지원을 합니다.

2) 문법 사용 예제 2

## app/views/admins/index.html.erb

<% if current_user.has_role? :admin %>
	<div>안녕하세요, 관리자 <%= current_user.nickname %>님!</div>
<% else %>
	<div>해당 페이지는 접근 불가입니다.</div>
<% end %>

하지만 if문을 보면 뭔가 좀 이상합니다.

예제 1과는 다르게 = 가 없습니다.

결국 <% %>  = 의 여부는

 

<%= ... %> : 출력 결과물을 보여주는 것,

<% %> : 출력 결과물을 보여주지 않는 것

 

위 2개의 차이로 이해를 하면 됩니다.

 

덧붙여서, <%# %> 도 있는데, #가 들어가면 주석처리가 되어 외부 View 결과상으로는 아무런 동작도 하지 않고, 보여지지도 않습니다.

### app/views/homes/index.html.erb

## 정상적으로 코드가 view에 노출
<%= current_user.nickname %>

## 주석 처리 : 코드가 작동하지도, 노출되지도 않음.
<%# current_user.nickname %>
<%#= current_user.nickname %>

더불어, View 파일 내에서는 다음과 같이 모델을 직접 참고해서 데이터를 불러올 수 있긴 하나, 해당 방법은 미래의 코드 유지보수에 있어 추천을 드리지 않습니다.

 

1) 올바른 코드 작성 예

## app/controllers/posts_controller.rb

class PostController < ApplicationController
	def index
		@posts = Post.all
	end
end
## app/views/homes/index.html.erb

<% @posts.each do |t| %>
	<%= t.title %> / <%= t.content %>
<% end %>

 참고  each do 문법은 변수가 가진 범위 만큼 반복을 돌면서 하나하나 데이터를 뽑아낼 때 쓰입니다.

(t라는 변수는 상속변수로서, 상세적으로 테이블의 컬럼(현재 예시에서는 title, content)을 가공할 때 쓰입니다.)

 

2) 올바르지 않은 코드 작성 예

* 작동은 잘 되긴 하나, 먼 미래에 유지보수 때 코드 찾느라 골 때릴 수 있음.

## app/views/homes/index.html.erb
<% Post.all.each do |t| %>
	<%= t.title %> / <%= t.content %>
<% end %>

 

 

  • View와 Controller 중 누가 먼저 작동될까?

한번 이런 의문점을 가진적이 있었는데, 확인 결과 Controller을 먼저 거치고, 그 후에 View의 결과를 보여주는 구조였습니다.

확실한 답을 결정짓는 코드는 바로 아래의 코드라고 보면 됩니다.

## app/controllers/posts_controller.rb
class PostController < ApplicationController
	def index
		@posts = Post.all
		redirect_to "/"
	end
end

 참고  redirect_to 코드는 페이지 방문 시 이동을 시킬 때 쓰이는 코드입니다.

 

위 코드 결과는 아무리 view에 뭘 꾸몄어도,  /posts/index  페이지에 방문 시 결국 Controller을 먼저 방문을 하게되고, redirect_to 코드로 인해 메인페이지로 이동시킵니다.

 

루비온 레일즈 Ruby on Rails ROR

댓글
  • 프로필사진 나그네 감사합니다. 도움이 많이 되었습니다.

    한가지 궁금한 것이 있는데 view에서는 인스턴스변수(<%= @name %>)를 쓸 수 있다는 건 알고 있는데
    위의 if문 예제와 같이 @없이 쓰는 변수는 어디에서 갖고오는 변수일까요?
    생략된 경우도 있을 수 있겠지만 이렇게 쓰이는 걸 본 적이 있어서요.

    ## app/views/admins/index.html.erb

    <% if current_user.has_role? :admin %> <===== current_user 는 어디에서 참조하고 있는 변수일까요?
    <div>안녕하세요, 관리자 <%= current_user.nickname %>님!</div>
    <% else %>
    <div>해당 페이지는 접근 불가입니다.</div>
    <% end %>

    2021.04.07 15:30
  • 프로필사진 마음 따뜻한 개발자, 나른한 하루 저도 이부분에 대해 잘 모르는상태로 써왔다가, 이 질문글을 보고 찾아보니, ApplicationController 에서 정의된 함수를 가지고와서 쓴다고 합니다.

    사실상 어떻게보면 current_user은 변수가 아닌 함수라고 보는게 좋을 것 같네요.
    [참고] https://stackoverflow.com/questions/12719958/rails-where-does-the-infamous-current-user-come-from
    2021.04.10 01:48 신고
댓글쓰기 폼
공지사항
Total
116,985
Today
218
Yesterday
343
링크
«   2021/06   »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30      
글 보관함