gpt4 book ai didi

ruby-on-rails - has_one 嵌套属性不保存

转载 作者:数据小太阳 更新时间:2023-10-29 08:04:13 29 4
gpt4 key购买 nike

我有两个模型 Project 和 ProjectPipeline。

我想创建一个项目表单,该表单也包含来自 ProjectPipeline 模型的字段。我已成功创建表单,但是当我点击保存时,值并未存储在数据库中。

project.rb

class Project < ActiveRecord::Base

has_one :project_pipeline

accepts_nested_attributes_for :project_pipeline

self.primary_key = :project_id
end

projectpipeline.rb

class ProjectPipeline < ActiveRecord::Base

belongs_to :project, autosave: :true

validates_uniqueness_of :project_id

end

我并不总是想要一个项目管道,而是在基于查看项目的用户的正确条件下。我希望构建项目管道字段,但仅当用户选择保存/填充它们时才保存。

因此,当显示项目时,我使用 project_id: from params[:id] 构建了一个临时项目管道(不确定我是否真的需要这样做)。然后当项目被保存时我使用 create_attributes。但如果它已经创建或构建,我只想让 has_one 和 belongs_to 关联启动,然后使用 update_attributes。

我的问题是,当我尝试保存时,如果我使用 params[:project_pipeline],我要么遇到“禁止属性”错误,要么如果我使用 project_params,则根本没有保存任何内容。我检查并重新检查了我的所有字段都在 project_params 中,甚至尝试使用 project_pipeline_params 但感觉不对。

这让我发疯,我需要 sleep 。

projects_controller.rb

def show
@project = Project.find(params[:id])
if @project.project_pipeline
else
@project.build_project_pipeline(project_id: params[:id])
end
autopopulate
end



def update
@project = Project.find(params[:id])
if @project.project_pipeline
else
@project.build_project_pipeline(project_id: params[:id], project_type: params[:project_pipeline][:project_type], project_stage: params[:project_pipeline][:project_stage])
end
if @project.update_attributes(project_params)
flash[:success] = "Project Updated"
redirect_to [@project]
else
render 'edit'
end
end


def project_params
params.require(:project).permit(:user_id, project_pipeline_attributes:[:project_id,:project_type,:project_stage,
:product_volume,:product_value,:project_status,:outcome, :_destroy])
end

show.html.haml

    - provide(:title, "Show Project")
%h1= @project.project_title
= simple_form_for(@project) do |f|
= f.input :id, :as => :hidden, :value => @project, :readonly => true
= f.input :user_id, label: 'Assigned to Account Manager', :collection => @account_managers, :label_method => lambda { |r| "#{r.first_name} #{r.last_name}" }
= f.input :project_id, :readonly => true
= f.input :status, :readonly => true
= f.input :project_stage, :readonly => true

- if @project.project_codename = "project pipeline"
= simple_fields_for @project.project_pipeline do |i|
%h2 Project Pipeline
- if @project.user_id == current_user.id
= i.input :project_volume, label: 'Project Status', collection: @project_status
= i.input :project_value, label: 'Project Status', collection: @project_status
= i.input :project_status, label: 'Project Status', collection: @project_status
= i.input :outcome, label: 'Outcome', collection: @outcome


= f.submit 'Save'

如果您已经走到这一步,我衷心感谢您。

最佳答案

解决方案

你需要在这里改变一些东西。首先:

= simple_fields_for @project.project_pipeline do |i|

当您传递对象时,rails 不知道它要与父对象相关联,因此会创建一个名为 project[project_pipeline] 的字段,而不是 project[project_pipeline_attributes ]。相反,您需要传递关联名称并在表单构建器上调用此方法:

= f.simple_fields_for :project_pipeline do |i|

这将检查您是否定义了 project_pipeline_attributes= 方法(使用 accept_nested_attributes_for` 并将其视为关联。然后在您的 Controller 中将您的显示操作更改为:

def update
@project = Project.find(params[:id])
@project.assign_attributes(project_params)
if @project.save
flash[:success] = "Project Updated"
redirect_to @project
else
render 'edit'
end
end

一切都应该有效。作为单独的注释,由于您允许在嵌套参数中使用 :_destroy 属性,我假设您希望能够使用嵌套属性删除记录。如果是这样,您需要将 allow_destroy: true 添加到您的 accepts_nested_attributes_for 调用中。

现在一些样式:

你可以稍微改进一下你的表演 Action 。首先,我注意到如果尚未声明任何操作,您将在每个操作中构建一个空管道。这意味着您可能应该将此逻辑移至您的模型中:

class Project < AR::Base

after_initalize :add_pipeline

private

def add_pipeline
project_pipeline || build_project_pipeline
end
end

您还有神秘的方法 prepopulate - 很可能它也应该是模型问题。

还有一点:这个语法:

if something
else
# do sth
end

在某种程度上非常流行,并且使代码变得难以阅读。相反,使用:

if !something
# do something
end

或(首选)

unless something
# do something
end

关于ruby-on-rails - has_one 嵌套属性不保存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23404542/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com