2010-01-15 103 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結尾,然後獲取該部分之前找到相關記錄。