关注Rails教程,未定义的方法'创建'对于nil:NilClass,具有嵌套资源

时间:2018-03-20 15:36:05

标签: ruby-on-rails ruby

我遵循Rails教程并在适当的位置进行更改,目的是在完成本教程后,我的教程项目将成为一个成熟的生产应用程序。

我遇到了本教程第二个模型部分的障碍。这就是我写第二个模型的方式。

在我的policy.rb

class Policy < ApplicationRecord
    has_one :insured
end

在我的insured.rb

class Insured < ApplicationRecord
    belongs_to :policy
end

在我的routes.rb

resources :policies do
    resource :insured
end

在我的insureds_controller.rb

def create
    @policy = Policy.find(params[:policy_id])
    # next line is raising the error
    @insured = @policy.insured.create(insured_params)
    redirect_to @insured
end

private
    def insured_params
        params.permit(:name, :address, :phone, :email)
    end

我已使用@policy检查了render plain: @policy.inspect对象,并确认ActiveRecord正在正确检索该策略。当我使用@policy检查render plain: @policy.attribute_names.inspect的属性时,我没有看到insured属性,我认为Rails应该为我自动管理。在本教程中,article has_many :comments和评论很容易创建,并通过此调用与父文章相关联:@article.comments.create(comment_params)。我还注意到本教程使用params.require(:comment).permit(...),而我必须使用params.permit(...),在检查params哈希后,我看到:insured属性存在于顶层哈希,而不是绑定到哈希中的:insured键。

我尝试手动保存并分配@insured对象,如下所示:

def create
    @policy = Policy.find(params[:policy_id])
    @insured = Insured.new(insured_params)
    if @insured.save
        @policy.insured = @insured
        redirect_to @insured
    end
end

仅在我的.../insureds/new.html.erb中遇到以下错误:

<h1>New Insured</h1>
<h1><%= @policy.policy_number %></h2>
<%= render 'form' %>
<%= link_to 'Cancel', policy_path(@policy) %>

源自我的部分格式.../insureds/_form.html.erb

# the following line raises the error
<%= form_with model: @insured, local: true do |form| %>
    # html omitted for brevity
<% end %>

错误:&#39;未定义的方法insureds_path&#39;。这很奇怪,因为当我检查HTML时,我可以看到此视图的表单操作是/policies/[:id]/insured

对于大量的文字墙,我很抱歉,我想告诉大家我确实想弄清楚出了什么问题。

2 个答案:

答案 0 :(得分:0)

config/routes.rb文件中存在错误:

resources :policies do
  # change it for:
  collection do
    get 'insured', to: 'policies#show_insured', as: 'show_policy_insured'
    # maybe unnecessary to be here
    # get 'insured/new', to: 'insureds#new', as: 'new_policy_insured'
    # post 'insured/create', to: 'insureds#create', as: 'create_policy_insured'
    # delete 'insured/delete', to: 'insureds#delete', as: 'delete_policy_insured'
  end
end
# add resources here
resources :insureds

policy_controller.rb

def show_insured # 'policy/:id/insureds/
end

insureds_controller.rb

def show # '/insureds/:id'
end

def create
  ...
  redirect_to show_policy_insured && return if @insured_policy
end

# before_filter or before_action
@policy = Policy.find(params[:id])
@insured_policy = @policy.insured

检查并运行以查看路线

$ bundle exec rake routes 


get /policies/:id/insured   => 'policies_controller#show_insured'
get /insureds/:id           => 'insureds_controller#show'
get /insured/new            => 'insureds_controller#new'
post /insureds/create       => 'insureds_controller#create'
delete /insureds/:id/delete => 'insureds_controller#delete'

答案 1 :(得分:0)

@maguri,这不是全部必要的。我遇到的绊脚石是Rails无法自动确定正确的路线。当我在form_with声明中提供我自己的网址时,一切进展顺利。

对于_form.html.erb投保模型belongs_to,请注意以下更改:has_one政策,<%= form_with model: @insured, url: policy_insured_path(@policy) local: true do |form| %> 已投保。

insureds_controller.rb

在我更新的def create @policy = Policy.find(params[:policy_id]) @insured = @policy.create_insured(insured_params) if @policy.insured.save redirect_to policy_insured_path(params[:policy_id]) else render 'new' end end 文件中,使用@ Phlip的建议:

routes.rb

这使我可以保持resources :policies do resource: insured end 简洁明了:

SELECT 
    COALESCE([t1].[company_number], [t2].[company_number]) AS [Company_Number],
    MONTH(COALESCE([t1].[date], [t2].[date])) AS [Month],
    [t1].[value] AS [2018 Value], 
    [t2].[value] AS [2017 Value]
FROM 
    [table1] AS [t1]
FULL OUTER JOIN 
    [table2] as [t2] on [t1].[company_number] = [t2].[company_number] 
    AND MONTH([t1].[date]) = MONTH ([t2].[date])

感谢您的回答,它帮助我发现问题出在我的路线上。