3

我有一个模型,报告,它是多态的。我网站上的很多项目可能有很多。

我想有一个通用控制器来发布它。它是一个非常简单的模型,只有一个文本消息和关联。

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

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

但在我的报告控制器中,我想从它的来源中得到关系。

像:

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]。我可以为所有关系做一个案例,但这似乎根本不是一个干净的解决方案......

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

4

2 回答 2

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 继承,这可能会很棘手。

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

另一种方法是分离报告并让它作为自己的控制器运行,其中与“可报告”记录的关系大多无关紧要。

于 2010-01-15T15:41:59.903 回答
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结尾的参数,然后在部分之前抓取它并找到相关记录。

于 2012-01-09T11:14:35.910 回答