2010-01-15 100 views
3

我有一个模型Report,它是多态的。 我的网站上有很多itens可能有很多。Rails多态关联加上路由

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

在我的路线,即时通讯做这样的事情

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]。我可以做所有关系的情况下,但它似乎并没有一个干净的解决方案...

具有多态性关联将是最好的,有没有如何?

回答

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

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

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

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结尾,然后获取该部分之前找到相关记录。