【问题标题】:rails form_for create new entry instead of updatingrails form_for 创建新条目而不是更新
【发布时间】:2015-06-04 15:11:57
【问题描述】:

我正在使用 form_for 来创建一个新条目。

在我设置的控制器中:

def create_ab_campaign
  @campaign = Campaign.find_by(id: params[:id],  account_id: current_account.id)
  @campaign_id = params[:id]
end

在我看来:

<%= form_for (@campaign), :url => {:controller => "campaigns", :action => "create_new_ab_campaign"} do |f| %>
<div class="form-group">
<%= f.label :name, "name", class: "control-label" %>
<%= f.text_field :name, class: "form-control", placeholder: "name" %>
</div>
<%= f.submit "Save Settings" %>

在提交时,我希望创建一个新条目而不是更新现有条目。

我在控制器中做了以下操作:

def create_ab_campaign_new
  @campaign_new = Campaign.new(create_a_new_ab_campaign)
   if @campaign_new.save
    redirect_to(:controller =>"campaigns", :action =>"index")
   else
    redirect_to(:action =>"new")
   end
end

private
  def create_a_new_ab_campaign
    params.require(:campaign).permit(:name)
  end

我得到以下信息: CampaignsController 中的 NoMethodError#update

它仍然尝试使用更新而不是“create_a_new_ab_campaign”

我使用更新来更新记录 - 这一切正常。

def update
  @campaign = Campaign.find_by(id:params[:id], account_id: current_account.id)
  @new = create_new_campaign
  if @campaign.update_attributes(@new)
    redirect_to(:controller =>"campaigns", :action =>"index")
  else
    render 'edit'
  end
end

但如上所述,我想做另一个案例,而不是更新/编辑,并从记录中创建一个新条目。

非常感谢您的帮助!

更新:

完整的错误日志:

CampaignsController#update 中的 NoMethodError nil:NilClass 的未定义方法“update_attributes”

提取的源代码(在 #124 行附近): 122 123 124 125 126 127

@new = create_new_campaign
@new[:page_type].delete_if{ |x| x.empty? }
if @campaign.update_attributes(@new)
  redirect_to(:controller =>"campaigns", :action =>"index")
else
  render 'edit'

Rails.root: /Users/sschindler/demostore

应用程序跟踪 |框架跟踪 |全跟踪 app/controllers/campaigns_controller.rb:124:in `update'

更新路线

路线:

发布“活动/create_new_ab_campaign”

获取“活动/create_new_ab_campaign”

post "/campaigns/:id/edit" => "campaigns#edit"

get "/campaigns/:id/edit" => "campaigns#edit"

发布“/campaigns/create_ab_campaign”=>“campaigns#create_ab_campaign”

get "/campaigns/create_ab_campaign" => "campaigns#create_ab_campaign"

post "/campaigns/:id" => "campaigns#edit"

post "/campaigns/:id" => "campaigns#new"

get "/campaigns/:id" => "campaigns#edit"

获取“活动/节目”

获取“广告系列/索引”

发布“/campaigns/edit”

get '/campaigns/edit'

【问题讨论】:

  • 请发布完整的错误堆栈跟踪。
  • 代码中有很多错别字。

标签: ruby-on-rails form-for


【解决方案1】:

我假设您的 create_ab_campaign 是您的新路线,create_ab_campaign_new 是您的发布路线。虽然我有点困惑,因为您在 #create_ab_campaign 中有一个 params[:id]

尽管如此,您的表单正在尝试更新,因为您传递了 form_for 一个已创建的广告系列变量:@campaign = Campaign.find_by(...)

rails form_for 将检查该对象是您数据库中的一个实例还是只是一个新模型。如果它已经创建,它将PATCH 到您的更新路线;如果它是一个新模型(但未创建),它将POST 到您的创建路线。

在您的#new 路由中,您需要将@campaign 分配给Campaign.new(account_id:current_account.id),而不是找到一个已经完成的。

更新
根据您的 cmets,您希望复制一个模型,更改一些字段并将其另存为新记录。在这种情况下,您需要将要复制的活动模型的 ID 发送到表单,以便您可以在创建路由中检索它,使用 model.dup,使用参数修改它,然后保存。

def create_ab_campaign
  @campaign = Campaign.new
  @campaign_id = params[:id]
end

在表单中添加隐藏字段

<%= form_for (@campaign), :url => {:controller => "campaigns", :action => "create_new_ab_campaign"} do |f| %>
<div class="form-group">
<%= hidden_field_tag :campaign_id, @campaign_id
<%= f.label :name, "name", class: "control-label" %>
<%= f.text_field :name, class: "form-control", placeholder: "name" %>
</div>
<%= f.submit "Save Settings" %>

创建路线
复制活动,进行修改并检查有效性。确保不要对此模型进行唯一性验证,否则会遇到一些麻烦

def create_ab_campaign_new
  @campaign_new = Campaign.find(params[:campaign_id]).dup
  @campaign_new.update(create_a_new_ab_campaign)
   if @campaign_new.save
    redirect_to(:controller =>"campaigns", :action =>"index")
   else
    redirect_to(:action =>"new")
   end
end

【讨论】:

  • PhilVarg,非常感谢。这里是路线 post "campaigns/create_new_ab_campaign" get "campaigns/create_new_ab_campaign" post "/campaigns/:id/edit" => "campaigns#edit" get "/campaigns/:id/edit" => "campaigns#edit" post "/campaigns/create_ab_campaign" => "campaigns#create_ab_campaign" 获取 "/campaigns/create_ab_campaign" => "campaigns#create_ab_campaign" post "/campaigns/:id" => "campaigns#edit" post "/campaigns/:id " => "campaigns#new" 获取 "/campaigns/:id" => "campaigns#edit" 获取 'campaigns/show' 获取 'campaigns/index'
  • 我想用现有Campaing的信息来创建一个新的。背景是:我想为同一个 Campaing 创建一个 AB 测试并修改其中的一件事。然后应将其保存为新广告系列。
  • 是的,我现在先克隆它然后编辑它,因为它总是尝试直接更新它。非常感谢您的帮助!
【解决方案2】:

看起来你正在混合你的动词

`post "campaigns/create_new_ab_campaign"`

是一个帖子和

= form_for (@campaign), :url =&gt; {:controller =&gt; "campaigns", :action =&gt; "create_new_ab_campaign"} do |f|

是一个 PUT。尝试更改为

在 route.rb 中:

match 'create_new_ab_campaign', to 'campaigns#create_new_ab_campaign', via: :post

然后

=form_for(@campaign), url: :create_new_ab_campaign, method: 'POST' do |f|

基本上如果您在新对象上调用 form_for,表单提交方法默认为 POST,如果您在现有对象上使用,表单提交方法默认为 PUT/PATCH。这就是为什么它一直在寻找更新。要更改此设置,请将 method 关键字添加到您的表单构建器。

进一步阅读:http://www.restapitutorial.com/lessons/httpmethods.html

【讨论】:

  • 非常感谢!!对于链接。为了解决这个问题,我现在先克隆Campaing,然后编辑它()。但我也会检查方法关键字!
  • 现在听起来不错。不要成为贴纸,但要保持 RESTful。 POST = 新记录,PUT/PATCH = 更新现有记录。
猜你喜欢
  • 2022-11-30
  • 1970-01-01
  • 1970-01-01
  • 2012-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多