Ruby on Rails Association 构建并分配 2 个相关关联



所以我有一个User模型,一个Building模型和一个MaintenanceRequest模型。

用户has_many :maintenance_requests,但belongs_to :building

维护请求belongs_to :buildingbelongs_to: user

我正在尝试弄清楚如何发送新的,然后创建维护请求。

我想做的是:

@maintenance_request = current_user.building.maintenance_requests.build(permitted_mr_params)
=> #<MaintenanceRequest id: nil, user_id: 1, building_id: 1> 

并将用户和建筑物设置为其父关联的新维护请求。

我要做的是:

@maintenance_request = current_user.maintenance_requests.build(permitted_mr_params)
@maintenance_request.building = current_user.building

如果我能获得维护请求以根据用户的建筑物设置其建筑物,那就太好了。

显然,我可以解决这个问题,但我真的很欣赏语法糖。

来自has_many文档

您可以将第二个参数范围作为可调用对象(即 proc 或 lambda(传递,以检索一组特定的记录或在访问关联的集合时自定义生成的查询。

class User < ActiveRecord::Base
  has_many :maintenance_requests, ->(user){building: user.building}, through: :users
end

然后,您想要的一行应该"正常工作"current_user.building.maintenance_requests.build(permitted_mr_params)

或者,如果您使用的是 cancancan,您可以在能力文件中添加哈希条件

can :create, MaintenanceRequest, user: @user.id, building: @user.building_id

在我看来,我认为你提出的方法很好。这是一行额外的代码,但实际上并没有增加控制器的复杂性。

另一种选择是合并请求参数中的user_idbuilding_id

permitted_mr_params.merge(user_id: current_user.id, building_id: current_user.building_id)
@maintenance_request = MaintenanceRequest.create(permitted_mr_params)

或者,如果您不关心批量分配,请将user_idbuilding_id设置为表单中的隐藏字段。但是,我没有看到巨大的好处,因为您必须将参数列入白名单。

我的方法是跳过

maintenance_request belongs_to :building

因为它已经通过用户属于它。相反,您可以定义一个方法

class MaintenanceRequest
    belongs_to :user
    def building
        user.building
    end
    #more class stuff
end

此外,在建筑类中

class Building
     has_many :users
     has_many :maintenance_requests,  through: :users
    #more stuff
end

因此,您可以完全省略与maintenance_request的显式构建关联

更新由于用户可以跨建筑物移动,因此您可以使用回调设置自动行为。这项工作将像你一样完成,但以更Railsey的方式完成。

class MaintenanceRequest
     #stuff
     before_create {
         building=user.building
     }
end

因此,当您为用户创建maintenance_request时,将相应地设置建筑物

最新更新