加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – Rails 3 – 处理控制器中嵌套资源查询的最佳方

发布时间:2020-12-17 03:53:04 所属栏目:百科 来源:网络整理
导读:如果我对Rails 3了解的一件事是,如果我很难做某事,我可能做错了.所以我正在寻求帮助. 我有一些与多对多关系相关的模型. 我能够在没有问题的情况下在模型中创建关联.我的问题在于如何构建控制器以使用这些关系.如果你不知道我要去哪里,我会试着举个例子. 例如
如果我对Rails 3了解的一件事是,如果我很难做某事,我可能做错了.所以我正在寻求帮助.

我有一些与多对多关系相关的模型.

我能够在没有问题的情况下在模型中创建关联.我的问题在于如何构建控制器以使用这些关系.如果你不知道我要去哪里,我会试着举个例子.

例如…

class Account < ActiveRecord::Base
    has_many :locations
end

class Contact < ActiveRecord::Base
    has_many :locations
end

class Location < ActiveRecord::Base
    has_and_belongs_to_many :accounts
    has_and_belongs_to_many :contacts
end

假设我有上述型号.这将是我的资源……

resources :accounts do
    resources :locations
end

resources :contacts do
    resources :locations
end

resources :locations do
    resources :accounts
    resources :contacts
end

所以为了缩短这一点,我想说我想要一个帐户所有位置的列表.上述路线可能是账号/ 1 /位置.因此登陆我的位置#index.

希望我在这一点上没有搞砸我的例子,但是建立这个行动的最佳方法是什么,因为它确实有多个工作……至少是帐户,联系人和所有地点的位置.

所以我最终得到这样的东西……

class LocationController < ApplicationController
    def index
        if params[:account_id]
            @locations = Location.find_all_by_account_id(params[:account_id])
        elsif params[:contact_id]
            @locations = Location.find_all_by_contact_id(params[:account_id])
        else
            @locations = Location.all
        end

        respond_with @locations
    end
end

更新#1:澄清一下,因为我得到一些答案,表明我改变了我的模型关系.我正在使用遗留系统,在此系统中我无法改变关系.最终我的目标是清理数据库和关系,但现在我不能.所以我需要找到一个适用于此配置的解决方案.

解决方法

你当前的方法不是DRY,如果说你想在索引上加入额外的范围,会让你头疼.例如分区,排序或按字段搜索.

考虑一个替代方案:注意你的if / elsif / else条件本质上是如何找到发送find的查找范围?为什么不把这个责任转移到一个方法呢?从而简化您的操作并删除冗余代码.

def index
  respond_with collection
end

def show
  respond_with resource
end

protected

# the collection,note you could apply other scopes here easily and in one place,# like pagination,search,order,and so on.
def collection
  @locations ||= association.all
  #@locations ||= association.where(:foo => 'bar').paginate(:page => params[:page])
end

# note that show/edit/update would use the same association to find the resource
# rather than the collection
def resource
  @location ||= association.find(params[:id])
end

# if a parent exists grab it's locations association,else simply Location
def association
  parent ? parent.locations : Location
end

# Find and cache the parent based on the id in params. (This could stand a refactor)
#
# Note the use of find versue find_by_id.  This is to ensure a record_not_found
# exception in the case of a bogus id passed,which you would handle by rescuing
# with 404,or whatever.
def parent
  @parent ||= begin
    if id = params[:account_id]
      Account.find(id)
    elsif id = params[:contact_id]
      Contact.find(id)
    end
  end
end

inherited_resources是一个很好的宝石,可以干净地处理这样的场景.由Jose Valim(Rails)撰写.我相信它应该与HABTM一起工作,但说实话,如果我曾经尝试过,我并不积极.

上面的例子基本上是inherited_resources的工作原理,但大多数它在幕后工作,你只需要覆盖方法.如果它适用于HABTM(我认为它应该),你可以编写你当前的控制器,如下所示:

class LocationController < InheritedResources::Base
  belongs_to :contact,:account,:polymorphic => true,:optional => true
end

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读