【发布时间】:2014-11-11 15:41:07
【问题描述】:
这和我的last quesion about unsaved objects有点关系,不过现在更多的是关于如何使用rails的具体问题。
我拥有的模型是:
class User < ActiveRecord::Base
has_many :project_participations
has_many :projects, through: :project_participations, inverse_of: :users
end
class ProjectParticipation < ActiveRecord::Base
belongs_to :user
belongs_to :project
enum role: { member: 0, manager: 1 }
end
class Project < ActiveRecord::Base
has_many :project_participations
has_many :users, through: :project_participations, inverse_of: :projects
accepts_nested_attributes_for :project_participations
end
使用这个模型,当我创建一个新项目时,我可以通过一个表单(fields_for 等)来完成,然后我可以在控制器中调用update_attributes。因此,如果我已经在数据库中有用户,我可以这样做:
u = Users.create # save one user in database (so we have at least one saved user)
p = Project.new
# add the user to the project as a manager
# the attributes could come from a form with `.fields_for :project_participations`
p.update_attributes(project_participations_attributes: [{user_id: u.id, role: 1}])
=> true
这工作正常,直到我想对项目的users 做点什么。例如,我想添加一个验证,一个项目必须至少有一个user:
class Project < ActiveRecord::Base
...
validates :users, presence: true # there must be at least one user in a project
...
end
现在给出:
u = Users.create
p = Project.new
p.update_attributes(project_participations_attributes: [{user_id: u.id, role: 1}])
=> false
p.errors
=> #<ActiveModel::Errors:... @base=#<Project id: nil>, @messages={:users=>["can't be blank"]}>
p.users
=> #<ActiveRecord::Associations::CollectionProxy []>
p.project_participations
=> #<ActiveRecord::Associations::CollectionProxy [#<ProjectParticipation id: nil, user_id: 1, project_id: nil>]>
所以在未保存的projects 上,.users 为空。这已经困扰了我(见my last quesion about unsaved objects)。但在这种情况下,我现在当然可以通过 validates :project_participations, presence: true 而不是 validates :users, presence: true 来解决这个问题,它的含义应该相同。
但这意味着我永远不应该使用.users 方法(在任何帮助器、模型、视图中,...),除非我完全确定我使用的是已保存的对象。这实际上使 .users 方法无法使用(就像验证用户的存在一样)。
如果我像这样调用update_attributes,验证会起作用并且会保存:
p.update_attributes(users: [u])
这样,它会自行创建project_participation,因此p.users 可以按预期工作。但是在这里我无法为该用户的project_participation 设置任何类似role 的数据。
所以我的问题是:无论对象是否保存,我都可以使.users 方法工作(我认为不是)吗?但是,我怎样才能将用户作为经理/成员添加到未保存的项目并使用未保存的项目?
我希望我的问题很清楚。
【问题讨论】:
标签: ruby-on-rails validation activerecord has-many-through