Rails多态关联加路由

时间:2010-01-15 13:59:42

标签: ruby-on-rails routes polymorphic-associations

我有一个模型,报告,这是多态的。 在我的网站上有这么多的itens可能有很多。

我希望有一个通用的控制器来发布它。 它是一个非常简单的模型,只有一条短信和关联。

在我的路线中,我正在做类似

的事情
map.resources :users, :has_many => [ :reports ]
map.resources :posts, :has_many => [ :reports ]

但在我的reports_controller中,我希望得到它来自的关系。

像:

before_filter :get_reportable

def get_reportable
   reportable = *reportable_class*.find params[:reportable_id]
end

这可能吗?

我怎样才能获得reportable_class和reportable_id?

当来自用户控制器时,我可以得到params [:user_id],或者当它来自帖子时,我可以得到params [:post_id]。我可以对所有关系做一个案例,但它看起来根本不是一个干净的解决方案......

具有多态关联将是最好的,有什么方法?

2 个答案:

答案 0 :(得分:4)

如果您有一个控制器通过两个不同的路径处理请求,那么您需要让它知道它将被调用的上下文。您经常会看到很多类似的代码:

before_filter :load_reportable

def load_reportable
  if (params[:user_id])
    @user = User.find(params[:user_id])
    @reportable = @user
  elsif (params[:post_id])
    @post = Post.find(params[:post_id])
    @reportable = @post
  end
rescue ActiveRecord::RecordNotFound
  render(:partial => 'not_found', :status => :not_found)
  return false
end

由于您正在使用多态关联,因此您可能会执行以下操作:

before_filter :load_reportable

def load_reportable
  unless (@reportable = @report.reportable)
    # No parent record found
    render(:partial => 'not_found', :status => :not_found)
    return false
  end

  # Verify that the reportable relationship is expressed properly
  # in the path.

  if (params[:user_id])
    unless (@reportable.to_param == params[:user_id])
      render(:partial => 'user_not_found', :status => :not_found)
      return false
    end
  elsif (params[:post_id])
    unless (@reportable.to_param == params[:post_id])
      render(:partial => 'post_not_found', :status => :not_found)
      return false
    end
  end
end

这种方法的问题在于,您有一个控制器为两条完全不同的路径提供服务,这就是生成错误消息,例如“找不到用户”和“找不到帖子”。例如,如果你没有从Users :: BaseController继承,这可能很难做到。

在许多情况下,创建两个独立的“报告”控制器比较容易,例如用户/报告和帖子/报告,其中从模块导入任何常用功能。这些控制器通常从执行加载和错误处理的基本控制器继承。基本控制器还可以建立布局,页面标题等,而无需为每个子资源控制器重新实现此功能。

另一种方法是解除报告并将其作为自己的控制器运行,其中与“可报告”记录的关系几乎无关紧要。

答案 1 :(得分:0)

或尝试:

before_filter :get_reportable

def get_reportable
  params.each do |name, value|
    if name =~ /(.+)_id$/
      @reportable = $1.classify.constantize.find(value)
    end
  end
end

它正在通过所有参数并试图找到一个以_id结尾,然后在部分之前抓住它并找到相关记录。