2

やあみんな私はあなたの貴重な助けが必要です。Ruby on Railsチュートリアルの第10章では、作成者は1つのビューに2つのコントローラーを持っています。1つのビューに2つのコントローラーがある同様のアプリを作成しましたが、2番目のコントローラーに属するメソッドをレンダリングすると、最初からパラメーターに問題が発生します。(チュートリアルでは、作成者は他のコントローラーのアクションでパラメーターを使用しません)

具体的には、UsersControllerとMicropostsControllerの2つのコントローラーがあります。また、Usersの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の内部

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

app / views / users/show.html.hamlで

- 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)1つのビューに複数のコントローラーを配置することは良い習慣ですか?ネットで矛盾する答えを見つけました。(実際、このコードがRESTfulのままであるかどうかさえわかりません)

2)1が「はい」の場合(または少なくともそれは悪い習慣ではありません)、同じことをより効率的な方法で実装できますか?私の見方では、別のコントローラーからアクションをレンダリングするたびに、変数を再定義する必要があります。

3) stackoverflowで同様のトピックを見つけました。このトピックでは、この方法を使用することを提案しています(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

このバージョンのcreateアクションを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

投稿ボタンを押すと、ブラウザに何も表示されません。さらに、users / 1ページを表示しようとすると、次のエラーが発生します(!!):

undefined method `[]' for nil:NilClass

どんな助けでも本当に価値があります!他の情報が必要な場合は私に知らせてください!

4

2 に答える 2

3
  1. 技術的には、この用語はやや紛らわしいです。デフォルトでは、コントローラーの各メソッドは同じ名前のビューファイルに対応しているため、「デフォルトのビューではないビューをレンダリングすることをお勧めしますか?」という質問を表現する方がよい場合があります。そして答えは、もちろん、それは異なります。これは、コントローラーコードを乾燥させるために一般的に使用される手法であり、それによって得られる利点がある場合は、アプリケーションで確実に使用します。実際、Railsのデフォルトのリソーススキャフォールディングによって生成されたコントローラーコードは、andメソッドでそれを使用します。Railsコアのすべてが、ベストプラクティスではないにしても、少なくとも正気の範囲内であるという議論をすることができると思います。createupdate

  2. そうは言っても、改善の機会があるかもしれません。同じことを処理する一般的な方法は、作成要求と更新要求を同じコントローラーアクションにルーティングし、同じコントローラービューを使用することです。それが不可能な場合は、少なくとも変数を再定義する必要がないことを確認してください。公式ドキュメントから:

:actionでrenderを使用することは、Railsの初心者にとって頻繁な混乱の原因です。指定されたアクションは、レンダリングするビューを決定するために使用されますが、Railsはコントローラーでそのアクションのコードを実行しません。ビューで必要なインスタンス変数は、renderを呼び出す前に現在のアクションで設定する必要があります。

  1. あなたはそれをする必要はないはずです...この状況、または私が考えることができる他の状況ではありません。Railsでそのようなスーパーハッキーを目にしたときはいつでも、何かがおそらく正しくないこと、そして同じことを処理するためのより良い方法があることを示しています。

ボーナス:すでにセットアップを担当している場所に移動する必要があり、スコープ内の変数にアクセスする必要がない場合は、リダイレクトの方がおそらく適切です。そうすれば、コントローラーロジックを複数の場所で再記述しなくてもかまいません。投稿したコードの例を次に示します。

    # 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
于 2012-11-08T01:12:14.573 に答える
0

チュートリアルの作成者が[マイクロポストの作成]アクションにDRYソリューションを実装しなかった理由は、レンダリングの代わりにredirect_toを使用すると、フォームのフラッシュエラーが失われるためだと思います。

フォームフラッシュエラーを維持するDRYソリューションが他にあるかどうかはわかりません。

于 2013-06-03T00:28:05.367 に答える