DaudiHell
DaudiHell

Reputation: 808

"undefined local variable or method `f' " on ruby on rails

In my app I'm rendering the partial below in the views/transactions/show.html.erb, but when I hit submit I get this error:

undefined local variable or method 'f' for #<PapersController:0x007fa790b51190>

In this line of the controller:

f.html { redirect_to "", notice: "Error: Paper Not created!!"}:

<%= form_for ( @newPaper ) do |f| %>

<div class="field">
    <%= f.label :date, class: 'form-text'%>
    <%= f.date_select :date %>
  </div>
<br />
  <div class="field">
    <%= f.label :paper_type %>
    <%= f.select(:paper_type, options_for_select(Paper::PAPER_TYPES)) %>
  </div>

  <br>
  <div class="field">
    <%= f.label :paper_weight %> :<%= f.number_field :paper_weight, class: 'form-fields'  %> -kg.
  </div>
 <br />
  <div class="field">
    <%= f.label :env_paper_weight %> :
    <%= f.number_field :env_paper_weight, class: 'form-fields' %>  -kg.
  </div>
  <br />

<br>

  <div class="actions">
    <%= f.submit "Add Paper" %>
  </div>
<% end %>

papers_controller.rb

class PapersController < ApplicationController

before_action :set_paper, only: [:edit, :update, :show, :destroy]
before_action :paper_owner, only: [ :edit, :update, :destroy]

def index 


  all_paper_type_values = Paper.all.pluck(:paper_type).uniq
   @data_for_chart = all_paper_type_values.map do |paper_type|
  { name: paper_type, data: Paper.where(paper_type: paper_type).group_by_month(:created_at).sum(:paper_weight)}
  end

    @pappi = Paper.all

    @newPaper = Paper.new


end

def new
    @paper = Paper.new
end

def create 

    @paper = Paper.new(paper_params)
    @paper.user_id = current_user.id

        if (@newPaper.save)
            redirect_to transaction_path(current_user), :notice => "Post has been saved successfully."
        else
            f.html { redirect_to "", notice: "Error: Paper Not created!!"}
        end 

end




def update
        if @paper.update(paper_params)
        flash[:success] = "Line was successfully updated"
        redirect_to papers_path(@paper)
    else
        render 'edit'
    end     

end

def destroy
    @paper.destroy
    flash[:danger] = "Line was successfully destroyed"
    redirect_to transaction_path(current_user) 
end


private

    def set_paper
        @paper = Paper.find(params[:id])
    end

def paper_params
    params.require(:paper).permit(:user_id, :paper_type, :date, :paper_weight, :env_paper_weight)

end

def paper_owner
            unless @paper.user_id == current_user.id
                flash[:notice] = 'Access denied as you are not owner of this Job'
                redirect_to papers_path
            end
end


end

transaction_controller.rb

class TransactionsController < ApplicationController

def new
    @paper = current_user.papers.build
    @kwst = current_user.kwsts.build
    @hwater = current_user.hwaters.build
    @transport = current_user.transports.build


end

def show

    @user = User.find(params[:id])
    @username = params[:id]

    @newPaper = Paper.new
    @newKwst = Kwst.new
    @newHwater = Hwater.new 
    @newTransport = Transport.new

    @papers = current_user.papers.order(created_at: :desc).limit(5)
    @kwsts = current_user.kwsts.order(created_at: :desc)
    @hwaters = current_user.hwaters.order(created_at: :desc)
    @transports = current_user.transports.order(created_at: :desc)

end    
end

I've changed the:

<%= form_for ( @newPaper ) do |f| %>

to

<%= form_for Paper.new do |f| %>

In the paper_controller.rb but still get the error. I'm kind of lost here, can someone help me?

Upvotes: 0

Views: 2718

Answers (2)

Pavan
Pavan

Reputation: 33542

undefined local variable or method 'f' for <PapersController:0x007fa790b51190>

The error triggers in this line

f.html { redirect_to "", notice: "Error: Paper Not created!!"}

as you not defined f in the controller method.

It seems you are trying write your create method using respond_to, then the create method should look like below

def create 
  @paper = Paper.new(paper_params)
  @paper.user_id = current_user.id
  respond_to do |f|
    if (@paper.save) #not @newPaper
      f.html {redirect_to transaction_path(current_user), :notice => "Post has been saved successfully."}
    else
      f.html { redirect_to "", notice: "Error: Paper Not created!!"}
     end
  end
end

Upvotes: 1

Fire Lancer
Fire Lancer

Reputation: 30135

The f in the two contexts you show is completely unrelated. Views and controllers share attributes (for a given request) but not local variables, and further your f variable is limited to the form_for block (from the do to the matching end), it has nothing at all to do with the PapersController#create method.

f.html could be a respond_to, but thats not really needed if you are only supporting HTML.

It is not really clear what you intend f.html { redirect_to "", notice: "Error: Paper Not created!!"} since that is in a different controller entirely. If you just want to redirect somewhere, then just use redirect_to directly, drop the f.html thing.

e.g.

redirect_to transaction_path(current_user), notice: "Error: Paper Not created!!"

If you want to display errors and keep the original form values then normally, you would have the form (normally an action called new) and the create in the same controller, and reuse the view.

class PapersController
  def new
    @paper = Paper.new
    render
  end
  def create
    @paper = Paper.new(paper_params)
    @paper.user = current_user
    if @paper.save
      redirect_to transaction_path(current_user), notice: "Post has been saved successfully."
    else
      render "new" # form_for will keep values from @paper, can also display @paper.errors
    end
  end
end

Allthough it is of course possible to render the same form/view from multiple controllers with full errors, etc. if you wish.

Upvotes: 0

Related Questions