【问题标题】:Rails test error when attempting to find associated model in test尝试在测试中查找关联模型时出现 Rails 测试错误
【发布时间】:2018-05-08 18:05:29
【问题描述】:

我正在使用 Ruby on Rails 制作一个在线图书馆系统。目前用户可以注册,但要这样做,他们必须先选择一种订阅计划。

最后,我发现最好的方法是像这样传递plan_id

config/routes.rb

get 'subscribe/paperback2u', to: 'members#new', :plan_id => 1
get 'subscribe/paperback4u', to: 'members#new', :plan_id => 2
get 'subscribe/paperback6u', to: 'members#new', :plan_id => 3

然后,members/new.html.erb 拉取 form 部分,如下所示:

<%= form_with(model: member, local: true) do |form| %>
  <% plan_id = params[:plan_id] %>

  <div class="field form-group">
    <%= form.label :first_name, "First Name" %>
    <%= form.text_field :first_name, 
                        id: :member_first_name,
                        :class => "form-control",
                        :required => true %> 
  </div>

  <div class="field form-group">
    <%= form.label :last_name, "Last Name" %>
    <%= form.text_field :last_name,
                        id: :member_last_name,
                        :class => "form-control",
                        :required => true %>
  </div>

  <div class="field form-group">
    <%= form.label :address_line_1, "Address Line 1" %>
    <%= form.text_field :address_line_1,
                        id: :member_address_line_1,
                        :class => "form-control",
                        :required => true %>
  </div>

  <div class="field form-group">
    <%= form.label :address_line_2, "Address Line 2" %>
    <%= form.text_field :address_line_2,
                        id: :member_address_line_2,
                        :class => "form-control" %>
  </div>

  <div class="field form-group">
    <%= form.label :town %>
    <%= form.text_field :town,
                        id: :member_town,
                        :class => "form-control",
                        :required => true %>
  </div>

以及成员模型的其他字段。

然后我们得到:

 98 <%= form.hidden_field :plan_id, value: params[:plan_id] %>

100 <% if form.object.new_record? %>
101   <%= render 'stripe-form' %>
102 <% end %>

说实话,我不认为 line 98 在做任何事情。

那么stripe-form 部分看起来像这样:

1  <div class="text-center">
2    <script src="https://checkout.stripe.com/checkout.js" class="stripe-button btn-primary"
3      data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
4      data-description="Subscribe to ReadAll Library"
5      data-amount=<%= (Plan.find(params["plan_id"].to_i).display_price) * 100 %>
6      data-currency="gbp"
7      data-panelLabel="Subscribe for"
8      data-label="Subscribe"
9      data-locale="auto"></script>
10 </div>

我得到的错误是:

Error:
MembersControllerTest#test_should_get_new:
ActionView::Template::Error: Couldn't find Plan with 'id'=1
    app/views/members/_stripe-form.html.erb:5:in `_app_views_members__stripe_form_html_erb___374722773566915779_70180218242520'
    app/views/members/_form.html.erb:101:in `block in _app_views_members__form_html_erb__2640496602018942691_70180179508500'
    app/views/members/_form.html.erb:1:in `_app_views_members__form_html_erb__2640496602018942691_70180179508500'
    app/views/members/new.html.erb:5:in `_app_views_members_new_html_erb___3025732295195500162_70180218177380'
    test/controllers/members_controller_test.rb:16:in `block in <class:MembersControllerTest>'

如果我在测试中添加puts response.body,我得到的错误是:“计划必须存在”。它做了什么!我的plans 表中有 3 个不同的计划。每个都有一个 ID,当我实际运行它时一切正常。只是测试不起作用。如果可以,我会取消测试,但我需要它作为项目的文档。

最后,这是我的Plan.rbMember.rb

`plan.rb`

 class Plan < ApplicationRecord
   has_many :members
 end

`member.rb`

   class Member < User
1    require 'stripe'
2 
3    before_save :set_type
4 
5    belongs_to :plan
6 
7 
8    def set_type
9      self.type = "Member"
10   end
11
12 end

以及两者的架构:

create_table "plans", force: :cascade do |t|
  t.string "stripe_id"
  t.string "nickname"
  t.decimal "display_price"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.string "product"
end

create_table "users", force: :cascade do |t|
  bunch of user attributes (first_name, address, etc)
  t.string "type" (members is a users type)
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.string "remember_digest"
  t.string "customer_id"
  t.bigint "plan_id"
  t.index ["email"], name: "index_users_on_email", unique: true
  t.index ["plan_id"], name: "index_users_on_plan_id"
end

我没有想法。我很感激你们能给我的任何帮助。干杯。

【问题讨论】:

  • 与您的问题无关,但真的需要在不同的 URL 中分离这个问题吗?您可以轻松地仅使用 on route 而不是 3 来选择新用户将获得哪个计划或让用户选择它。
  • 从这一行:“ActionView::Template::Error: 找不到 'id'=1 的计划”。似乎您的测试正在尝试从数据库中检索 ID 等于 1 的 Plan 对象,而不是选择用户将使用哪个 Plan(它只是作为参数传递 id)。由此,我会说你的问题来自于有 3 个 URL 来代表相同的问题。我不知道如何解决您遇到的问题。
  • @PedroGabrielLima 我只是找不到将现有计划与用户关联的方法。这是我可以让它工作的唯一方法。由于我不想创建新计划(因此没有嵌套形式),我只想在 plan_id 列中为新成员提供现有计划的 ID。有什么建议吗?
  • 从“我只是找不到将现有计划与用户关联起来的方法”,嗯,有一种方法。您只需要添加一种方式让用户选择他们想要的计划,并将其与所有其他信息一起发送到您的控制器。我将发布一个带有一般示例的答案。
  • 我发布了另一种让用户选择计划的方法。为了帮助您解决真正的问题,您是否为模型计划创建了固定装置?如果你不这样做,那可能会引发错误。

标签: ruby-on-rails ruby model-view-controller


【解决方案1】:

在您看来,如果您希望用户从表单中进行选择,您可以添加选择输入并让用户选择他们想要的计划。但是您可以通过 URL 传递这些信息,就像您已经做的那样。

查看:

<%= form_with(model: member, local: true) do |form| %>

  <div class="field form-group">
    <%= form.label :first_name, "First Name" %>
    <%= form.text_field :first_name, 
                        id: :member_first_name,
                        :class => "form-control",
                        :required => true %> 
  </div>

  <div class="field form-group">
    <%= form.label :plan, "Choose your plan" %>
    <%= form.select :plan_id, 
        Plan.all {|p| [ p.name, p.id ]}, 
        { include_blank: false, selected: form.object.plan_id }, class: 'form-control' %>
  </div>

  <%= f.submit "Salvar", class: "btn btn-primary" %>  
<% end %>

我相信其余的你已经做到了。在控制器中,将plan_id 添加到params 白名单中,并在模型中将模型关系添加为has_many 和belong。 P.s:我没有测试这个。

【讨论】:

  • 谢谢佩德罗!我会改用这个。我最终改用了 collection_select,因为它没有呈现名称或 ID。 Gracias chamo!
  • @SHorvath,很高兴它对你有所帮助!
猜你喜欢
  • 2015-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多