문제

Ruby on Rails 애플리케이션에 사용자 작업을 기록하고 싶습니다.

지금까지 업데이트 및 생성 후에 데이터베이스에 로그를 삽입하는 모델 관찰자가 있습니다.어떤 사용자가 기록된 작업을 수행했는지 저장하려면 세션에 액세스해야 하는데 그게 문제가 됩니다.

첫째, MVC 모델을 깨뜨립니다.둘째, 기술은 해킹적인 것부터 이상한 것까지 다양하며 아마도 구현을 Mongrel 서버에 연결하는 것일 수도 있습니다.

취해야 할 올바른 접근 방식은 무엇입니까?

도움이 되었습니까?

해결책

나는 이것이 매우 흥미로운 질문이라고 생각합니다. 나는 여기서 큰 소리로 생각할 것입니다 ...

궁극적으로, 우리가 직면 한 것은 특정 기능 세트를 달성하기 위해 설계 패턴 수용 가능한 관행을 위반하기로 한 결정입니다. 그래서 우리는 스스로에게 물어야합니다

1) 가능한 솔루션은 무엇입니까? ~ 아니다 MVC 패턴을 위반합니다

2) 가능한 솔루션은 무엇입니까? ~일 것이다 MVC 패턴을 위반하십시오

3) 어떤 옵션이 가장 좋습니까? 나는 디자인 패턴과 표준 관행이 매우 중요하다고 생각하지만 동시에 코드를 보유하면 코드를 더 복잡하게 만들면 올바른 솔루션은 관행을 위반하는 것일 수 있습니다. 어떤 사람들은 그것에 대해 나와 동의하지 않을 수도 있습니다.

먼저 #1을 고려해 봅시다.

내 머리 꼭대기에서 다음과 같은 가능한 해결책을 생각할 것입니다.

a) 누가 이러한 작업을 수행하고 있는지에 관심이 있다면,이 데이터는 모델에 저장되어야합니까? 이 정보를 관찰자가 이용할 수있게합니다. 또한 ActiveRecord 클래스의 다른 프론트 엔드 발신자가 동일한 기능을 얻는다는 것을 의미합니다.

b) 누가 항목을 만들었는지 이해하는 데 관심이 없지만 웹 동작 자체를 기록하는 데 더 관심이 있다면 컨트롤러 동작을 "관찰"하는 것을 고려할 수 있습니다. 내가 Rails 소스 주위를 찌른 지 얼마되지 않았기 때문에 그들의 Activerecord :: Observer가 모델을 "관찰"하는 사람은 확실하지 않지만 컨트롤러 관찰자에게 적응할 수 있습니다. 이런 의미에서, 당신은 더 이상 모델을 관찰하지 않으며, 해당 관찰자에게 세션 및 기타 컨트롤러 유형 데이터 정보를 만드는 것이 합리적입니다. c) "구조"가 가장 적은 가장 간단한 솔루션은보고있는 작업 방법 끝에 로깅 코드를 단순히 삭제하는 것입니다.

MVC 관행을 중단하여 지금 옵션 #2를 고려하십시오.

a) 제안대로, 모델 관찰자가 세션 데이터에 액세스하도록하는 수단을 찾을 수 있습니다. 모델을 비즈니스 로직에 연결했습니다.

b) 여기에 다른 사람을 생각할 수 없습니다 :)

귀하의 프로젝트에 대한 더 이상 세부 사항을 알지 못하는 저의 개인적인 성향은 1A입니다. 사람들을 레코드에 첨부하려면 1A 또는이 작업에 관심이있는 곳이 몇 개 밖에되지 않은 경우 1C입니다. 모든 컨트롤러 및 작업에 대한 강력한 로깅 솔루션을 원한다면 1B를 고려할 수 있습니다.

모델 옵저버가 세션 데이터를 찾는 것은 약간 "stinky"이며 다른 프로젝트/상황/컨텍스트에서 모델을 사용하려고 시도하면 깨질 수 있습니다.

다른 팁

흠, 이건 곤란한 상황이군요.제대로 작동하려면 MVC를 위반해야 합니다.

나는 다음과 같이 할 것입니다 :

class MyObserverClass < ActiveRecord::Observer
  cattr_accessor :current_user # GLOBAL VARIABLE. RELIES ON RAILS BEING SINGLE THREADED

  # other logging code goes here
end

class ApplicationController
  before_filter :set_current_user_for_observer

  def set_current_user_for_observer
    MyObserverClass.current_user = session[:user]
  end
end

약간 해키하기는 하지만 내가 본 다른 많은 코어 레일보다 더 해키하지는 않습니다.

스레드로부터 안전하도록 만들기 위해 해야 할 일은(어차피 jruby에서 실행하는 경우에만 중요함) cattr_accessor를 적절한 방법으로 변경하고 데이터를 스레드 로컬 저장소에 저장하도록 하는 것입니다.

당신은 MVC를 깨는 것에 대해 옳습니다. 컨트롤러에 콜백을 사용하는 것이 좋습니다. 주로 관찰자가 아무것도 기록하고 싶지 않은 상황 (저장이 호출되는 모델과 같은 모델과 같은 모델과 같은)이 있기 때문입니다.

나는 내가 선택한 대답에 의해 제안 된 것을 할 수있는 깨끗한 방법을 찾았다.

http://pjkh.com/articles/2009/02/02/creating-an-audit-log-in-rails

이 솔루션은 AuditLog 모델과 TrackChanges 모듈을 사용하여 모든 모델에 추적 기능을 추가합니다. 그래도 업데이트하거나 만들 때 컨트롤러에 라인을 추가해야합니다.

과거에는 이와 같은 일을 할 때 '현재 사용자'의 아이디어를 포함하도록 사용자 모델 클래스를 확장하는 경향이있었습니다.

이전 답변을 살펴보면 세션에 실제 활성 레코드 사용자를 저장하는 제안이 있습니다. 이것은 몇 가지 단점이 있습니다.

  • 세션 데이터베이스에 큰 객체를 저장합니다.
  • 이는 사용자의 사본이 항상 '캐시 링'되었음을 의미합니다 (또는 로그 아웃이 강제 될 때까지). 즉,이 사용자의 상태 변경은 사용자가 로그 아웃하고 다시 로그인 할 때까지 인식되지 않을 것입니다. 예를 들어, 이는 사용자가 로그 오프 및 켜기를 기다리는 것을 비활성화한다는 것을 의미합니다. 이것은 아마도 당신이 원하는 행동이 아닐 것입니다.

요청이 시작될 때 (필터에서) 세션에서 user_id를 가져 와서 사용자를 읽습니다. user.current_user를 설정하십시오.

이 같은...

class User
  cattr_accessor :current_user
end

class Application
  before_filter :retrieve_user

  def retrieve_user
    if session[:user_id].nil?
      User.current_user = nil
    else
      User.current_user = User.find(session[:user_id])
    end
  end
end

그때부터 그것은 사소해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top