On Fri, Oct 16, 2009 at 7:21 AM, Sergey Rogachev <[email protected]> wrote:
> I don't know what is need to set in the variable ADDRESSES:
> Organization.stub!(:find_by_id).with("100").and_return(mock_organization(:id
> => "100", :addresses => ??? ))
>
> Somebody help me. Any ideas? I tried to find the solution of problem but
> I can't.
>
> --- rspec - controllers
> def mock_organization(stubs={})
> �...@parent_object ||= mock_model(Organization, stubs)
> end
>
> it "assigns a newly created address as @address" do
>  Organization.stub!(:find_by_id).with("100").and_return(
>       mock_organization(:id => "100", :addresses => ??? )) <<!--- here
> �...@parent_object.stub(:addresses).stub(:new).with({:these => 'params'})
>
>  post :create, :address => {:these => 'params'}, :organization_id =>
> @parent_object.id
>  assigns[:address].should equal(mock_address)
> end
>
> ---- models ----
> class Organization < ActiveRecord::Base
>  has_many :addresses, :as => :addressable
> end
>
> class Address < ActiveRecord::Base
>  belongs_to :addressable, :polymorphic => true
> end
>
> ----- controllers -----
> class AddressesController < ApplicationController
>  before_filter :load_parent_object
>
>  def create
>   �...@address = @parent_object.addresses.new(params[:address])
>
>    respond_to do |format|
>      if @address.save
>        flash[:notice] = 'Address was successfully created.'
>        format.html { redirect_to(@parent_object) }
>        format.xml  { render :xml => @address, :status => :created,
> :location => @address }
>      else
>        format.html { render :action => "new" }
>        format.xml  { render :xml => @address.errors, :status =>
> :unprocessable_entity }
>      end
>    end
>  end
>
>  private
>
>  def load_parent_object
>    if params[:organization_id]
>     �...@parent_object = Organization.find_by_id(params[:organization_id])
>    end
>  end
>
> end

Hi Sergey,

This is a great example of why it's helpful to write the examples
first. There is no need for this controller to know anything about
organizations - that can be handled by the model, where the
association is defined. Here's how I might have done this:

it "assigns a newly created address as @address" do
  address = stub_model(Address)
  Address.stub(:new).
    with({:these => 'params'}).
    and_return(address)

  post :create, :address => {:these => 'params'}

  assigns[:address].should equal(address)
end

class AddressesController < ApplicationController
  def create
    @address = Address.new(params[:address])

    respond_to do |format|
      if @address.save
        flash[:notice] = 'Address was successfully created.'
        format.html { redirect_to(@address.addressable) }
        format.xml  { render :xml => @address, :status => :created,
:location => @address }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @address.errors, :status =>
:unprocessable_entity }
      end
    end
  end
end

Now the post to the create action can include :organization_id within
params[:address] instead of as a separate hash key, and all is well.

That said, the following _should_ work w/ your current design:

it "assigns a newly created address as @address" do
  address     = mock('address')
  addresses   = mock('addresses')
  addressable = mock_model(Organization, :id => "100", :addresses => addresses)

  Organization.stub!(:find_by_id).with("100").and_return(addressable)
  addressable.stub(:addresses).and_return(addresses)
  addresses.stub(:new).with({:these => 'params'}).and_return(address)

  post :create, :address => {:these => 'params'}, :organization_id => "100"

  assigns[:address].should equal(address)
end

class AddressesController < ApplicationController
  before_filter :load_addressable

  def create
    @address = @addressable.addresses.new(params[:address])

    respond_to do |format|
      if @address.save
        flash[:notice] = 'Address was successfully created.'
        format.html { redirect_to(@addressable) }
        format.xml  { render :xml => @address, :status => :created,
:location => @address }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @address.errors, :status =>
:unprocessable_entity }
      end
    end
  end

private

  def load_addressable
    if params[:organization_id]
      @addressable = Organization.find_by_id(params[:organization_id])
    end
  end

end

Notes:

* I changed @parent_object to @addressable, since that's how the
association is labeled in the code.
* The only object in the code example that uses mock_model is the one
that is actually needs to behave like an AR model in the context of
this example

Let me know if you have any questions.

Cheers,
David
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to