2009-10-21 5 views
9

저는 독립 계정 사이트를 격리하기 위해 하위 도메인을 사용하는 Rails (현재 2.3.4) 앱을 개발 중입니다. 분명한 것은 foo.mysite.com이 foo 계정의 콘텐츠를 표시하고 bar.mysite.com이 bar의 콘텐츠를 표시해야한다는 것입니다.레일스 : 하위 도메인을 기반으로 쿼리 범위를 지정하는 것이 가장 좋습니다.

모든 모델 검색어의 범위가 현재 하위 도메인으로 지정되도록하는 가장 좋은 방법은 무엇입니까? 예를 들어

내 컨트롤러 중 하나는 다음과 같은 :

@page = @global_organization.pages.find_by_id(params[:id])   

(@global_organization를 참고 하위 도메인-FU를 통해 application_controller에 설정되어 있습니다.) 내가 무엇을 선호하는 경우 뭔가 같은 :

@page = Page.find_by_id(params[:id]) 

페이지 모델 검색은 자동으로 올바른 조직으로 범위가 지정됩니다. 나는이 같은 default_scope 지시어를 사용하여 시도했다 : 글로벌 액세스를위한 조직의 ID에 [조직] 단지 주목하는, 다시

class Page < ActiveRecord::Base 
    default_scope :conditions => "organization_id = #{Thread.current[:organization]}" 
    # yadda yadda 
end 

((페이지 모델), 같은 application_controller는 Thread.current을 설정합니다.)이 방법의 문제점은 기본 범위가 첫 번째 요청에서 설정되고 후속 요청이 다른 하위 도메인에서 변경되지 않는다는 것입니다.

세 가지 명백한 솔루션까지 :

1을 사용하여 별도의 각 하위 도메인에 대한 가상 호스트 단지는 (mod_rails를 사용하여) 하위 도메인 당 응용 프로그램의 다른 인스턴스를 실행합니다. 이 접근법은이 응용 프로그램을 위해 확장 할 수 없습니다.

2 위의 원래 컨트롤러 방식을 사용하십시오. 안타깝게도 앱에는 상당히 많은 모델이 있고 모델 중 많은 모델은 조직에서 제거 된 몇 가지 조인이므로이 표기법은 빠르게 번거로워집니다. 더 나쁜 것은 개발자가 제한을 기억하고 적용하거나 중요한 보안 문제를 위험에 빠뜨릴 것을 적극적으로 요구한다는 것입니다.

3 각 요청에서 before_filter를 사용하여 모델의 기본 범위를 재설정합니다. 여기에 나오는 성능이나 reqeust 당 업데이트 할 모델을 선택하는 최선의 방법에 대해 확신 할 수 없습니다.

생각하십니까? 내가 누락 된 다른 해결책? 이것은 모범 사례가되어야하는 공통된 문제인 것처럼 보입니다. 모든 의견 감사, 감사합니다!

답변

2

default_scopelambda을 정의 해 보셨습니까? 옵션을 정의하는 lambda 비트는 범위가 사용될 때마다 평가됩니다.

class Page < ActiveRecord::Base 
    default_scope lambda do 
    {:conditions => "organization_id = #{Thread.current[:organization]}"} 
    end 
    # yadda yadda 
end 

필터 매직과 함께 작업하면 세 번째 옵션이됩니다. 그러나 그보다 조금 더 적극적으로 페이지 모델에서 사용되는 모든 단일 검색을 시작합니다.

모든 모델에 대해이 동작을 원할 경우 default_scope를 ActiveRecord :: Base에 추가 할 수 있지만 몇 가지 조인이 있음을 언급 할 수 있습니다. 따라서이 경로를 사용하는 경우 조인을 처리하기 위해 해당 모델의 기본 범위를 재정의해야합니다.

+0

감사합니다. 실제로 코드를 테스트 해 보셨습니까? 난 그냥 응용 프로그램에서 그것을 시도하고 람다가 실제로 각 find에서 평가되고 있는지 확인할 수있는 동안, default_scope는 반환 값을 적용하지 않습니다. 출력 된 SQL을 살펴보면 : 조건은 단순히 무시 된 것처럼 보입니다. 다른 여러 가지 이유 때문에 아직 디버거를 사용할 수 없었지만 백업하고 실행하자 마자 피크를 잡을 것입니다. 왜 작동하지 않는지 생각해보십시오. – qfinder

+0

솔직히 내부 서버가 어떻게 쓰레드를 사용하는지 모르겠다. 따라서 Thread.current [: organization]이 모델에서 작동한다고 가정했다. 그러나 그것이 조건들이 무시되는 이유를 설명 할 수있을 지 모르겠습니다. 기본적으로 organazation_id = nil을 찾을 기본 범위를 정의하고 있습니다. – EmFi

+0

추가 조사에서 아직 작동하지 않는 것 같습니다. 패치는 있지만 YMMV : https://rails.lighthouseapp.com/projects/8994/tickets/1812-default_scope-cant-take-procs – EmFi

2

특히 레코드를 만들 때 잘못된 보안 감각으로 이어질 수 있으므로 여기에 기본 범위로주의하십시오.당신은 또한 그래서 당신의 새로운 생성/행동을 보이는 것, 새로운 기록에 적용이 연결을 보장하기 원하기 때문에

@page = @go.pages.find(params[:id]) 

가장 큰 이유입니다 :

나는 항상이 명확 유지하기 위해 첫 번째 예제를 사용했습니다 다음과 같이, 제대로 부모 협회 범위 것을 보장 :

# New 
@page = @go.pages.new 

# Create 
@page = @go.pages.create(params[:page]) 
+0

좋은 점은,이 경우에는 조인 구조로 인해 생성시 강제해야 할 곳이 몇 군데 있지만 읽는 동안 시행해야하는 곳이 많기 때문에 여전히 길을 찾고 싶습니다. default_scope을 사용합니다. – qfinder

+0

또한 하위 도메인 범위의 멀티 테넌트 애플리케이션을 시작하기위한 샘플 앱인 http://github.com/devinterface/authlogic_subdomain_fu_startup_app을 살펴보십시오. 초기 사용자 (계정의 소유자이기도 함)와 계정 생성을 처리합니다. – bensie

+1

컨트롤러에서 추가 작업/코드 혼란처럼 보일 수도 있지만 실제로는 그렇지 않습니다. 결국 프로그래머의 의도를 보여 주므로 도로를 쉽게 수정할 수 있습니다. 개발자가 제한을 기억하고 적용해야하는 경우 모든 작업에 대한 테스트가 있어야하며 이러한 테스트 중 하나는 모델의 부모 범위가 올바르게 설정되었는지 확인해야합니다. – bensie

0

당신은 하위 도메인을 기반으로 database per account and switching the database connection를 가진 더 나은 수 있습니다.

기본 데이터베이스를 사용하려는 모델 (귀하의 경우 계정)이있는 경우 위의 링크 외에 모델에 establish connection을 포함하기 만하면됩니다.

class Account < ActiveRecord::Base 

    # Always use shared database 
    establish_connection "shared_#{RAILS_ENV}".to_sym 
+0

실행 가능한 솔루션 일 수도 있지만 계정 전체에서 보고서 (분석)를 실행하면 큰 어려움이 있습니다. 또한 마이 그 레이션 등. –

+0

네, 마이 그 레이션은 나를 위해 고통의 한 지점이었습니다. 데이터베이스 목록에 대해 마이그레이션을 실행할 수있는 솔루션을 보았지만 기억이 안납니다. – Kris

관련 문제