所以我有一个User
模型,一个Building
模型和一个MaintenanceRequest
模型。
用户has_many :maintenance_requests
,但belongs_to :building
。
维护请求belongs_to :building
和belongs_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_id
和building_id
:
permitted_mr_params.merge(user_id: current_user.id, building_id: current_user.building_id)
@maintenance_request = MaintenanceRequest.create(permitted_mr_params)
或者,如果您不关心批量分配,请将user_id
和building_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
时,将相应地设置建筑物