1
votes

I am using form_for in order to create a new entry.

In the controller I set:

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

In the view I do:

<%= 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" %>

On submit I want to create a new entry instead of updating the existing one.

I did the following in the controller:

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

I get the following: NoMethodError in CampaignsController#update

It tries still to use the update instead of "create_a_new_ab_campaign"

I used the update for updating records - this works all fine.

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

But as described instead of an update/edit I want to do another case and create a new entry out of the record.

Thanks a lot for your help!

UPDATE:

Full error log:

NoMethodError in CampaignsController#update undefined method `update_attributes' for nil:NilClass

Extracted source (around line #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

Application Trace | Framework Trace | Full Trace app/controllers/campaigns_controller.rb:124:in `update'

Update routes

Routes:

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"

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

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

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

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

get 'campaigns/show'

get 'campaigns/index'

post '/campaigns/edit'

get '/campaigns/edit'

2
Please post the full error stacktrace. - Pavan
You got lot of typos in the code. - Pavan

2 Answers

0
votes

I'm assuming your create_ab_campaign is your new route and create_ab_campaign_new is your post route. Although i am little confused because you have a params[:id] value in #create_ab_campaign

From the looks of it though, your form is trying to update because you're passing form_for an already created campaign variable: @campaign = Campaign.find_by(...)

rails form_for will check if the object is an instance in your db or if its just a new Model. if its already been created, it will PATCH to your update route; if its a new Model (but not created) it will POST to your create route.

in your #new route, you need to assign @campaign to Campaign.new(account_id:current_account.id) instead of finding one thats already been made.

Update
Based on your comments, you want to duplicate a model, change some of the fields and save it as a new record. in that case, you'd want to send the id of the campaign model that you want to copy to the form, so you can retrieve it in your create route, use model.dup, modify it with params, then save.

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

add hidden field to form

<%= 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" %>

Create route
dup the campaign, make modifications, and check validity. Be sure not to have uniqueness validations on this model or youll run into a bit of trouble

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
0
votes

Looks like you're mixing your VERBS

`post "campaigns/create_new_ab_campaign"`

is a post and

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

is a PUT. Try change to

in route.rb:

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

and then

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

Basically If you call form_for on a new object, the form submit method defaults to a POST and if you using on an existing object, the form submit method defaults to a PUT/PATCH. This is why it keeps looking for update. To change this add the method keyword to your form builder.

further reading: http://www.restapitutorial.com/lessons/httpmethods.html