Syk
Syk

Reputation: 393

Association not recognized, undefined method error

I created 2 scaffolds 'mepager' and 'pimp' and linked the models like this:

class Mepager < ActiveRecord::Base
    belongs_to :pimp
end

class Pimp < ActiveRecord::Base
    has_one :mepager
end

I added following lines to my routing:

resources :pimps do  
    resources :mepagers
end

And my mepager create action looks like this:

def create
    @mepager = @pimp.build_mepager(mepager_params)

    respond_to do |format|
      if @mepager.save
        format.html { redirect_to @mepager, notice: 'Mepager was successfully created.' }
        format.json { render action: 'show', status: :created, location: @mepager }
      else
        format.html { render action: 'new' }
        format.json { render json: @mepager.errors, status: :unprocessable_entity }
      end
    end
end

And for @pimp to set

def setPimp
    @pimp = Pimp.find_by_id(:pimp_id)
end 

But if I try to create a new mepager at pimps/1/mepagers/new I get an undefined method build_mepager error.

undefined method `build_mepager' for nil:NilClass

I tried the same in the rails console and it worked with just that method. So I guess somethings still missing to make it work on my web application.

Btw I m using rails 4.0.0

Regards!

Routing

Prefix Verb   URI Pattern                                 Controller#Action
pimps GET    /pimps(.:format)                            pimps#index
POST   /pimps(.:format)                            pimps#create
new_pimp GET    /pimps/new(.:format)                        pimps#new
edit_pimp GET    /pimps/:id/edit(.:format)                   pimps#edit
pimp GET    /pimps/:id(.:format)                        pimps#show
PATCH  /pimps/:id(.:format)                        pimps#update
PUT    /pimps/:id(.:format)                        pimps#update
DELETE /pimps/:id(.:format)                        pimps#destroy
root GET    /                                           pimps#index
pimp_mepagers GET    /pimps/:pimp_id/mepagers(.:format)          mepagers#index
POST   /pimps/:pimp_id/mepagers(.:format)          mepagers#create
new_pimp_mepager GET    /pimps/:pimp_id/mepagers/new(.:format)      mepagers#new
edit_pimp_mepager GET    /pimps/:pimp_id/mepagers/:id/edit(.:format) mepagers#edit
pimp_mepager GET    /pimps/:pimp_id/mepagers/:id(.:format)      mepagers#show
PATCH  /pimps/:pimp_id/mepagers/:id(.:format)      mepagers#update
PUT    /pimps/:pimp_id/mepagers/:id(.:format)      mepagers#update
DELETE /pimps/:pimp_id/mepagers/:id(.:format)      mepagers#destroy
GET    /pimps(.:format)                            pimps#index
POST   /pimps(.:format)                            pimps#create
GET    /pimps/new(.:format)                        pimps#new
GET    /pimps/:id/edit(.:format)                   pimps#edit
GET    /pimps/:id(.:format)                        pimps#show
PATCH  /pimps/:id(.:format)                        pimps#update
PUT    /pimps/:id(.:format)                        pimps#update
DELETE /pimps/:id(.:format)                        pimps#destroy

Altered line in pimp controller

def create
    @pimp = Pimp.new(pimp_params)
      respond_to do |format|
      if @pimp.save
               format.html { redirect_to new_pimp_mepager_path, notice: 'Product Improvement was successfully created.' }
            format.json { render action: 'show', status: :created, location: @pimp }
      else
            format.html { render action: 'new' }
            format.json { render json: @pimp.errors, status: :unprocessable_entity }
      end
    end
end

mepager controller

class MepagersController < ApplicationController
  before_action :set_mepager, only: [:show, :edit, :update, :destroy]

  def setPimp
    @pimp = Pimp.find(params[:pimp_id])
  end

  # GET /mepagers
  # GET /mepagers.json
  def index
    @mepagers = Mepager.all
  end

  # GET /mepagers/1
  # GET /mepagers/1.json
  def show
  end

  # GET /mepagers/new
  def new
    @mepager = Mepager.new
  end

  # GET /mepagers/1/edit
  def edit
  end

  # POST /mepagers
  # POST /mepagers.json
  def create
    raise params[:pimp_id].inspect
    @mepager = @pimp.build_mepager(mepager_params)

    respond_to do |format|
      if @mepager.save
        format.html { redirect_to @mepager, notice: 'Mepager was successfully created.' }
        format.json { render action: 'show', status: :created, location: @mepager }
      else
        format.html { render action: 'new' }
        format.json { render json: @mepager.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /mepagers/1
  # PATCH/PUT /mepagers/1.json
  def update
    respond_to do |format|
      if @mepager.update(mepager_params)
        format.html { redirect_to @mepager, notice: 'Mepager was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @mepager.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /mepagers/1
  # DELETE /mepagers/1.json
  def destroy
    @mepager.destroy
    respond_to do |format|
      format.html { redirect_to mepagers_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_mepager
      @mepager = Mepager.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def mepager_params
      params.require(:mepager).permit(:pre, :post, :comment, :save_h, :save_c, :save_other, :save_otherv, :affect_design, :affect_stress, :affect_me, :affect_other, :affect_dno, :affect_mid, :affect_otherdoc, :owner, :pps, :reference)
    end
end

Upvotes: 0

Views: 82

Answers (1)

Taryn East
Taryn East

Reputation: 27747

The problem is probably here:

@pimp = Pimp.find_by_id(:pimp_id)

what you are doing is finding a pimp that has an id of the literal symbol :pimp_id (which is highly unlikely to exist)

Probably what you want is the parameter: params[:pimp_id]

EDIT:

and for the second part.

for the create action to work with a real @pimp (that can be found by :pimp_id), you must also do the same on the new action too! Otherwise create won't work.

Can I recommend something like...

before_action :fetch_pimp, only: [:new, :create]


# GET /mepagers/new
def new
  @mepager = Mepager.new
end

# POST /mepagers
# POST /mepagers.json
def create
  @mepager = @pimp.build_mepager(mepager_params)

  respond_to do |format|
    # as previously...
  end
end

# ...
private
   def fetch_pimp
     @pimp = Pimp.find(params[:pimp_id])
   end

Upvotes: 4

Related Questions