Rails 5:重构 - 一对多关系(测试和视图)

Rails 5: Refactoring - One to Many Relationship (Tests and Views)

对 rails 有点陌生,并试图通过 Rails 文档或 rails 指南找到我一直遇到的问题的一些答案,但运气不佳,或者rails 教程。

我的目标是接受 rails 处理事情的方式,并尝试让其他开发人员以后更容易进入该项目。

问题 1:重构问题

Rails 重构实践。我不确定这是否应该放在模型或控制器中,我真的只是想知道哪些项目应该放在控制器中,哪些应该放在模型中。

第一次迭代:

<% @departments.each do |department| %>
      <tr>
        <td><%= department.name %></td>
        <td><%= department.description %></td>
        <td>
          <%= library = Library.find_by(id: department.library_id).name %>
        </td>
        <td><%= link_to 'Show', department %></td>
        <td><%= link_to 'Edit', edit_department_path(department) %></td>
        <td><%= link_to 'Destroy', department, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>

这对我来说似乎是错误的,并且似乎应该将其作为后端逻辑从该部分中删除。

第二次迭代:

型号

class Department < ApplicationRecord
  belongs_to :library

  def get_library_name(lib_id)
    library = Library.find_by(id: lib_id)
    return library.name
  end
end

查看

<% @departments.each do |department| %>
      <tr>
        <td><%= department.name %></td>
        <td><%= department.description %></td>
        <td>
          <%= department.get_library_name(department.library_id) %>
        </td>
        <td><%= link_to 'Show', department %></td>
        <td><%= link_to 'Edit', edit_department_path(department) %></td>
        <td><%= link_to 'Destroy', department, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>

这感觉更正确,但并非完全正确,所以我不确定如何才能将其更改为更正确,特别是因为列出记录的索引视图非常相似。

我该如何重构它?

问题 2:我的测试不会通过

无论如何,我的测试没有通过。我猜这就是我使用一对多关系的方式。

  test "should get index" do
    get departments_url
    assert_response :success
  end

错误:

DepartmentsControllerTest#test_should_get_index:
ActionView::Template::Error: undefined method `name' for nil:NilClass
    app/models/department.rb:6:in `get_library_name'
    app/views/admin/departments/index.html.erb:21:in `block in _app_views_admin_departments_index_html_erb__1894713831414342893_57284960'
    app/views/admin/departments/index.html.erb:16:in `_app_views_admin_departments_index_html_erb__1894713831414342893_57284960'
    test/controllers/departments_controller_test.rb:11:in `block in <class:DepartmentsControllerTest>'

问题一:

您可以使用关联方法轻松访问关联图书馆的查询。

每当您将 belong_to :library 添加到 Department 时,您实际上只是在 Department 的实例上创建一个名为 library 的方法,它会为您调用适当的查询。

has_manyhas_onehas_and_belongs_to_many 关联也会发生同样的情况,希望相反的情况发生。

它不是寻找 Library.find_by(id: department.library_id),而是相反,Department.find_by(library_id: department.library_id)

所有这些都可以通过关联方法轻松访问。

department = Department.first
library = department.library

回到这个问题,就我个人而言,我喜欢将最大的数据集展示给我的观点,然后从那里缩小范围。

我只会向视图发送一个 @department,而不会费心创建一个方法来显示名称或 delegate 从图书馆到部门(带前缀)的名称以获得 library_name方法。

<% @departments.each do |department| %>
  <tr>
    <td><%= department.name %></td>
    <td><%= department.description %></td>
    <td><%= department.library.name %></td>
    <td><%= link_to 'Show', department %></td>
    <td><%= link_to 'Edit', edit_department_path(department) %></td>
    <td><%= link_to 'Destroy', department, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>

问题二:

不幸的是,我没有多少答案。问题是可以使用的信息很少,而且现在我们涉及许多可能正在发送的方法,而 nil 可以多米诺骨牌一直到您的模型方法。

我强烈怀疑你们的一个部门没有 library_id,这会导致循环崩溃,因为这取决于每个部门都有图书馆。

编辑

问题三:

要获得反向关系,只需执行 department.libraries

在您描述的情况下,您有一个部门集合,这与单个部门实例不同。