Rails 5活动记录关联

时间:2016-11-17 18:56:47

标签: relational-database rails-activerecord foreign-key-relationship ruby-on-rails-5

我正在学习如何使用Ruby on Rails并希望找到解决问题的最佳方法。我搜索了许多论坛和Rails文档,但还没有能够理解解决方案,所以希望有人能够提供帮助!

我的应用有3个控制器 - 用户,user_addresses和发票。每个用户可以拥有多个user_addresses,还有多个发票。我添加了一个user_id列作为我的user_addresses表的主键,并将user_id和address_id列添加为我的发票表中的主键。

当我创建发票并选择要分配给它的地址时,保存它,我无法弄清楚如何填充user_id和address_id,我只能得到一个或另一个保存。在下面的示例中,我将user_id保存,但不知道如何从地址获取user_id和id以保存到发票。

我的用户模型设置为has_many:user_addresses和has_many:发票。我的Invoice和UserAddress模型都属于belongs_to:user。从我所读到的,我想我可能需要使用:通过扩展,但我迷路了,不知道该怎么做。任何帮助或指导将不胜感激!

发票表单

<div class="form-group">
    <%= label_tag(:user_id, "Customer") %>
    <%= f.select(:user_id, @addresses.map {|a| [a.user.first_name + ' ' + a.user.last_name + ' - ' + a.street_1, a.user.id]},{}, {:class => 'form-control'})  %>
  </div>

  <div class="form-check">
    <label class="form-check-label">
    <%= f.check_box(:status, :class => 'form-check-input')  %>
    Status
    </label>
  </div>

  <div class="form-group">
    <%= label_tag(:service_date, "Service Date") %>
    <%= f.text_field(:service_date, 'data-provide' => 'datepicker', :class => 'form-control')  %>
  </div>

  <div class="form-group">
    <%= label_tag(:service_type, "Service Type") %>
    <%= f.select(:service_type, ["General Pest", "Weed Control", "Specialty Pest", "Rodent"],{}, {:class => 'form-control'})  %>
  </div>

  <div class="form-group">
    <%= label_tag(:service_charge, "Service Charge") %>
    <%= f.text_field(:service_charge, :class => 'form-control')  %>
  </div>

发票控制器

  def new
    @invoice = Invoice.new
    @addresses = UserAddress.all
  end

发票表

  create_table "invoices", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t|
t.integer  "user_id"
t.integer  "address_id"
t.boolean  "status",            default: false
t.string   "service_date"
t.string   "service_type"
t.string   "service_areas"
t.string   "service_materials"
t.string   "service_charge"
t.string   "service_info"
t.datetime "created_at",                        null: false
t.datetime "updated_at",                        null: false
t.index ["address_id"], name: "index_invoices_on_address_id", using: :btree
t.index ["user_id"], name: "index_invoices_on_user_id", using: :btree

1 个答案:

答案 0 :(得分:1)

  

我添加了一个user_id列作为user_addresses表的主键

声明PK表示用户最多只能拥有一个地址。如果您希望用户能够拥有多个地址,那么您就不会想要那个PK。您可能希望每个用户地址对都是UNIQUE / PK。

  

user_id和address_id列作为我的发票表中的主键

这意味着您无法为同一个人 - 地址对分配两张发票。这可能不是你想要的。通常,发票的唯一候选/主键是唯一的运行时发票ID。虽然您很可能希望某种索引来帮助优化基于人员 - 地址对查找发票。

如果您将某些列声明为候选键(可能是PK),那么您说它们是唯一的而不是NULL。但是你说你想要一张没有用户和地址的发票,这与之相反。每个用户有很多发票,但这只是因为每个用户有许多用户地址对(每个都有发票)。声明这样的有发票。而不是用户这样做,因为您必须使UserInvoice与Invoice保持冗余。 (但你真的想要发票ID。)

A:通过管理冗余。包括解决上面提到的索引优化问题。

首先阅读制作关系设计,然后通过Active Record设计表达它(以及所需的优化)。