module RSpec::Rails::Mocks

def stub_model(model_class, stubs={})

stub_model(Person) {|person| person.first_name = "David"}
stub_model(Person, :to_param => 37)
stub_model(Person).as_new_record
stub_model(Person)

@example

inherently more state-based than interaction-based.
helper), it is especially useful in view examples, which are
While you can use stub_model in any example (model, view, controller,

example a bit more descriptive.
case persisted? will return false, but using `as_new_record` makes the
set the id to nil. You can also explicitly set :id => nil, in which
the object to behave as a new record, sending it `as_new_record` will
This means that by default persisted? will return true. If you want
persisted? is overridden to return the result of !id.nil?

framework.
assigned as a stub return value using RSpec's mocking/stubbing
If the model does not have a matching attribute, the key/value pair is
(determined by `respond_to?`) it is simply assigned the submitted values.
For each key in `stubs`, if the model has a matching attribute

`ActiveRecord` model, it is prohibited from accessing the database*.
generated value that is unique to each object. If `Model` is an
Creates an instance of `Model` with `to_param` stubbed using a
def stub_model(model_class, stubs={})
  model_class.new.tap do |m|
    m.extend ActiveModelStubExtensions
    if defined?(ActiveRecord) && model_class < ActiveRecord::Base
      m.extend ActiveRecordStubExtensions
      primary_key = model_class.primary_key.to_sym
      stubs = stubs.reverse_merge(primary_key => next_id)
      stubs = stubs.reverse_merge(:persisted? => !!stubs[primary_key])
    else
      stubs = stubs.reverse_merge(:id => next_id)
      stubs = stubs.reverse_merge(:persisted? => !!stubs[:id])
    end
    stubs = stubs.reverse_merge(:blank? => false)
    stubs.each do |k,v|
      m.__send__("#{k}=", stubs.delete(k)) if m.respond_to?("#{k}=")
    end
    m.stub(stubs)
    yield m if block_given?
  end
end