在另一个控制器内插入带有“find_or_create_by”的记录失败

时间:2014-12-14 20:24:14

标签: ruby-on-rails ruby database record

这是我的代码:

类ApplicationsController< ApplicationController中

def new
    @application = Application.new
end

def create
    @application = Application.new(application_params)
    @layout = Layout.find_or_create_by(application_id: @application.id)

    if @application.save
        redirect_to @application
    else
        render 'new'
    end
end

layout belongs_to:application

当我检查Layouts表时,它是空的。你能帮帮我吗?

4 个答案:

答案 0 :(得分:1)

在您的布局创建行中,@ application还没有ID。结果,你将'nil'传递给@ layout的application_id,这会使其验证失败。 (您在评论中提到了布局的应用程序状态验证)。

所以在保存@application之后创建布局,你应该好。

if @application.save
  @layout = Layout.create(application_id: @application.id)

答案 1 :(得分:1)

您的模型包含以下验证:

validates :adv_path, presence: true 
validates :start_time, presence: true 
validates :end_time, presence: true

因此,如果没有此值,您将无法创建Layout。你必须做这样的事情(有用的价值):

Layout.find_or_create_by(id: @application.id) do |layout|
  layout.adv_path   = 'A useful default'
  layout.start_time = 1.second.ago
  layout.end_time   = 100.year.from_now
end

或者重新考虑验证者的需要。

答案 2 :(得分:0)

当您使用{/ 1}}方法时

new

它不会将该记录持久存储到db,换句话说它没有id。你应该使用方法@application = Application.new(application_params) 代替

create

然后@application = Application.create(application_params) 将被持久保存到db,当您说@application时,它会找到ID,而不是搜索ID find_or_create_by

答案 3 :(得分:0)

def create
  @application = Application.new(application_params)

  @layout = Layout.find_or_create_by(application_id: @application.id)  # <== that line
  if ...
    ....
  end
end

这条线很容易产生误导。 @ application.id是零。所以第一次,你将创建一个application_id为nil的布局记录。下一次,它将使用application_id:nil找到记录并使用它。所以它只会创建一个记录并永远使用它。

如果您每次创建应用程序时都在创建布局,请考虑这样做:

def create
    @application = Application.new(application_params)

    if @application.save
        @layout = @application.layouts.create( ... ) # assuming application has_many :layouts
        redirect_to @application
    else
        render 'new'
    end
end