Skip to content

Instantly share code, notes, and snippets.

@arturdent
Created December 5, 2012 14:53
Show Gist options
  • Save arturdent/4216093 to your computer and use it in GitHub Desktop.
Save arturdent/4216093 to your computer and use it in GitHub Desktop.
shared_examples_for :CRUD do |options|
root_key = options[:klass].name.split('::').last.camelize(:lower)
options[:index_path] ||= "/#{options[:klass].name.underscore.pluralize}"
options[:show_path] ||= "#{options[:index_path]}/:id"
options[:security_context] = $user if options[:security_context].nil?
options[:model_pk] ||= :id
index_path, show_path, actions = options[:index_path], options[:show_path], options[:actions]
before :all do
options.each{|k,v| instance_variable_set :"@#{k}", v }
@root_key = root_key
@model = @klass.make!(@klass_arguments.try(:call) || {})
@show_path = @show_path.gsub ':id', @model.send(@model_pk).to_s
end
def remove_timestamps!(attributes)
%w(created_at updated_at).each{|key| attributes.delete(key) || attributes.delete(key.to_sym) }
attributes
end
if actions.include?(:index)
describe_request :index, request_path: index_path, method: 'GET' do
it "lists #{root_key.pluralize}" do
get @index_path
response.code.should == '200'
response.body.should have_json_size(@klass.count).at_path(@root_key.pluralize)
end
end
end
if actions.include?(:create)
describe_request :create, request_path: index_path, method: 'POST' do
it "creates #{root_key}" do
attributes = @klass.make(@klass_arguments.try(:call) || {}).attributes
attributes = if @security_context
attributes.slice(
*@klass.restrict(@security_context).reflect_on_security[:restrictions].allowed_fields[:create].map(&:to_s)
)
else
remove_timestamps!(attributes)
end
attributes.merge!(@additional_attributes.try(:call) || {})
if options[:unique_attr]
@klass.destroy_all
end
expect {
post @index_path, @root_key.underscore => attributes
response.code.should == '200'
}.to change(@klass, :count).by(1)
end
it "rejects to create invalid #{root_key}" do
expect {
if options[:required_root_key]
@blank_attributes = @klass.make.as_json
else
@blank_attributes = {}
end
post @index_path, @root_key.underscore => @blank_attributes
response.code.should == '422'
}.to change(@klass, :count).by(0)
end
end
end
if actions.include?(:show)
describe_request :show, request_path: show_path, method: 'GET' do
it "reads #{root_key}" do
get @show_path
response.code.should == '200'
response.body.should have_json_keys([@root_key])
end
end
end
if actions.include?(:update)
describe_request :update, request_path: show_path, method: 'PUT' do
it "updates #{root_key}" do
attributes = @klass.make(@klass_arguments.try(:call) || {}).attributes
attributes = if @security_context
attributes.slice(
*@klass.restrict(@security_context).reflect_on_security[:restrictions].allowed_fields[:update].map(&:to_s)
)
else
remove_timestamps!(attributes)
end
attributes.merge!(@additional_attributes.try(:call) || {})
put @show_path, @root_key.underscore => attributes
response.code.should == '200'
end
if actions.include?(:update_invalid)
it "rejects to update invalid #{root_key}" do
attributes = if @security_context
@klass.restrict(@security_context).reflect_on_security[:restrictions].allowed_fields[:update].
each_with_object({}) {|k, h| h[k] = ''}
else
@klass.new.attributes
end
attributes.merge!(@additional_attributes)
put @show_path, @root_key.underscore => attributes
response.code.should == '422'
end
end
end
end
if actions.include?(:destroy)
describe_request :delete, request_path: show_path, method: 'DELETE' do
it "deletes #{root_key}" do
expect {
delete @show_path
response.code.should == '200'
}.to change(@klass, :count).by(-1)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment