在Rails,我怎么可以创建用户组作为另一个关联,如"成员:QUOT ;? [英] In Rails, how can I create group of users as another association, such as "members"?
问题描述
我想创建两个现有的模型之间的特殊关系,用户
和住房
。 A 住房
只有一个所有者(住房belongs_to的:用户
,用户HAS_ONE:蜗居
)的创建时间。但是,其他用户可以添加到这个住房
为室友
(有没有为这个创造了现在的模式,室友
是一个概念上的关系)。
我不认为我需要一个单独的模型,而是与现有机型的特殊关系,但我可能是错的。我想引用需要与 USER_ID
从用户
表中进行。我真的不知道从哪里开始这个。谢谢你的任何及所有的帮助!
例如:
Dwelling1
USER_ID:1
室友:[1,2,3,4]
其中,1,2,3,4是user_ids
更新款式
住宅示范
#dwelling.rb
住宅类和LT; ActiveRecord的::基地
attr_accessible:STREET_ADDRESS,:城市:状态:ZIP,:昵称 belongs_to的:所有者,:CLASS_NAME => 用户,:foreign_key => owner_id
的has_many:室友,:CLASS_NAME => 用户 验证:STREET_ADDRESS,presence:真
验证:城市,presence:真
验证:状态,presence:真
验证:拉链,presence:真结束
用户模型
#user.rb
类User< ActiveRecord的::基地
attr_accessible:电子邮件,:FIRST_NAME,:姓氏,:密码:password_confirmation,:拉链
has_secure_password before_save {|用户| user.email = email.downcase}
before_save:create_remember_token belongs_to的:蜗居
的has_many:属性:CLASS_NAME => 蜗居,:foreign_key => owner_id 验证:FIRST_NAME,presence:真的,长度:{最大值:50}
...
更新栖居创建动作
#dwellings_controller.rb
...
打造高清
@dwelling = current_user.properties.build(PARAMS [:住宅]) 如果@ dwelling.save
current_user.dwelling = @dwelling
如果current_user.save
闪光[:成功=呜呼你住在已创建欢迎回家!!
redirect_to的CURRENT_USER
其他
使新
结束
结束
结束
...
我的回答假设你只想要一个用户
是一个室友
在同一蜗居
。如果你想有一个用户
是一个室友
的多个蜗居
,我觉得@ ARI的回答是不错的,虽然我可能会选择 has_and_belongs_to_many
而不是的has_many:通过
。
现在我的答案是:
我设定,让一个住宅 belongs_to的
所有者和的has_many
室友(包括可能的所有者,但不一定)。
您可以使用用户
模式既为所有者
和室友
。你不需要任何额外的表或模型,你就可以使用需要设置合适的人际关系:CLASS_NAME
和:foreign_key
选项。
在你的住房
模型:
#dwelling.rb
belongs_to的:所有者,:CLASS_NAME => 用户,:foreign_key => owner_id
的has_many:室友,:CLASS_NAME => 用户
在你的用户
模型:
#user.rb
belongs_to的:蜗居#这是用户生活的地方
的has_many:属性:CLASS_NAME => 蜗居,:foreign_key => owner_id#这是用户拥有住房
在你的住房
表,则需要一个 owner_id
列来存储 USER_ID
所有者
在你的用户
表,则需要一个 dwelling_id
存储 dwelling_id
住宅的在用户的生活。
要回答你的问题在有关控制器的评论:
如果您想设置 CURRENT_USER
作为新住宅的业主,这样做:
@dwelling = current_user.properties.build(PARAMS [:住宅])
....
如果您想要安装 CURRENT_USER
作为所有者和新住宅的室友,做到这一点:
@dwelling = current_user.properties.build(PARAMS [:住宅]如果@ dwelling.save
current_user.dwelling = @dwelling
如果current_user.save
#闪光灯和重定向到这里
其他
#目前尚不清楚为什么会不救,但是你确定
#什么在这样的情况下做的。
结束
其他
...
结束
以上是处理该住宅是有效的并保存,但由于某些原因,无关的 CURRENT_USER
无法保存的情况下最棘手的部分。根据您的应用程序时,您可能希望住宅仍要保存,即使你不能分配 CURRENT_USER
作为室友。或者,您可能希望不是蜗居保存---如果是的话,你需要使用一个模型交易,这是有点超出了这个问题的范围。
您控制器code没有工作,因为节约了住宅实际上并没有更新 CURRENT_USER
记录存储 dwelling_id
。您code将等同于以下内容:
@dwelling = Dwelling.new(PARAMS [:住宅])
current_user.dwelling = @dwelling
如果@ dwelling.save
...
注意 CURRENT_USER
永远不会保存,因此 current_user.dwelling = @dwelling
行是没用的。
这似乎违反直觉,但底线是, build_dwelling
实际上不为你所期望的内存设置的东西。你会取得更直观的结果,如果你救了你正在构建的从的模型,而不是你正在构建模型:
@dwelling = current_user.build_dwelling(PARAMS [:住宅])
如果current_user.save#这将节省的住所(如果它是有效的)
不过,这(默认)将不会保存蜗居如果有验证错误,除非你把<$ C $ C>:自动保存上的关联,这也是有点超出这个问题的范围。我真的不推荐这种方法。
更新:
下面是一个更详细的code片断:**
#dwellings_controller.rb打造高清
@dwelling = current_user.properties.build(PARAMS [:住宅]) 如果@ dwelling.save
#当前用户现在是老板,但我们也想尝试分配
#他作为一个室友:
current_user.dwelling = @dwelling
如果current_user.save
闪光[:通知] =您已经成功创建了蜗居
其他
#出于某些原因,CURRENT_USER不能被指定为在一个室友
#住宅。这可能是有几个原因,如在验证
#用户模型,prevent被保存在CURRENT_USER。
闪光[:通知] =您已成功创建了一个住所,但我们不能赋予您将其作为一个室友
结束
redirect_to的CURRENT_USER
其他
#住宅无法保存,所以重新显示创建表单:
渲染:新
结束
结束
在住宅成功保存,当前用户将成为(在数据库中的 owner_id
)的所有者。但是,如果 CURRENT_USER
不保存,你需要决定你的应用程序应如何处理作出回应。在上面的例子中,我让住宅被保存(即我不回滚其创作),但我告诉自己不能被指定为一个室友用户。当发生这种情况,很可能是因为其他code在您的应用程序引起的问题。你可以检查的CURRENT_USER
错误明白。或者,你可以使用 current_user.save!
,而不是 current_user.save
暂时解决。
另一种方式来做到这一切是在住房
模型中的 after_create
回调。在许多方面,这将是一个更清洁,更简单的方式来做到这一点。然而,醒目当 CURRENT_USER
无法保存,可能会比上面的方法,甚至丑陋的情况下,根据您要如何处理它。
我认为底线是, current_user.save
code会引起一些问题。你需要诊断为什么,然后确定你的应用程序应该在这种情况下做什么。有几种方法来处理这个问题,包括至少以下
- 放在一个事务块的一切,并使用
current_use.save!
而不是current_user.save
,使一个引发异常既不用户或住宅被保存。 - 保存住宅,但告知他不是一个室友用户(如上)
- 如果不想保存CURRENT_USER的,使用
update_column
(以避免回调,验证,等等)。
我相信你所遇到的问题,目前基本上无关原来的问题。如果您需要进一步的帮助,它可能是最好打破它作为一个单独的问题。
I am trying to create a special relationship between two existing models, User
and Dwelling
. A Dwelling
has only one owner (Dwelling belongs_to :user
, User has_one :dwelling
) at the time of creation. But other Users can be added to this Dwelling
as Roomies
(there is no model created for this now, Roomie
is a conceptual relationship).
I don't think I need a separate model but rather a special relationship with the existing models, but I could be wrong. I think the reference needs to be made with user_id
from the Users
table. I'm not really sure where to start this. Thank you for any and all help!
For example:
Dwelling1
user_id: 1
roomies: [1, 2, 3, 4]
Where 1, 2, 3, 4 are user_ids.
Updated Models
Dwelling Model
# dwelling.rb
class Dwelling < ActiveRecord::Base
attr_accessible :street_address, :city, :state, :zip, :nickname
belongs_to :owner, :class_name => "User", :foreign_key => "owner_id"
has_many :roomies, :class_name => "User"
validates :street_address, presence: true
validates :city, presence: true
validates :state, presence: true
validates :zip, presence: true
end
User Model
# user.rb
class User < ActiveRecord::Base
attr_accessible :email, :first_name, :last_name, :password, :password_confirmation, :zip
has_secure_password
before_save { |user| user.email = email.downcase }
before_save :create_remember_token
belongs_to :dwelling
has_many :properties, :class_name => "Dwelling", :foreign_key => "owner_id"
validates :first_name, presence: true, length: { maximum: 50 }
...
Updated Dwelling Create Action
#dwellings_controller.rb
...
def create
@dwelling = current_user.properties.build(params[:dwelling])
if @dwelling.save
current_user.dwelling = @dwelling
if current_user.save
flash[:success] = "Woohoo! Your dwelling has been created. Welcome home!"
redirect_to current_user
else
render 'new'
end
end
end
...
My answer assumes you only want a user
to be a roomie
at one dwelling
. If you want a user
to be a roomie
at more than one dwelling
, I think @ari's answer is good, although I might opt for has_and_belongs_to_many
instead of has_many :through
.
Now for my answer:
I would set it up so that a dwelling belongs_to
an owner and has_many
roomies (including possibly the owner, but not necessarily).
You can use the User
model both for owners
and roomies
. You don't need any additional tables or models, you just need to setup the proper relationships by using the :class_name
and :foreign_key
options.
In your Dwelling
model:
# dwelling.rb
belongs_to :owner, :class_name => "User", :foreign_key => "owner_id"
has_many :roomies, :class_name => "User"
In your User
model:
# user.rb
belongs_to :dwelling # This is where the user lives
has_many :properties, :class_name => "Dwelling", :foreign_key => "owner_id" # This is the dwellings the user owns
In your dwellings
table you need an owner_id
column to store the user_id
of the owner
In your users
table you need a dwelling_id
to store the dwelling_id
of the dwelling where the user lives.
To answer your question in the comments regarding the controller:
If you want to setup current_user
as the owner of the new dwelling, do this:
@dwelling = current_user.properties.build(params[:dwelling])
....
If you want to setup the current_user
as the owner AND a roomie of the new dwelling, do this:
@dwelling = current_user.properties.build(params[:dwelling]
if @dwelling.save
current_user.dwelling = @dwelling
if current_user.save
# flash and redirect go here
else
# It's not clear why this wouldn't save, but you'll to determine
# What to do in such a case.
end
else
...
end
The trickiest part of above is handling the case that the dwelling is valid and saves, but for some unrelated reason the current_user
can't be saved. Depending on your application, you may want the dwelling to save anyway, even if you can't assign the current_user
as a roomie. Or, you might want the dwelling not to be saved --- if so, you'd need to use a model transaction, which is bit beyond the scope of this question.
Your controller code didn't work because saving the Dwelling doesn't actually update the current_user
record to store the dwelling_id
. Your code would be equivalent to the following:
@dwelling = Dwelling.new(params[:dwelling])
current_user.dwelling = @dwelling
if @dwelling.save
...
Note that current_user
is never saved, so the current_user.dwelling = @dwelling
line is useless.
This might seem counter-intuitive, but the bottom line is that build_dwelling
isn't actually setting up things in memory as you might expect. You'd achieve more intuitive results if you saved the model you're building from rather than the model you're building:
@dwelling = current_user.build_dwelling(params[:dwelling])
if current_user.save # This will save the dwelling (if it is valid)
However, this (by default) won't save the dwelling if it has validation errors unless you turn :autosave
on for the association, which is also a bit beyond the scope of this question. I really wouldn't recommend this approach.
Update:
Here is a more detailed code snippet:**
# dwellings_controller.rb
def create
@dwelling = current_user.properties.build(params[:dwelling])
if @dwelling.save
# The current user is now the owner, but we also want to try to assign
# his as a roomie:
current_user.dwelling = @dwelling
if current_user.save
flash[:notice] = "You have successfully created a dwelling"
else
# For some reason, current_user couldn't be assigned as a roomie at the
# dwelling. This could be for several reasons such as validations on the
# user model that prevent the current_user from being saved.
flash[:notice] = "You have successfully created a dwelling, but we could not assign you to it as a roomie"
end
redirect_to current_user
else
# Dwelling could not be saved, so re-display the creation form:
render :new
end
end
When a dwelling saves successfully, the current user will be the owner (owner_id
in the database). However, if the current_user
doesn't save, you'll need to decide how your application should respond to that. In the example above, I allow the dwelling to be saved (i.e. I don't rollback its creation), but I inform the user that he couldn't be assigned as a roomie. When this happens, it's most likely other code in your application causing the problem. You could examine the errors of current_user
to see why. Or, you could use current_user.save!
instead of current_user.save
temporarily to troubleshoot.
Another way to do all of this is with an after_create
callback in the Dwelling
model. In many ways that would be a cleaner and simpler way to do it. However, catching the case when the current_user
can't be saved could be even uglier than the method above, depending on how you want to handle it.
I believe the bottom line is that the current_user.save
code is causing some problems. You'll need to diagnose why, and then determine what your application should do in that case. There are several ways to handle this, including at least the following
- Put everything in a transaction block, and use
current_use.save!
instead ofcurrent_user.save
so that an exception is raised and neither the user or dwelling is saved. - Save the dwelling, but inform the user that he isn't a roomie (As above)
- Instead of saving the current_user, use
update_column
(which avoids callbacks, validations, etc.).
I believe the current problems you're experiencing are essentially unrelated to the original question. If you need further assistance, it might be best to break it off as a separate question.
这篇关于在Rails,我怎么可以创建用户组作为另一个关联,如&QUOT;成员:QUOT ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!