我正在尝试在两个现有模型User
和Dwelling
之间创建特殊关系。 Dwelling
在创建时只有一个所有者(Dwelling belongs_to :user
,User has_one :dwelling
)。但是其他用户可以作为Dwelling
添加到此Roomies
(现在没有为此创建模型,Roomie
是概念关系。)
我认为我不需要单独的模型,而是需要与现有模型建立特殊关系,但我可能错了。我认为需要使用user_id
表中的Users
进行引用。我不确定从哪里开始这个。感谢您的帮助!
例如:
Dwelling1
user_id: 1
roomies: [1, 2, 3, 4]
其中1,2,3,4是user_ids。
更新模型
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
...
答案 0 :(得分:2)
我的回答假设您只希望一个user
roomie
为dwelling
。如果您希望user
成为多个roomie
的{{1}},我认为@ ari的答案很好,但我可能会选择dwelling
而不是{{1} }}
现在回答我的问题:
我会设置它以便住所has_and_belongs_to_many
所有者和has_many :through
房间(可能包括所有者,但不一定)。
您可以将belongs_to
模型用于has_many
和User
。您不需要任何其他表格或模型,只需使用owners
和roomies
选项设置正确的关系。
在:class_name
模型中:
:foreign_key
在Dwelling
模型中:
# dwelling.rb
belongs_to :owner, :class_name => "User", :foreign_key => "owner_id"
has_many :roomies, :class_name => "User"
在User
表格中,您需要# 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
列来存储所有者的dwellings
在owner_id
表中,您需要user_id
来存储用户所在住所的users
。
在有关控制器的评论中回答您的问题:
如果您想将dwelling_id
设为新住所的所有者,请执行以下操作:
dwelling_id
如果您想将current_user
设置为新住宅的所有者和房间,请执行以下操作:
@dwelling = current_user.properties.build(params[:dwelling])
....
上面最棘手的部分是处理住宅有效并保存的情况,但由于某些不相关的原因,current_user
无法保存。根据您的应用程序,您可能希望住宅无论如何都要保存,即使您无法将@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
指定为房间。或者,您可能希望住宅不被保存 - 如果是这样,您需要使用模型事务,这有点超出了这个问题的范围。
您的控制器代码无效,因为保存住所并未实际更新current_user
记录以存储current_user
。您的代码将等同于以下内容:
current_user
请注意,永远不会保存dwelling_id
,因此@dwelling = Dwelling.new(params[:dwelling])
current_user.dwelling = @dwelling
if @dwelling.save
...
行无用。
这可能看似违反直觉,但最重要的是current_user
实际上并没有像你期望的那样在内存中设置内容。如果您从而不是正在构建的模型中保存了正在构建的模型,那么您将获得更直观的结果:
current_user.dwelling = @dwelling
但是,如果它具有验证错误,则此(默认情况下)不会保存住宅,除非您为关联启用build_dwelling
,这也超出了此问题的范围。我真的不推荐这种方法。
更新
以下是更详细的代码段:**
@dwelling = current_user.build_dwelling(params[:dwelling])
if current_user.save # This will save the dwelling (if it is valid)
当住宅成功保存时,当前用户将是所有者(数据库中的:autosave
)。但是,如果# 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
未保存,则需要确定应用程序应如何响应。在上面的例子中,我允许保存住宅(即我不回滚它的创建),但我通知用户他不能被指定为房间。发生这种情况时,很可能是应用程序中的其他代码导致了问题。您可以检查owner_id
的错误以了解原因。或者,您可以暂时使用current_user
代替current_user
进行问题排查。
完成所有这些操作的另一种方法是在current_user.save!
模型中使用current_user.save
回调。在许多方面,这将是一种更简洁,更简单的方法。但是,在after_create
无法保存的情况下捕捉案例可能比上述方法更加丑陋,具体取决于您希望如何处理它。
我认为底线是Dwelling
代码导致了一些问题。您需要诊断原因,然后确定应用程序在这种情况下应该执行的操作。有几种方法可以解决这个问题,至少包括以下内容
current_user
代替current_user.save
,以便引发异常,并且不会保存用户或住所。current_use.save!
(避免回调,验证等),而不是保存current_user。我相信您遇到的当前问题与原始问题基本无关。如果您需要进一步的帮助,最好将其作为一个单独的问题予以解决。
答案 1 :(得分:1)
您有两种可能的选择。 根据您的计划,住宅可能更清楚,而不是拥有一栋住宅的业主。那么住宅也可以有用户。您可以向User添加一个名为dwelling_id的列,然后您可以为has_many用户提供住所。
另一种选择是使用"has_many through" association。这意味着你需要创建一个跟踪这种关联的新模型,比如“Relationship.rb”,它同时属于User和Dwelling(并且两者都有列)。然后你就可以编写这样的代码:
//in Dwelling.rb
has_many :roomies, through: :relationships, source: :user
//in User.rb
has_many :dwellings, through: :relationships
这样,用户也可以加入多个住宅。
答案 2 :(得分:1)
您可以通过将Roomie ID存储为Dwelling中的列
来实现进行迁移:
class AddRoomiesToDwelling < ActiveRecord::Migration
def self.up
add_column :dwelling, :roomies, :text
end
def self.down
remove_column :dwelling, :roomies
end
end
在您的住宅模型中:
class Dwelling < ActiveRecord::Base
serialize :roomies
end
然后,您可以使用以下内容设置房间ID:
roomie_ids = [1, 2, 3, 4]
@dwelling.roomies = {:ids => roomie_ids}
@dwelling.save!
取自{em>保存数组,哈希以及this 的文本列部分中的其他不可映射对象