在创建/更新期间跳过关联模型中某些成员的验证

发布于 2024-12-20 12:52:45 字数 1307 浏览 2 评论 0原文

我有以下 4 个模型

Hotel (name)
  has_one :address
  has_one :contact
  has_one :bank_account
  validates_presence_of :name
  def build_dependencies
    build_contact
    build_address
    build_bank_account
  end

Address (phone, street_address, hotel_id)
  belongs_to :hotel
  validates_presence_of :phone, :street_address

Contact (name, email, hotel_id)
  belongs_to :hotel
  validates_presence_of :name, :email

BankAccount (name, number, hotel_id)
  belongs_to :hotel
  validates_presence_of :name, :number

在用于创建酒店的表单中,我为联系人模型输入姓名和电子邮件,但为地址模型仅输入电话号码。

HotelController#new
  @hotel = Hotel.new
  @hotel.build_dependencies #this creates empty Contact and Address to generate the form fields
  #render the form to create the hotel

HotelController#create
  #receive form data
  @hotel = Hotel.new
  @hotel.build_dependencies
  @hotel.save :validate => false
  @hotel.attributes = params[:hotel]
  @hotel.save :validate => false

这是我能够创建带有联系信息、电话地址和空银行帐户的酒店的唯一方法。我必须

@hotel.save :validate => false

第一次调用来保存 Hotel 实例,其中包含 BankAccount、Address、Contact 的空白实例。然后我必须更新联系人和地址的属性,然后

@hotel.save :validate => false

确保原始表单数据按预期完全保存。

毫无疑问,这是一段非常糟糕的代码。谁能告诉我如何清理这个?

I have the following 4 models

Hotel (name)
  has_one :address
  has_one :contact
  has_one :bank_account
  validates_presence_of :name
  def build_dependencies
    build_contact
    build_address
    build_bank_account
  end

Address (phone, street_address, hotel_id)
  belongs_to :hotel
  validates_presence_of :phone, :street_address

Contact (name, email, hotel_id)
  belongs_to :hotel
  validates_presence_of :name, :email

BankAccount (name, number, hotel_id)
  belongs_to :hotel
  validates_presence_of :name, :number

In a form used to create a Hotel, I take input for both name and email for the Contact model but only phone for the Address model.

HotelController#new
  @hotel = Hotel.new
  @hotel.build_dependencies #this creates empty Contact and Address to generate the form fields
  #render the form to create the hotel

HotelController#create
  #receive form data
  @hotel = Hotel.new
  @hotel.build_dependencies
  @hotel.save :validate => false
  @hotel.attributes = params[:hotel]
  @hotel.save :validate => false

This is the only way I was able to create a Hotel with contact information, phone from address and empty bank account. I had to call

@hotel.save :validate => false

the first time to save the Hotel instance with blank instances of BankAccount, Address, Contact. Then I had to update_attributes on contact and address and then

@hotel.save :validate => false

to ensure that the original form data got saved completely as expected.

This, beyond doubt, is a very bad piece of code. Can anyone tell me how to clean this up?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

聆听风音 2024-12-27 12:52:46

您可以使用过滤器(即 after_create)在保存 @hotel 变量后调用关联模型来创建关联记录。

我碰巧面临同样的问题,这是我的解决方案。抱歉,这么长时间后这可能没有帮助,但对未来的用户来说会有好处。

class User < ActiveRecord::Base
has_one :bank_account

# Filter -- After Creation
after_create :create_default_bank_account

def create_default_bank_account
  self.build_bank_account
  self.bank_account.save(:validate=>false) 
  # :validate=>false must be called on the bank_account's save. I made the mistake of trying to save the user. =(
end

这样,您可以从 create 操作中创建空行,恕我直言,该操作应该属于模型。然后,您可以使用编辑操作让用户“创建”银行帐户条目。使用它,您只需要一个标准的创建操作(例如由rails gscaffold_controller生成)。

更新:回答后我重新阅读了您的问题,发现自己更加困惑。我假设您想要呈现一个表单,其中用户不需要立即输入银行帐户,而是稍后在另一个页面上进行编辑。

You can use a filter, namely the after_create to call the associated model to create associated records after saving of the @hotel variable.

I happen to be facing the same problem and here's my solution. Sorry this probably is not helpful after such a long while but it'll be good for future users.

class User < ActiveRecord::Base
has_one :bank_account

# Filter -- After Creation
after_create :create_default_bank_account

def create_default_bank_account
  self.build_bank_account
  self.bank_account.save(:validate=>false) 
  # :validate=>false must be called on the bank_account's save. I made the mistake of trying to save the user. =(
end

This way, you can take the empty row creation out of the create action, which IMHO, should belong to the Model. You can then use the edit action to let users "create" the bank account entry. Using this, you only need a standard create action (e.g. generated by rails g scaffold_controller).

Update: I re-read your question after answering and found myself to be more confused. I assume you want to render a form where the user is not expected to enter the bank account immediately but edit it later on another page.

我恋#小黄人 2024-12-27 12:52:46
Address
  validates_presence_of :phone, :on => :create, :if => proc { |u| u.creating_hotel? }
  validates_presence_of :street, :phone, :on => :update

Contact
  validates_presence_of :name, :email :on => :update

def creating_hotel?
  addressable_type == 'Hotel'
end

用户仅在创建酒店后才能看到 :street, :name, :email 字段,而在创建过程中会看到 :phone 字段。

Address
  validates_presence_of :phone, :on => :create, :if => proc { |u| u.creating_hotel? }
  validates_presence_of :street, :phone, :on => :update

Contact
  validates_presence_of :name, :email :on => :update

def creating_hotel?
  addressable_type == 'Hotel'
end

The user sees the :street, :name, :email fields only after the hotel is created and :phone during the creation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文