【问题标题】:Rails 5 Active Record AssociationsRails 5 活动记录关联
【发布时间】:2016-11-17 18:56:46
【问题描述】:

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

我的应用有 3 个控制器——用户、用户地址和发票。每个用户可以有多个 user_addresses,也可以有多个发票。我添加了一个 user_id 列作为我的 user_addresses 表的主键,并添加了一个 user_id 和 address_id 列作为我的 invoices 表的主键。

当我创建一张发票并选择一个地址来分配它,然后保存它时,我不知道如何填充 user_id 和 address_id,我只能获取一个或另一个来保存。在下面的示例中,我正在获取要保存的 user_id,但不确定如何从地址中获取 user_id 和 id 以保存到发票中。

我的用户模型设置为 has_many :user_addresses 和 has_many :invoices。我的 Invoice 和 UserAddress 模型都属于_to :user。根据我的阅读,我认为我可能需要使用 :through 扩展,但我迷路了,不知道该怎么做。任何帮助或指导将不胜感激!

发票表格

<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

结束

【问题讨论】:

  • “我只能保存其中一个”是什么意思?即什么程序的什么输入导致什么行为(错误和/或输出)?另请显示所有相关代码并阅读minimal reproducible examples。 PS 请参阅我在答案开头添加的编辑。

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


【解决方案1】:

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

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

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

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

如果您将某些列声明为候选键(可能是 PK),那么您是在说它们是唯一的而不是 NULL。但是你说你想要一张没有用户和地址的发票,这与此相矛盾。每个用户有许多发票,但这仅仅是因为每个用户有许多用户地址对(每个都有发票)。声明这样的 pair 有发票。而不是用户这样做,因为您必须让 UserInvoice 与 Invoice 冗余同步。 (但您确实需要发票 ID。)

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

了解如何首先进行关系设计,然后通过 Active Record 设计表达它(以及所需的优化)。

【讨论】:

  • 感谢您的回复。我可能没有彻底解释,但我确实希望所有发票都有一个 user_id 和 address_id...但是由于用户可以有多个地址,我无法弄清楚如何设置关系以根据选择自动填充数据库。我将通过 Active Record 对关系设计进行更多研究。我确实找到了一个解决方案,方法是在设置为地址 id 的选择字段选项上设置数据属性,并使用 jQuery 填充隐藏表单元素的值以将地址 id 提交到表单。
  • 我没有说发票没有关联的 user_id 和 address_id。我说您可能希望这些不形成发票 CK,而您可能希望列 invoice_id 可以。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
相关资源
最近更新 更多