2012-11-07 2 views
3

안녕 얘들 아, 네 도움이 필요해. Ruby on Rails tutorial의 10 장에서 작성자는 2 개의 컨트롤러를 한 번에 볼 수 있습니다. 나는 두 번째 컨트롤러에 속한 메서드를 렌더링 할 때 첫 번째 컨트롤러에서 두 개의 컨트롤러가있는 비슷한 응용 프로그램을 빌드합니다. 첫 번째 컨트롤러의 문제는 params에 문제가 있습니다. (자습서에서는 작성자가 다른 컨트롤러의 동작에 매개 변수를 사용하지 않습니다.)하나의보기에서 여러 컨트롤러 (레일 MVC에서 루비)

특히 2 개의 컨트롤러가 있습니다 : UsersController 및 MicropostsController. 또한 사용자의 show.html.haml 페이지에서 두 개의 컨트롤러를 사용합니다. 사용자의 마이크로 포스트를 표시하는 UsersController와 사용자가 새로운 마이크로 포스트를 만들 수 있도록 MicropostsController를 사용합니다.

내부 MicropostsController :

def create 
    @micropost = current_user.microposts.build(params[:micropost]) 
    if @micropost.save 
    flash[:success] = "Micropost created!" 
    redirect_to user_path(current_user) 
    else 
    #render text: renderActionInOtherController(UsersController,:show, {:id => 1}) 
    @user = User.find(current_user) 
    @microposts = @user.microposts.paginate(page: params[:page]) 
    render 'users/show' 
    end 
end 

내부 UsersController 응용 프로그램/뷰/사용자/show.html.haml에서

def show 
    @user = User.find(params[:id]) 
    @microposts = @user.microposts.paginate(page: params[:page]) 
    @micropost = current_user.microposts.build if signed_in? 
end 

- provide(:title, @user.name) 
.users_page 
    .row 
    %aside.span4 
     - if !signed_in? 
     %section 
      %h1 
      = gravatar_for @user 
      = @user.name 
     - else 
     %section 
      = render 'shared/user_info' 
     %section 
      = render 'shared/micropost_form' 

    .span8 
     - if @user.microposts.any? 
     %h3 Microposts (#{@user.microposts.count}) 
     %ol.microposts 
      = render @microposts 
     = will_paginate @microposts 
다음과 같이

그래서 기본적으로 내 질문에 요약 :

1) 하나의보기에 여러 개의 컨트롤러가있는 것이 좋습니다. 나는 그물에서 모순되는 대답을 발견했다. (실제로이 코드가 RESTful인지 확실하지 않은 경우)

2) 1이 예 (또는 적어도 나쁜 습관은 아닙니다) 인 경우 더 효율적인 방법으로 같은 것을 구현할 수 있습니까? 내가 보는 방식 때문에 다른 컨트롤러에서 동작을 렌더링 할 때마다 변수를 다시 정의해야합니다.

3) 나는이 방법을 사용하는 것을 제안하는 stackoverflow에서 similar 주제를 발견했다. (정확히 내가 RoR에서 새로운 것부터 얻지 못한 것을 얻는다.) 나는 후 버튼을 누르면 때

def renderActionInOtherController(controller,action,params) 
    controller.class_eval{ 
    def params=(params); @params = params end 
    def params; @params end 
    } 
    c = controller.new 
    c.request = @_request 
    c.response = @_response 
    c.params = params 
    c.send(action) 
    c.response.body 
end 

내가 MicropostsController 내부 조치를 생성의이 버전을 사용하는 경우

,

def create 
    @micropost = current_user.microposts.build(params[:micropost]) 
    if @micropost.save 
    flash[:success] = "Micropost created!" 
    redirect_to user_path(current_user) 
    else 
    render text: renderActionInOtherController(UsersController,:show, {:id => 1}) 
    #@user = User.find(current_user) 
    #@microposts = @user.microposts.paginate(page: params[:page]) 
    #render 'users/show' 
    end 
end 

나는 브라우저에서 완전히 아무 것도 얻을 수 없습니다. 또한 사용자/1 페이지를 보려고하면 다음과 같은 오류가 발생합니다 (!!) :

undefined method `[]' for nil:NilClass 

어떤 도움도 정말 유용 할 것입니다! 다른 정보가 필요하면 알려주십시오!

답변

4
  1. 기술적으로이 용어는 다소 혼란 스럽습니다. 기본적으로 컨트롤러의 각 메소드는 비슷하게 이름이 지정된보기 파일에 해당하므로 질문을 으로 말하면 "기본보기가 아닌보기를 렌더링하는 것이 좋습니까?" 그리고 대답은 물론 다릅니다. 이것은 컨트롤러 코드를 DRY하는 데 일반적으로 사용되는 기술이며, 어플리케이션에서 얻을 수있는 장점이 있다면 확실히 사용할 것입니다. 실제로, uses it 레일의 기본 리소스 스캐 폴딩에서 생성 된 컨트롤러 코드는 createupdate 메쏘드입니다. 제 생각에는 Rails 코어의 모든 것이 적어도 모범 사례가 아니더라도 적어도 정당성의 한계 내에서 가능하다는 주장을 할 수 있다고 생각합니다.

  2. 그렇다면 개선의 기회가있을 수 있습니다.동일한 작업을 처리하는 일반적인 방법은 생성 및 업데이트 요청을 동일한 컨트롤러 작업으로 라우팅하고 동일한 컨트롤러보기를 사용하는 것입니다. 이것이 가능하지 않다면 적어도 변수를 재정의 할 필요가 없다는 것을 확신하십시오. official documentation에서 :

렌더링 사용 : 작업은 레일 이민자를위한 혼란의 빈번한 소스입니다. 지정된 동작은 에 대한 뷰를 결정하는 데 사용되지만 레일에서는 컨트롤러에서 해당 동작에 대한 코드를 실행하지 않습니다. 뷰에서 필요한 인스턴스 변수는 렌더링을 호출하기 전에 을 현재 작업에 설정해야합니다.

  1. 당신은 아니이 상황, 또는 내가 생각할 수있는 다른 하나 ... 그렇게 할 필요가 없습니다. 언제든지 Rails에서 그와 같은 슈퍼 해커 (super hackey)가 보이는 것은 아마도 무언가가 옳지 않다는 표시이며, 같은 것을 처리하는 데 더 좋은 방법이 있다는 것입니다.

보너스 : 당신은 이미 그 자체를 설정하는 담당 어딘가에 갈 필요가, 당신은 범위 변수에의 액세스를 필요로하지 않는 경우, 리디렉션 아마 더 나은 선택입니다. 그렇게하면 여러 곳에서 컨트롤러 로직을 다시 설명 할 필요가 없습니다.

# inefficient and not DRY 
    @user = User.find(current_user) 
    @microposts = @user.microposts.paginate(page: params[:page]) 
    render 'users/show' 

    # does the same thing as above (in this case) 
    redirect_to users_path 
0

난 그냥 사람이 대신 redirect_to를 사용하는 경우 때문에 튜토리얼 작성자가 작성 Microposts 행동을 덜 DRY 솔루션을 구현하는 이유에 대한 정당화가 믿는 것을 추가하고 싶습니다 : 여기에 귀하의 게시 된 코드의 예입니다 렌더링하면 양식의 플래시 오류가 손실됩니다.

양식 플래시 오류를 유지하는 더 DRY 솔루션이 있는지 확실하지 않습니다.