티스토리 뷰

오늘은 좋아요 기능 복습과 gem을 활용한 검색 기능에 대해 배워보도록 할게요!


M:N 모델 관계 다 기억하시나요?

좋아요 기능에 필요한 모델은 총 3개! Like, Post, User

이 세개의 모델은 각각 M:N 모델관계를 가지게 됩니다.


한 명의 User는 여러개의 Post를 작성할 수 있고 여러개의 Post에 대해 Like 버튼을 누를 수 있습니다.


한 개의 Post의 Like는 여러 명의 User들에게 눌릴 수 있습니다.


이 모델의 관계를 그림으로 나타내면 다음과 같습니다.


자 그럼 직접 만들어볼까요?



[모델 만들기]

scaffold를 활용해서 crud의 기본 토대를 만들어주세요.

1
2
3
#bash창
rails g scaffold Post title:string body:tex
cs


Like모델을 만들어주세요.
이 모델은 post 모델과 user 모델을 참조합니다.
1
2
3
#bash창
 
rails g model like post:references user:references
cs


Devise gem을 설치해주세요.

1
2
3
#Gemfile
 
gem 'devise'
cs


1
2
3
4
#bash창
 
bundle install
rails g devise:install
cs



User모델도 만들어주세요.

이제 rake db:migrate 해주면 완성!


1
2
3
4
#bash창
 
rails g devise user
rake db:migrate
cs



[모델 관계 설정]

app/models폴더를 확인해보면 우리가 사용할 3개의 모델이 만들어져있습니다.

이 모델들간의 관계를 설정해줍시다.


먼저 like모델을 확인해볼까요?

1
2
3
4
#app/models/like.rb
 
belongs_to :post
belongs_to :user
cs










이미 모델들관의 관계가 설정되어있는 것을 확인할 수 있습니다.


그렇다면 post모델을 설정해줄까요?

1
2
3
4
5
#app/models/post.rb
 
belongs_to :user
has_many :likes
has_many :liked_users, through: :likes, source: :user
cs

"한 개의 Post의 Like는 여러 명의 User들에게 눌릴 수 있습니다."


마지막으로 user모델을 설정해주세요!

1
2
3
4
5
#app/models/user.rb
 
belongs_to :posts
has_many :likes
has_many :liked_posts, through: :likes, source: :post
cs


"한 명의 User는 여러개의 Post를 작성할 수 있고 여러개의 Post에 대해 Like 버튼을 누를 수 있습니다."


[메소드 정의]


1
2
3
4
5
#app/models/user.rb
 
def is_like? (post)
Like.find_by(user.id: self.id, post_id: post.id).present?
end

cs








[컨트롤러 생성]

1
2
#bash창
 rails g controller likes
cs


좋아요 기능을 수행해줄 like_toggle 메소드를 정의해주세요.

1
2
3
4
5
#app/controllers/likes_controller.rb
 
def like_toggle
    #곧 채워줍시다.
end
cs

라우트 설정을 해줄까요?

1
2
3
4
5
#config/routes.rb
 
root 'posts#index'
post 'post/:post_id/like' => 'likes#like_toggle'
get 'users/sign_out'
cs

 rootposts#index

 scaffold로 만들었던 index.erb를 메인화면으로!

 post ‘post/:post_id/like’ => ’likes#like_toggle

 좋아요 기능을 수행할 컨트롤러 라우트 설정!

 get ‘users/sign_out

 user가 로그아웃 할 수 있도록 설정!



여기서 잠깐!

우리가 만들고자 하는 화면의 모습을 잠시 확인 해볼까요?


views/posts/index.html.erb


views/posts/show.html.erb



scaffold를 통해 구현되지 않은 부분들은 전부 빨간색 네모로 만들었습니다.

우리는 이 빨간색 네모를 채워주려고합니다. 


[View 설정]

먼저, show.html.erb 를 꾸며봅시다.


Like: N명이 좋아합니다.

[좋아요 버튼] 


이 두가지 기능을 구현해 봅시다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#views/posts/show.html.erb
 
<p>
  <strong>Like:</strong>
  <%= @post.likes.size %> 명이 좋아합니다. 
</p>
 
<p>
  <if current_user.is_like? (@post) %>
  <form action='/post/<%= @post.id%>/like' method='post'>
  <button> 좋아요 취소 </button>  
  </form>
  
  <else %>
  <form action='/post/<%= @post.id%>/like' method='post'>
  <button> 좋아요</button>  
  </form>
  
  <end %>
</p>
cs


현재 유저가 좋아요를 눌렀다면? 좋아요 취소 버튼 생성

현재 유저가 좋아요를 안눌렀다면? 좋아요 버튼 생성


[컨트롤러 채우기]


아까 like컨트롤러에 만들어준 like_toggle 메소드를 정의해줍시다.


1
2
3
4
5
6
7
8
9
10
11
12
def like_toggle
  like = Like.find_by(user_id: current_user.id, post_id: params[:post_id])
    
  if like.nil?
    Like.create(user_id: current_user.id, post_id: params[:post_id])   
  else
    like.destroy
 
  end
    
  redirect_to :back
 end
cs

현재 유저의 id, 현재 보고있는 게시물의 id를 참조합니다.

만약, like가 nil일 경우, '좋아요' 반영, nil이 아닐 경우 '좋아요' 삭제 


이제, view.html.erb 를 꾸며봅시다.

Like 목록을 추가하고 현재 몇 명의 User가 좋아요를 눌렀는지 확인할 수 있도록 만들어줍시다.


1
2
3
4
5
#views/posts/index.html.erb
<th>Title</th>
<th>Body</th>
<th>Like</th>
<th>LinkTo</th>
<th colspan="3"></th>


cs

1
2
3
#views/posts/index.html.erb
<td><%= post.title %></td>
<td><%= post.body %></td>
<td><%= post.likes.size %> 명</td>
cs

3번째 줄의 코드를 각각 추가해줍시다.


자 이렇게 하면 좋아요 기능은 구현 완료되었습니다.

여기서 추가로 로그아웃 링크와 현재 로그인한 유저의 이메일을 확인할 수 있도록 구현해 봅시다.


먼저, c9주소/users/sign_in에 들어가서 회원가입을 해주세요!

config/initializers/devise.rb 파일에서 ctrl+fsign_out검색해서

:delete  :get으로 바꿔주세요.


1
2
3
4
#app/views/posts/index.html.erb
 
<h2>USER: <%= current_user.email%></h2>
 
cs

1
2
3
#app/views/posts/index.html.erb
 
<a href= '/users/sign_out'> Log out </a>

cs


마지막으로 해줘야 할 작업이 남아있습니다.

바로! 로그인한 유저만 글의 목록을 볼 수 있고 수정, 삭제, 로그아웃을 할 수 있도록 설정해줍시다.


1
2
3
4
5
6
7
8
#app/controllers/posts_controller.rb
 
def index
  @posts = Post.all
  unless user_signed_in?
    redirect_to '/users/sign_in'
  end
end
cs



여기까지 잘 실행된다면 좋아요 기능은 완료!



Sunspot & Solr

먼저 젬을 사용하기 전에 Sunspot과 Solr에 대해서 간략하게 알아볼까요?


[Solr]

Apache Lucene 프로젝트에 기반을 둔 검색 엔진으로써 Java언어로 작성되었습니다.

단독 애플리케이션 서버 형태로 작동하며, REST 형식의 API를 제공합니다.

오픈소스 기업용 검색엔진입니다. 


[Sunspot]

sunspot_rails gem을 통해 solr 라이브러리를 사용할 수 있도록 해주며, full text search를 가능하게 해줍니다.


자 그럼 gem을 설치해볼까요?


1
2
3
4
#Gemfile
 
gem 'sunspot_rails'
gem 'sunspot_solr'
cs


1
2
3
#bash창
 
bundle install
cs


gem 설치 완료!


1
2
3
#bash창
 
rake sunspot:solr:start
cs


Solr는 분리된 프로세스로 작동하기때문에 Solr server는 따로 작동시켜주어야합니다.

* 만약 서버를 끄려면 rake sunspot:solr:stop


[Post 모델 설정]

1
2
3
4
5
#app/model/post.rb
validates_presence_of :title, :body
searchable do
  text :title
end
cs


현재, 우리는 Post 모델 중 title 칼럼만 검색될 수 있도록 설정해둡시다.

만약, body 칼럼도 검색하고 싶다면! :body도 추가해주세요! 

(밑에서 더 자세하게 배워봅시다.)


[액션 만들기]

1
2
3
4
5
6
7
#config/routes.rb
 
resources :posts do
  collection do
    get :search
  end
end
cs



[Search 메소드 정의]

1
2
3
4
5
6
7
8
9
10
11
12
#app/controllers/posts_controller.rb
 
def search
  @posts = Post.search do
    keywords params[:query]
  end.results
  
  respond_to do |format|
    format.html { render :action => "index" }
    format.xml  { render :xml => @posts }
  end
end
cs


1
2
3
4
#app/views/index.html.erb
<%= form_tag search_posts_path, :method => :get do %>
<%= text_field_tag :query, params[:query] %> <%= submit_tag "Search!" %>
<end %>
cs


Post.search는 sunspot search 메소드입니다.

검색어 입력창에서부터 넘어온 값을 바탕으로 검색을 한 후 결과들만 뽑아줍니다.


end.results => 검색한 값의 결과만 깔끔하게 보여준다!

respond_to do |format| end => 사용자가 원하는 포맷으로 리턴해준다!

ex) html, js, xml, json ...



[라우트 설정]

1
2
3
#config/routes.rb
 
get 'posts/search' => 'posts#search'



cs



준비 끝! 

RUN! 검색해볼까요?



Great을 검색했을 때 나오는 결과입니다.


그렇다면 Body 칼럼의 내용도 검색해볼까요?

아까 위에서는 title만 검색범위에 넣었었죠? 이번에는 body도 추가해봅시다.




분명 body 칼럼을 추가했는데 없다고 뜨네요?

현재 존재하는 데이터들을 reindex 시켜준 후에 다시 검색해봅시다!


1
2
3
#bash창
 
rake sunspot:reindex
cs




검색 성공!

이번 교육은 여기까지!


댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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 31
글 보관함