class Endpoint::Stub

Represents a stubbed endpoint that creates, updates, destroys, and stores data based on http requests.

Attributes

stubs[R]
defaults[R]
model[R]
records[RW]
site[R]

Public Class Methods

[](model) click to toggle source

Gets or creates a stub for the given model. i.e. Endpoint::Stub

# File lib/endpoint/stub.rb, line 63
def [](model)
  create_for model or get_for model
end
clear!() click to toggle source

Clears all endpoint stubs.

# File lib/endpoint/stub.rb, line 56
def clear!
  @stubs = {}
end
clear_all_records!() click to toggle source
# File lib/endpoint/stub.rb, line 50
def clear_all_records!
  @stubs.values.each(&:clear_records!)
end
clear_for(model) click to toggle source

Removes fake endpoint for the given model, meaning any ActiveResource activity on the model will raise errors once again.

# File lib/endpoint/stub.rb, line 42
def clear_for(model)
  stubs.delete assure_model model
end
create_for(model, options={}, &block) click to toggle source

Creates a fake endpoint for the given ActiveResource model.

The options hash currently only accepts :defaults, which allows you to define default attribute values for the endpoint to consider on record creation.

If a block is supplied, it will be executed in the context of the new Endpoint::Stub, allowing you to elegantly mock custom responses if needed.

# File lib/endpoint/stub.rb, line 23
def create_for(model, options={}, &block)
  model = assure_model model
  return if stubs.keys.map(&:name).include? model.name
  new_stub = Stub.new(model, options)

  EndpointStub::Config.default_responses.each do |response|
    new_stub.mock_response(*response)
  end

  @stubs[model] = new_stub

  new_stub.instance_eval(&block) if block_given?
  new_stub
end
each(&block) click to toggle source
# File lib/endpoint/stub.rb, line 67
def each(&block)
  @stubs.each(&block)
end
get_for(model) click to toggle source
# File lib/endpoint/stub.rb, line 46
def get_for(model)
  @stubs[assure_model(model)]
end
new(model, options) click to toggle source
# File lib/endpoint/stub.rb, line 85
def initialize(model, options)
  @defaults = options[:defaults] || {}

  @model = model
  @site = URI "#{model.site}/#{model.name.split('::').last.underscore.pluralize}"

  @responses = {}

  @records = []
end

Private Class Methods

assure_model(model) click to toggle source
# File lib/endpoint/stub.rb, line 72
def assure_model(model)
  if model.ancestors.include? ActiveResource::Base
    model
  else
    Kernel.const_get model
  end
end

Public Instance Methods

add_default(attrs) click to toggle source

Adds default attributes for record creation.

# File lib/endpoint/stub.rb, line 171
def add_default(attrs)
  @defaults.merge!(attrs)
end
Also aliased as: add_defaults
add_defaults(attrs)
Alias for: add_default
add_record(attrs) click to toggle source

Adds a record to the stub, automatically assigning an id as though it were in a database.

# File lib/endpoint/stub.rb, line 99
def add_record(attrs)
  unless attrs.is_a? Hash
    raise "Endpoint::Stub#add_record expects a Hash. Got #{attrs.class.name}."
  end
  attrs[:id] = current_id
  attrs.merge!(@defaults) { |k,a,b| a }
  @records << attrs
  attrs
end
clear_records!() click to toggle source

Clear all records in this stub.

# File lib/endpoint/stub.rb, line 133
def clear_records!
  @records = []
end
current_id() click to toggle source

The next id for a record to be assigned to.

# File lib/endpoint/stub.rb, line 151
def current_id
  @records.count
end
drop_overrides!() click to toggle source

Removes all overrides, reducing each response to their originals.

# File lib/endpoint/stub.rb, line 234
def drop_overrides!
  @responses.each do |type, responses|
    responses.each do |route, response|
      response.drop_overrides!
    end
  end
end
last_id() click to toggle source

The last assigned id.

# File lib/endpoint/stub.rb, line 145
def last_id
  @records.count-1
end
location(id) click to toggle source

Gets the url location for the given id, as used by RESTful record creation.

# File lib/endpoint/stub.rb, line 164
def location(id)
  site = @site.to_s[-1] == '/' ? @site.to_s[0...-1] : @site
  "#{site}/#{id}"
end
mock_response(type, route='', proc=nil, &block) click to toggle source

Mock a custom response. Requires a type (http mthod), and route. This method will override any previous responses assigned to the given type and route.

The route is the uri relative to the record's assigned site and can be formatted similarly to rails routes. Such as: '/test/:some_param.json' or '.xml' to simply imply the model's site with '.xml' appended.

Lastly, a proc or block is needed to actually handle requests. The proc will be called with the request object, the extracted parameters from the uri, and the stub object so that you can interact with the stubbed records.

# File lib/endpoint/stub.rb, line 191
def mock_response(type, route='', proc=nil, &block)
  proc = block if block_given?
  route = clean_route route

  @responses[type] ||= {}
  @responses[type][route].deactivate! if @responses[type][route]
  @responses[type][route] = Response.new(type, prepare_uri(type, route), self, &proc)
  @responses[type][route].activate!
end
model_name() click to toggle source

The name of the represented model in underscore notation.

# File lib/endpoint/stub.rb, line 157
def model_name
  @model.name.underscore
end
override_all(&block) click to toggle source

Overrides all currently assigned responses. Will not have any effect on responses mocked after this method is called.

# File lib/endpoint/stub.rb, line 224
def override_all(&block)
  @responses.each do |type, responses|
    responses.each do |route, response|
      response.add_to_stack(&block)
    end
  end
end
override_response(type, route, proc=nil, &block) click to toggle source

Same thing as mock_response, except it will not overWRITE existing mocks. Instead, it allows you to call a block inside of your response which will act as a 'super' call, invoking previously defined responses. Yielding inside a top-level response will give you an empty hash, so no nil related issues should arrise (unless of course the super-response returns nil, which it shouldn't).

Also note that this does not re-activate a deactivated response.

# File lib/endpoint/stub.rb, line 210
def override_response(type, route, proc=nil, &block)
  proc = block if block_given?
  route = clean_route route

  if @responses[type] and @responses[type][route]
    @responses[type][route].add_to_stack(&proc)
  else
    mock_response(type, route, proc)
  end
end
record(id) click to toggle source

Get the record at the given id. Accepts strings as well as ints.

# File lib/endpoint/stub.rb, line 139
def record(id)
  @records[id.to_i]
end
remove_record(id) click to toggle source

Removes the record with the given id from the fake database.

# File lib/endpoint/stub.rb, line 123
def remove_record(id)
  id = id.to_i
  if @records[id]
    @records[id] = nil
    true
  end
end
unmock_response(type, route) click to toggle source

Remove a mocked response with the given type and route.

# File lib/endpoint/stub.rb, line 244
def unmock_response(type, route)
  route = clean_route route
  if @responses[type] && @responses[type][route]
    @responses[type][route].deactivate!
    @responses[type][route] = nil
    true
  end
end
update_record(id, attrs) click to toggle source

Updates the record with the given id with the given attributes.

# File lib/endpoint/stub.rb, line 111
def update_record(id, attrs)
  unless attrs.is_a? Hash
    raise "Endpoint::Stub#update_record expects a Hash. Got #{attrs.class.name}."
  end
  id = id.to_i
  if @records[id]
    @records[id].merge! attrs
  end
end

Private Instance Methods

clean_route(route) click to toggle source
# File lib/endpoint/stub.rb, line 272
def clean_route(route)
  route = route[1..-1] if route[0] == '/'
  route = route[0...-1] if route[-1] == '/'
  route
end
prepare_uri(type, route) click to toggle source
# File lib/endpoint/stub.rb, line 254
def prepare_uri(type, route)
  site = "#{@site.scheme}://#{@site.host}:#{@site.port}"
  path = @site.path.split(/\/+/).reject(&:empty?)

  if route[0] == '.' && !route.include?('/')
    # This allows passing '.json', etc as the route
    if path.last
      path = path[0...-1] + [path.last+route]
    else
      site += route
    end
  else
    path += route.split('/')
  end

  URI.parse site+'/'+path.join('/')
end