Rails 3-嵌套对象表单(重用地址模型)

时间:2010-11-12 11:34:14

标签: mysql ruby-on-rails activerecord

我无法解决这个问题。

我有商业模式和地址模型。为了使事情变得更复杂,我也有一个位置模型。企业可以有多个位置,但只有一个邮寄地址。

这是一个简单的对象图表。

组织
-name
-MailingAddress

位置
- 商务
-name
-address

我想重新使用商家和地址模型的地址模型。位置。我需要做些什么呢。如果它有帮助,我正在使用MySQL。

首先我如何构建模型?我是否需要has_many:location,:business(适用于位置/业务)? 然后,如何将用于创建地址的表单嵌套到新的业务/位置表单中。

谢谢!

2 个答案:

答案 0 :(得分:8)

我将从一些基本的模型代码开始,然后转到控制器,然后进行查看。

首先是模特:

#app/models/business.rb
class Business < ActiveRecord::Base
  has_one :mailing_address, :class_name => "Address", :dependent => :destroy
  accepts_nested_attributes_for :mailing_address

  has_many :locations
  accepts_nested_attributes_for :locations
end

#app/models/location.rb
class Location < ActiveRecord::Base
  has_one :address, :dependent => :destroy
  accepts_nested_attributes_for :address

  belongs_to :business
end

#app/models/address.rb
class Address < ActiveRecord::Base
  belongs_to :business
  belongs_to :location
end

现在控制器新动作:

#app/controllers/businesses_controller.rb#new
def new
  @business = Business.new

  mailing_address = @business.build_mailing_address
  3.times do
    location = @business.locations.build
    address = location.build_address
  end
  respond_to do |format|
    format.html # new.html.erb
    format.xml  { render :xml => @business }
  end
end

最后意见:

#app/views/businesses/_form.html.erb
<%= form_for(@business) do |f| %>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <%= f.fields_for :mailing_address do |builder| %>
    <h3>Mailing Address</h3>
    <%= render "address_fields", :f => builder %>
  <% end %>
  <%= f.fields_for :locations do |builder| %>
    <h3>Location</h3>
    <%= render "locations_fields", :f => builder %>
    <%= builder.fields_for :address do |mini_builder| %>
      <h3>Location Address</h3>
      <%= render "address_fields", :f => mini_builder %>
    <% end%>
  <% end %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

地址部分:

#app/views/businesses/_address_fields.html.erb
<p>
  <%= f.label "Street Address"%>
  <%= f.text_field :street %>
  <%= f.label "City"%>
  <%= f.text_field :city %>
  <%= f.label "State"%>
  <%= f.text_field :state %>
  <%= f.label "Zip"%>
  <%= f.text_field :zip %>  
</p>

位置偏:

#app/views/businesses/_location_fields.html.erb
<p>
  <%= f.label "Location Name"%>
  <%= f.text_field :name%>
</p>

这一切都有一些棘手的组成部分。您必须记住,构建has_one和has_many子对象是控制器中的另一种方法。此外,您需要为邮件地址关系正确定义类。

如果您想从与业务地址关联的位置集合中填充业务邮件地址,那么您可以在Business模型中添加一个类似这样的方法:

#app/models/business.rb#possible_mailing_addresses
def possible_mailing_addresses
  Location.where(:business_id=>self.id).joins(:address)
end

答案 1 :(得分:0)

关于模型,你可能想要这样的东西:

class Business < ActiveRecord::Base
  has_many :locations
  has_many :addresses, :through => :locations do
    def mailing
      find_by_is_mailing_address(true)
    end
  end
end

class Location < ActiveRecord::Base
  has_one :address
  belongs_to :business
end

class Address < ActiveRecord::Base
  belongs_to :location
  belongs_to :business, :through => :location      
end

...这会给你my_business.addresses.mailing

然后,您需要一个名为addresses的{​​{1}}表中的布尔列,您只能在其业务的邮件地址的地址上设置is_mailing_address。您还应该在true模型中验证每个商家只有一个地址Address

我担心我对嵌套表格不是很有经验;希望其他人可以帮助你。

Ruby专家:我确信您可以使用is_mailing_addresshas_one :mailing_address开展业务:through => :locations,但我不明白{{1} }。也许你可以启发我们两个?