Pregunta

I've seen this question come up on SO a few times and have tried to the recommended approaches to solve the problem. I'm still encountering this error for my form_for:

First argument in form cannot contain nil or be empty

I have several fields that should be entered into a 'Charge' object. I want the form to submit and create a charge object that includes the proper fields that I have in the form, including the hidden fields (user_id and gift_id).

Models:

class Gift
  has_many :codes
  has_many :charges

class Code
  belongs_to :gift

class Charge
  belongs_to :user
  belongs_to :gift

class User
  has_many :charges

charges_controller.rb

class ChargesController < ApplicationController

skip_before_filter :verify_authenticity_token, :only => [:new, :create]

def index
    @charges = Charge.all
end 

def show
    @charge = Charge.find(params[:id])
end 

def new
    @charge = Charge.new
end

def create
    @charge = Charge.new(params[:charge_params])
        Stripe.api_key = "sk_test_Ig7H6rhd0jl7W3V48y5pleOa"
        token = params[:stripeToken]
        customer = Stripe::Customer.create(
          :card => token,
          :description => "payinguser@example.com"
        )
        Stripe::Charge.create(
            :amount => gift.price,
            :currency => "cad",
            :customer => customer.id
        )
        save_stripe_customer_id(user, customer.id)

        # Later...
        customer_id = get_stripe_customer_id(user)

        Stripe::Charge.create(
          :amount   => 1500,
          :currency => "cad",
          :customer => customer_id
        )

        if @charge.save 
            redirects_to gifts_path, flash[:notice] = 'It worked'
        else 
            render 'gifts/new'
        end 
end

def edit
    @charge = Charge.find(params[:id])
end

def update
    @charge = Charge.find(params[:id])
    @charge.update_attributes(charge_params)
end

def destroy
    @charge = Charge.find(params[:id])
    @charge.destroy
end

private

def charge_params
    params.require(charge).permit(:sender_name, :recipient_email, :recipient_msg, :stripeToken, :gift_id, :user_id)
end
end 

_new.html.erb (the form collecting the data)

<%= form_for @charge do |f| %>

  <%= f.hidden_field :gift_id %>
  <%= f.hidden_field :user_id %>

  <div class="form-group left-inner-addon">
    <i class="glyphicon glyphicon-send"></i>
    <%= f.text_field :sender_name, :class => "form-control", :placeholder => "Sender's Name" %>
  </div>

  <div class="form-group left-inner-addon">
    <i class="glyphicon glyphicon-send"></i>
    <%= f.email_field :recipient_email, :class => "form-control", :placeholder => "Recipient's Email" %>
  </div>

  <div class="form-group left-inner-addon">
    <i class="glyphicon glyphicon-pencil"></i>
    <%= f.text_field :recipient_msg, :class => "form-control", :placeholder => "Message to Recipient" %>
  </div>

  <div class="form-group left-inner-addon ">
    <i class="glyphicon glyphicon-credit-card"></i>
    <%= f.text_field "data-stripe" => "number", :class= => "form-control", :placeholder => "Credit Card Number" %>
  </div>

   <div class="form-group">
     <div class="row">
       <div class="col-xs-4 left-inner-addon ">
         <i class="glyphicon glyphicon-calendar"></i>
         <%= f.text_field "data-stripe" => "exp-month", :class => "form-control", :placeholder => "MM" %>
       </div>
       <div class="col-xs-5 left-inner-addon ">
         <i class="glyphicon glyphicon-calendar"></i>
         <%= f.text_field "data-stripe" => "exp-year", :class => "form-control", :placeholder => "YYYY" %>
       </div>
     </div>
   </div>

   <div class="form-group">
     <div class="row">
       <div class="col-xs-5 left-inner-addon ">
         <i class="glyphicon glyphicon-ok-circle"></i>
         <%= f.text_field "data-stripe" => "cvc", :class => "form-control", :placeholder => "CVC" %>
       </div>
     </div>
   </div>
   <%= f.submit :class => "btn btn-primary", :type => "submit" %>
<% end %>

_show.html.erb (the partial that renders the form)

   <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
    <h4 class="modal-title"><center><%= gift.name %></center></h4>
</div>
<div class="modal-body">
    <p><%= image_tag gift.picture.url(:mobile) %></p>
    <p><%= gift.description %></p>
    <p>$<%= gift.price %></p>
    <%= render partial: 'charges/new', :locals => { :gift => gift } %>
</div>
<div class="modal-footer">
</div>

index.html.erb (Page that renders the _show.html.erb partial)

<%= title "Redwood | Gifts" %>
<div class="container">
    <div class="row" id="item">
        <% @gifts.each do |gift|  %>
        <div class="col-sm-6 col-md-4">
            <div class="thumbnail">
                <%= image_tag gift.picture.url(:medium) %>
                <div class="caption">
                    <h3><%= gift.name %></h3>
                    <h4><%= link_to gift.merchant.name, merchant_path(gift.merchant.id) %></h4>
                    <p><%= gift.description %></p>
                    <p><%= link_to 'Buy', gift_path(gift), :remote => true, 'data-toggle' =>  "modal", 'data-target' => "#myModal#{gift.id}", :class => "btn btn-primary", 'data-type' => "html" %></p>
                </div>
                <!-- Modal -->
                    <div class="modal fade" id="myModal<%= gift.id %>">
                        <div class="modal-dialog">
                            <div class="modal-content">
                                <%= render partial: 'show', :locals => { :gift => gift } %>
                            </div>
                        </div>
                    </div>
                <!-- End of Modal -->
            </div>
        </div>
        <% end %>
    </div>
</div>
¿Fue útil?

Solución

Your 'new' partial is being rendered by your 'show' partial and then that 'show' partial is being rendered by your 'index' view. That means it's only the code in your 'index' action that's being run. Since you don't instantiate an instance variable called @charge in your index action, @charge will return nil in the 'new' partial. That's why you get that error.

To fix that error, you should either add the below code to your index action:

@charge = Charge.new

That way, @charge will return an instance of Charge and not nil. You could also choose not to use a 'new' partial and just display the form for creating a new charge in a 'new' view of its own so that it runs the code in the 'new' action.

Hope that helps!

Otros consejos

In ChargesContorller::index you create a variable called @chargeS. Then in the _new.html.erb you are using @charge (no s).

To get your code to work, you can initiate a new @charge variable in index (besides @charges), or use Charge.new in the form, in place of @charge.

What I think confuses you, because it confused me until I figured it out, it that the render function DOES NOT run the method in the controller (in you case ChargesContorller::new), but only goes directly to the view and renders it. I may be mistaken here because your new is a partial which isn't connected to a controller method anyway (and running new from index seems weird to me). In any case you need to initialize your variable.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top