Rails 3:支持多个控制器的单一模型

时间:2011-07-25 10:07:41

标签: ruby-on-rails ruby ruby-on-rails-3

好的,我搜索了Google,API以及StackOverflow,并且没有找到真正的决定性帮助。所以这里!

我有一个名为Favorite的多态模型设置,它与用户绑定。作为收藏夹是多态的我当然可以使用这种关系允许我的用户在我的应用程序中添加几乎任何实体作为他们的收藏夹。

用户和特定模型之间的每个最喜欢的关系我希望能够调用不同的内容,例如“收藏”或“喜欢”或“朋友”。这允许我有一个不同的Controller with Views来管理这些不同的关系,以便用户和我自己更容易理解。因此,我用“朋友”更精确的概念来涵盖“收藏夹”的全局通用概念。

所以我继续创建了一个带有关联视图的Friend控制器来处理用户和系统中其他用户之间的Favorite关系。

但是我发现Rails希望我在视图和控制器之间的所有交互中传递'朋友'模型,即使我想使用收藏模型并且我得到'未初始化的常量朋友'作为错误我的看法。我如何通过这个'惯例',如何在必要时制作控制器和视图,了解我使用喜欢的模型作为我的基础模型而不是朋友?

我考虑创建一个名为'Friend'的新模型,并从'Favorite'继承它只是为了欺骗控制器,但是对我来说这似乎是浪费精力的人。那里有什么想法吗?

代码示例这是使用Favorite多态模型来ButtSlap另一个用户。每个表单部分都将User作为名为local_entity的局部变量传递。

ButtSlapController

class ButtSlapsController < AuthorizedResourceController

  def create
    @favorite = current_user.favorites.build(params[:favorite])

    respond_to do |format|
      if @favorite.save
        flash[:success] = 'butt slap successful!'
        format.html { redirect_to('/lounge') }
        # format.js   { render :action => "create_success"}
      else
        flash[:success] = 'ah poop!'
        format.html { redirect_to('/lounge') }
        # format.js   { render :action => "create_failure"}
      end
    end
  end

  def destroy
    @favorite = current_user.favorites.find(params[:id])

    respond_to do |format|
      if @favorite.destroy
        flash[:success] = 'butt slap has been successfully removed.'
        format.html { redirect_to('/lounge') }
        # format.js   { render :action => "create_success"}
      else
        flash[:success] = 'ah poop!'
        format.html { redirect_to('/lounge') }
        # format.js   { render :action => "create_failure"}
      end
    end
  end

end

创建ButtSlap

<%= form_for current_user.favorites.build, :as => :favorite, :url => butt_slaps_path do |f| %>
    <div><%= f.hidden_field :favorable_id, :value => local_entity.id %></div>
    <div><%= f.hidden_field :favorable_type, :value => local_entity.class.to_s %></div>
    <div class="actions"><%= f.submit "butt slap!" %></div>
<% end %>

删除ButtSlap

<%= form_for current_user.get_favorites(
                     {:id => local_entity.id,
                      :type => local_entity.class.to_s}),
                      :html => { :method => :delete }, :url => butt_slaps_path do |f| %>
    <div class="actions"><%= f.submit "take back" %></div>
<% end %>

1 个答案:

答案 0 :(得分:0)

这一切都证明是一个名为CanCan v1.6.4的小宝石

我一直在我的应用程序中使用CanCan进行授权,并且在您的Ability类中声明授权规则时,您可以通过模型或控制器或混合物来执行。

为了处理这个问题,我设置了2个继承自ApplicationController的根控制器。第一个'AuthorizedController'用于所有不使用Model的控制器,第二个'AuthorizedResourceController'用于所有由Model支持的控制器。

事实证明,对于我的ButtSlap控制器,我将其设置为AuthorizedResourceController,并且通过这样做,CanCan自动寻找基于控制器名称'ButtSlap'来拉取和授权集合或单个模型。但是由于我每次尝试向控制器发布时都在后端使用Favorite模型,CanCan尝试根据其约定加载其虚构模型。因此我收到了错误消息'未初始化的常量'ModelName''。

一旦我将ButtSlapController从AuthorizedResourceController切换到AuthorizedController,CanCan就不再需要根据控制器名称实例化和授权模型,而是转移到基于控制器的授权,就像每个人都说“噗”我的困惑一样为什么Rails正在寻找一个与控制器名称相关的模型已经不见了。

你真的不得不喜欢这样的错误,他们真的会扩展你的限制以及你的键盘库存(当我感到沮丧时,我倾向于抛出键盘;)