DonutWorks / Ari

0 stars 0 forks source link

Feature/issue 315 (여러 동아리가 쓸 수 있다) #355

Closed angdev closed 9 years ago

angdev commented 9 years ago

315 작업을 하였습니다.

작업 내용은 #315 에 있고 테스트를 한 번 제대로 해봐야할 것 같습니다. (굉장히 구멍이 많을 것..) 현재 필요한 작업 중 하나는 클럽이 들어가고 나서 관련 테스트를 추가하지 못한 점에 대응하는 작업입니다 ㅠㅠ

변경 사항에 대한 내용은 여기에 계속 업데이트하겠습니다.

(작성 중)

minhyeok4dev commented 9 years ago

이거 테스트 어떻게해? 뭔가 기본 club 정보가 없어서 못들어가는것같은데, 우리 정책상 일단 club db는 우리 선에서 만들어서 주기로 했고, 그럼 seed data가 있어야하지 않을까??

angdev commented 9 years ago

rake club:create 하면 테스트 클럽이 생기긴 하는데 (테스트용이라 task 이름 바꿔야할듯) 이런 내용을 포함해서 바뀐 내용을 빨리 적을게요 ㅠㅠ

shaynekang commented 9 years ago

우와... 정말 어마어마하게 고치셨네요. ㅎㄷ 이걸 시킨 내가 죄인입니다. 일요일에 만나서 나를 한 대 치세요.(..)

  1. app/controllers/application_controller.rb에 다음과 같은 코드가 있는데,
def capture_club
  if controller_name == "clubs"
    @current_club ||= Club.friendly.find(params[:id].downcase)
  else
    @current_club ||= Club.friendly.find(params[:club_id].downcase)
  end
rescue ActiveRecord::RecordNotFound => e
 not_found
end

이 구현은 ApplicationController라는 상위 클래스가 ClubsController라는 하위 클래스의 존재를 알고 있다는 사실이 되는 셈 같네요. (if controller_name == "clubs") 저라면 코드가 다소 길어지더라도 ApplicationController와 ClubsController를 다르게 정의해 줄 것 같습니다. ㅎㅎ

가령 ApplicationController에서는

class ApplicationController < ActionController::Base
# ...

protected
  def capture_club
    @current_club ||= Club.friendly.find(params[:club_id].downcase)
  rescue ActiveRecord::RecordNotFound => e
   not_found
  end
end

이렇게 구현하고, ClubsController에서는

class ClubsController < ApplicationController
 # ...

protected
  def capture_club
    @current_club ||= Club.friendly.find(params[:id].downcase)
  rescue ActiveRecord::RecordNotFound => e
   not_found
  end

이렇게 재정의 하는거죠. ㅎㅎ

  1. 2에 대한 여담인데, capture_clubbefore_filter를 걸어서 @current_club을 매 번 저장해주는 것 보다, current_user와 동일한 방식으로 current_club을 만들어줘도 되지 않을까요? 지금 구현은 어떠한 상황에서도 한 번의 액션당 current_club을 최소 한 번 읽어둬야 한다는 구현인데, 이렇게 한 이유가 있는지 궁금합니다. ㅎㅎ
  2. 루트 페이지(http://localhost:3000/)를 가면 Not Found 가 나오는 것 같네요. ㅠㅠ
  3. 버그를 하나 발견했는데 이건 사진으로 보여드리기 좀 애매하네요;;
    1. 두 개의 다른 클럽(DonutWorks1, SNU-Habitat)을 만들고, 하나의 AdminUser(username@donutworks.com / 12345678)을 만들어서 DonutWorks1소속으로 만들었습니다.
    2. 이후 SNU-Habitat의 관리자 로그인 페이지(/snu-habitat/admin)에 들어가서 username@donutworks.com / 12345678 로 로그인하면, 로그인이 성공하는 것 같은데, 'Not Found' 에러가 뜨네요. ㅎㄷ 이후 주소창에서 도넛웍스 관리자 페이지(/donutworks1/admin)를 입력해서 들어가면 성공적으로 들어가집니다.

확실히 서비스 전체를 뜯어고치는 대규모 수정이다보니, 자잘한 버그나 정책 변경사항이 많네요. ㅠㅠ 하나하나 발견해서 고쳐보도록 하죠. ㅎㅎ

shaynekang commented 9 years ago

관리자 로그인페이지에서 로그인에 실패하면 다음과 같은 에러가 나네요. ㅠㅠ

19_admin_login_error

shaynekang commented 9 years ago

오~ 음 그래도 뭔가 그럭저럭 잘 돌아가는 듯? 배포 전까지 자잘한 버그만 잡으면 될 것 같네요. ㅋ

수고하셨습니당~ -_-)/

minhyeok4dev commented 9 years ago

아직도 작업중인건가? 나중에 테스트 가능할 시점에 짧게나마 가이드 작성해주라~ 그때 해볼게~

angdev commented 9 years ago

@minhyeok92 @MujinChae @yhoonkim

TL;DR - 그런 건 없으니 다 읽어주세요.

이번 구현에서는 사실 모델 사이의 관계만 알아도 구현 내용을 대부분 이해할 수 있습니다.

models/club.rb 를 열어보면 아래와 같은 코드가 있습니다.

class Club < ActiveRecord::Base
  extend FriendlyId
  friendly_id :name, use: :slugged

  has_many :admin_users
  has_many :invitations
  has_many :messages
  has_many :notices
  has_many :responses
  has_many :users
  has_many :checklists
  has_many :tags

  def representive
    AdminUser.find_by(club: self)
  end
end

to_param 메서드를 override 해서 구현하던 것을 이런 저런 이슈들을 포함해서 쉽게 해결하기 위해 friendly_id gem을 사용하였습니다. 한편 클럽 이름으로 클럽을 찾을 때는 club.friendly.find(params[:club_id])와 같이 사용합니다. find 함수 override를 gem에서 의도적으로 하고 있지 않기 때문에 저렇게 써주시면 됩니다. (마찬가지로 notice의 경우도 이렇게 바뀌었습니다.)

이전에 User.all 과 같이 쓰던 것을 current_club.users 로 써주시면 됩니다. 같은 느낌으로 User.new 대신 current_club.users.new 해주시면 club_id가 새 인스턴스에 들어가있어서 편하게 사용할 수 있습니다.

지금까지는 클럽이 하나였으므로 전체 리스트를 가져와도 문제가 없었지만 이제는 club이 생겼으니 머지할 때 현재 클럽에 속한 것을 가져오도록 신경을 써주는 것이 중요합니다. 이와 더불어 club reference가 잘 연결되어 있는지 (club_id가 nil은 아닌지) 꼭 확인해주세요.

크게 복잡한 부분은 없으니 직접 보시면 될 것 같고, 현재는 클럽당 관리자는 한 명이기 때문에 클럽 관리자 접근은 current_club.representive 을 이용하여 하고 있으니 참고 바랍니다.

가장 큰 변화는 당연히 거의 모든 route가 resources :clubs의 블록 안으로 들어갔다는 점입니다. 이에 따라 컨트롤러, 뷰에 퍼져있는 모든 path, url 을 변경해주어야 합니다. 이 역시 머지하실 때 참고해주세요.

notice는 이제 title을 slug로 만들어서 이를 url로 사용합니다.

한편 원래 사용되는 url과의 호환성을 지원하기 위해서 아래와 같은 코드가 추가되었습니다. 간단히 설명하자면 notices/:id 를 :club_id/notices/:notice_slug 로 보내주는 코드입니다.

# for back compatibility
  resources :notices, only: [] do
    collection do
      get '/:id(/*rest)', to: (redirect do |path_params, req|
        notice = Notice.find_by_id(path_params[:id])
        "#{notice.club.friendly_id}/notices/#{notice.friendly_id}/#{path_params[:rest]}"
      end)
    end
  end

다들 아시는 이야기이겠지만, 한 계정이 여러 클럽에 로그인할 수 있으면 문제가 되기 때문에 이에 대한 strategy (config/initializers/club_scoped_authenticatable.rb)를 구현하였습니다. 요약하면 패스워드까지 확인하고 로그인하고자 하는 클럽에 속했는지 확인까지 해줍니다.

resource 이름이 AdminUser 이기 때문에 각종 헬퍼도 ~admin_user 입니다. 예를 들어 현재 관리자를 가져오려면 current_admin_user를 호출하면 됩니다.

를 하면 하나의 클럽과 그 클럽에 속한 3명의 유저, 3개의 공지글이 생기게 되니 테스트에 참고해주세요. 한편 2번 하면 중복이 생겨서 에러가 나는데 이건 FactoryGirl의 버그인지 의도사항인지 찾아보고 있습니다.

그냥 하나의 클럽만 만들려면 FactoryGirl.create(:club) 으로 하시면 됩니다.

일단 이 정도로 정리하면 될 것 같습니다. 더 생각나면 추가할게요!

angdev commented 9 years ago

참고로 지금 develop 브랜치까지는 제가 머지를 해보았습니다. (문제는 있을지 몰라도)

yhoonkim commented 9 years ago

(테스트 완)

angdev commented 9 years ago

일단 머지하였습니다. 각자 맡았던 부분 한번씩 봐주시고 문제 있는 부분은 적어주시거나 고쳐주셔도 좋습니다~

덧붙여서 세 가지 rake task를 추가하였습니다. (두 가지는 추가고 하나는 변경)

  1. rake club:create[name, logo_url]

클럽을 만들어 줍니다.

  1. rake club:create:test

테스트용 클럽을 만들어줍니다.

  1. rake club:create:representive[email, password, club_name, name, phone_number]

관리자 계정을 만들어줍니다.

zsh의 경우는 위의 task를 사용하실 때 rake "club:create[snu-habitat, http://google.com]" 와 같이 따옴표를 붙여주시면 잘 작동합니다.