3

私はそのような2つのモデルを持っています

class Plan < ActiveRecord::Base
    belongs_to :profile

class Profile < ActiveRecord::Base
    has_many :plans

そして次のようなルート:(私はする必要があります)

resources :profiles do
    resources :plans
end
resources :plans

したがって、 ruby-on-railsのフォローアップ-ネストされたリソースの問題、私はこのようなPLANSインデックスコントローラーを作成して、NESTEDとUNESTEDを同時に動作させました(今のところ私が見つけた唯一の方法):

def index
  if params.has_key? :profile_id
    @profile = Profile.find(params[:profile_id])
    @plans = @profile.plans
  else
    @plans = Plan.all
end

これにはよりクリーンなアプローチがありますか?

私はこの状況で別のモデルを持っています、そしてすべてのアクションをすべてのコントローラーに入れてこのように振る舞うのは面倒です。

4

1 に答える 1

0

あなたは私にアイデアを与えました:

models / user.rb:

class User < ActiveRecord::Base
  has_many :posts
  attr_accessible :name
end

models / post.rb:

class Post < ActiveRecord::Base
  belongs_to :user
  attr_accessible :title, :user_id
end

コントローラ/posts_controller.rb:

class PostsController < ApplicationController
  belongs_to :user # creates belongs_to_user filter

  # @posts = Post.all # managed by belongs_to_user filter

  # GET /posts
  # GET /posts.json
  def index
    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @posts }
    end
  end
end

そして今、実体:

controllers / application_controller.rb:

class ApplicationController < ActionController::Base
  protect_from_forgery

  def self.belongs_to(model)
                                                      # Example: model == :user
    filter_method_name = :"belongs_to_#{model}_index" # :belongs_to_user_index
    foreign_key        = "#{model}_id"                # 'user_id'
    model_class        = model.to_s.classify          # User

    class_eval <<-EOV, __FILE__, __LINE__ + 1
      def #{filter_method_name}                                                # def belongs_to_user_index
        if params.has_key? :'#{foreign_key}'                                   #   if params.has_key? :user_id
          instance_variable_set :"@#{model}",                                  #     instance_variable_set :"@user",
                                #{model_class}.find(params[:'#{foreign_key}']) #                           User.find(params[:user_id])
          instance_variable_set :"@\#{controller_name}",                       #     instance_variable_set :"@#{controller_name}",
                                @#{model}.send(controller_name.pluralize)      #                           @user.send(controller_name.pluralize)
        else                                                                   #   else
          instance_variable_set :"@\#{controller_name}",                       #     instance_variable_set :"@#{controller_name}",
                                controller_name.classify.constantize.all       #                           controller_name.classify.constantize.all
        end                                                                    #   end
      end                                                                      # end
    EOV

    before_filter filter_method_name, only: :index # before_filter :belongs_to_user_index, only: :index
  end
end

Rubyメタプログラミングの概念がある場合、コードを理解するのは複雑ではありません。コントローラー名と関連付けから名前を推測するインスタンス変数を宣言するbefore_filterを宣言します。複数インスタンス変数バージョンを使用する唯一のアクションであるインデックスアクションに対してのみ実装されますが、他のアクションのフィルターバージョンを簡単に記述できるはずです。

于 2013-01-25T15:16:54.617 に答える