在Rails,我怎么可以创建用户组作为另一个关联,如"成员:QUOT ;? [英] In Rails, how can I create group of users as another association, such as "members"?

查看:96
本文介绍了在Rails,我怎么可以创建用户组作为另一个关联,如"成员:QUOT ;?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建两个现有的模型之间的特殊关系,用户住房。 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会引起一些问题。你需要诊断为什么,然后确定你的应用程序应该在这种情况下做什么。有几种方法来处理这​​个问题,包括至少以下


  1. 放在一个事务块的一切,并使用 current_use.save!而不是 current_user.save ,使一个引发异常既不用户或住宅被保存。

  2. 保存住宅,但告知他不是一个室友用户(如上)

  3. 如果不想保存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

  1. Put everything in a transaction block, and use current_use.save! instead of current_user.save so that an exception is raised and neither the user or dwelling is saved.
  2. Save the dwelling, but inform the user that he isn't a roomie (As above)
  3. 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆