gpt4 book ai didi

ruby-on-rails - Rails 3 - 在 Controller 中处理嵌套资源查询的最佳方式?

转载 作者:数据小太阳 更新时间:2023-10-29 07:24:05 25 4
gpt4 key购买 nike

如果我从 Rails 3 中学到的一件事是,如果我在做某事时遇到困难,那么我可能做错了。所以我正在寻求帮助。

我有几个模型以多对多的关系相关。

我能够毫无问题地在模型中创建关联。我的问题在于如何构建 Controller 来处理这些关系。如果您不明白我的意思,我会尝试举个例子。

例如...

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

因此,为了缩短一点,假设我想要一个帐户的所有位置的列表。上面的路由大概是 account/1/locations。因此让我降落在 locations#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是一个很好的 gem,可以干净地处理这样的场景。由 Jose Valim(Rails 的)编写。我相信它应该与 HABTM 一起使用,但老实说,如果我尝试过它,我并不肯定。

上面的例子本质上是 inherited_resources 的工作方式,但主要是它在幕后发挥其魔力,您只在需要时才覆盖方法。如果它适用于 HABTM(我认为它应该),你可以像这样编写你当前的 Controller :

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

关于ruby-on-rails - Rails 3 - 在 Controller 中处理嵌套资源查询的最佳方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7342470/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com