Odd behaviour in controller

21 views
Skip to first unread message

Jean le Roux

unread,
Feb 12, 2015, 8:56:20 AM2/12/15
to cape-town-r...@googlegroups.com
Hi there

Here is my controller:

class Api::V1::ClientsController < ::ApplicationController
  def index
    respond_with @clients
  end

  def show
    respond_with @client
  end

  def create
    @client.save
    respond_with @client
  end

  def update
    @client.update_attributes(client_params)
    respond_with @client
  end

  def destroy
    @client.destroy
    respond_with @client
  end

  private

  def client_params
    params.require(:client).permit(:name, :user_ids => [])
  end
end

And here is my spec output:

Api::V1::ClientsController
  GET index

    returns a list of clients
  GET show

    returns an existing client
  POST create
    creates a new client (FAILED - 1)
  PUT update
    updates an existing client
  DELETE destroy
    destroys an existing client

Failures:

  1) Api::V1::ClientsController POST create creates a new client
     Failure/Error: post :create, {:client => client.attributes}
     NoMethodError:
       undefined method `client_url' for #<Api::V1::ClientsController:0x000000051afea0>
     # ./app/controllers/api/v1/clients_controller.rb:12:in `create'
     # ./spec/controllers/api/v1/clients_controller_spec.rb:30:in `block (4 levels) in <top (required)>'
     # ./spec/controllers/api/v1/clients_controller_spec.rb:29:in `block (3 levels) in <top (required)>'

Finished in 0.83597 seconds (files took 5.88 seconds to load)
5 examples, 1 failure


Notice how only #create fails with that undefined method error.

This is a rails 4.2 + rails-api application. I'm just stumped why create would fail here, if update and everything else works.

Anyone seen this before?  Any ideas ?

Routes look like:

  namespace :api, :constraints => {:format => 'json'} do
    namespace :v1 do
      resource :home, :only => [:show]

      resources :users, :except => [:new, :edit]
      resources :clients, :except => [:new, :edit]

    end
  end



--
Kind regards.

Jean le Roux
Yardmaster

mobile: +27 84 606 5950
office:   +27 21 851 9374
twitter:   @shuntyard
web:      www.shuntyard.co.za
email:    je...@shuntyard.co.za



Please consider the environment before printing this email or any related attachments.

Wiehann

unread,
Feb 13, 2015, 4:00:05 PM2/13/15
to cape-town-r...@googlegroups.com
Jean,

Have you tried providing the format as :json when making the request in your spec ie.
post :create, :client => client.attributes, format: :json

If you're using something like FactoryGirl you could try the following
post :create, :client => attributes_for(:client), format: :json

-- Wiehann

Andre Mouton

unread,
Feb 16, 2015, 7:35:09 AM2/16/15
to cape-town-r...@googlegroups.com
Hi Jean,

Mind posting the controller spec for that.

Regards,
Andre Mouton

--
You received this message because you are subscribed to the Google Groups "Cape Town Ruby Brigade" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cape-town-ruby-br...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jean le Roux

unread,
Feb 16, 2015, 8:29:33 AM2/16/15
to cape-town-r...@googlegroups.com
Sure, very basic stuff though:

require 'rails_helper'

RSpec.describe Api::V1::ClientsController, :type => :controller do

  describe "GET index" do
    api_user
    it "returns a list of clients" do
      3.times do
        create(:client)
      end
      get :index
      expect(JSON.parse(response.body).count).to eq(3)
    end
  end

  describe "GET show" do
    api_user
    it "returns an existing client" do
      client = create(:client)
      get :show, {:id => client.id}
      expect(response.body).to eq(client.to_json)
    end
  end

  describe "POST create" do
    api_user
    it "creates a new client" do
      client = build(:client)
      expect {
        post :create, {:client => client.attributes}
      }.to change{Client.count}.by(1)
    end
  end

  describe "PUT update" do
    api_user
    it "updates an existing client" do
      client = create(:client)
      client.name = 'updated name'
      expect {
        put :update, {:id => client.id, :client => client.attributes}
        client.reload
      }.to change{client.updated_at}
    end
  end

  describe "DELETE destroy" do
    api_user
    it "destroys an existing client" do
      client = create(:client)
      expect {
        delete :destroy, {:id => client.id}
      }.to change{Client.count}.by(-1)
    end
  end
end

I should mention that I found a work-around:

  def create
    @client.save
    respond_with @client, location: -> { api_v1_client_path(@client)}
  end


The fix stems from the responders gem and how it deals with :post actions.

--
Jean le Roux

phone: +27 84 606 5950
twitter: @elarex
skype: jeanlrx77
Reply all
Reply to author
Forward
0 new messages