Skip to content

Instantly share code, notes, and snippets.

@mainej
Created April 23, 2012 05:21
Show Gist options
  • Save mainej/2468960 to your computer and use it in GitHub Desktop.
Save mainej/2468960 to your computer and use it in GitHub Desktop.
anemic controllers, thin models, fat domain
class PostRepository
def self.update(id, post_updates, editor)
post = find(id)
raise SecurityTransgression unless can_edit?(post, editor)
post.update_attributes!(post_updates)
post
end
def self.find(id)
Post.find(id)
end
def self.can_edit?(post, editor)
editor.admin? || post.created_by?(editor)
end
end
require 'post_repository'
class Post
end
describe PostRepository do
describe ".update" do
let(:user) { stub! }
let(:post) { stub! }
before do
stub(user).admin { false }
stub(post).created_by?(user) { true }
stub(Post).find('1') { post }
end
it "returns the updated post" do
stub(post).update_attributes!(a: 'b') { true }
PostRepository.update('1', {a: 'b'}, user).should == post
end
context "permissions" do
it "allow admins to edit" do
stub(user).admin { true }
stub(post).created_by?(user) { false }
mock(post).update_attributes!(a: 'b') { true }
PostRepository.update('1', {a: 'b'}, user)
end
it "allow creator of post to edit" do
# default config
mock(post).update_attributes!(a: 'b') { true }
PostRepository.update('1', {a: 'b'}, user)
end
it "disallow others from editing" do
stub(user).admin { false }
stub(post).created_by?(user) { false }
dont_allow(post).update_attributes!(a: 'b')
expect {
PostRepository.update('1', {a: 'b'}, user)
}.to raise_error(SecurityTransgression)
end
end
it "raises error when post is missing" do
stub(Post).find(1) { raise ActiveRecord::RecordNotFound }
expect {
PostRepository.update('1', {a: 'b'}, user)
}.to raise_error(ActiveRecord::RecordNotFound)
end
it "raises error when post becomes invalid" do
stub(post).update_attributes!(a: 'b') { raise ActiveRecord::RecordInvalid }
expect {
PostRepository.update('1', {a: 'b'}, user)
}.to raise_error(ActiveRecord::RecordInvalid)
end
end
end
class PostsController < ApplicationController
# no before filters here, but heavy use of rescue_from, responds_to in ApplicationController
def update
post = PostRespository.update(params[:id], params[:post], current_user)
respond_with post
end
end
require 'spec_helper'
describe PostsController do
before { log_in mock_user }
it "redirects to post's page" do
stub(PostRepository).update('1', {a: 'b'}, mock_user) { mock_post }
put :update, id: '1', post: {a: 'b'}
response.should redirect_to(post_url(mock_post))
end
it "renders 404 when post repository can't find post" do
stub(PostRepository).update('1', {a: 'b'}, mock_user) { raise ActiveRecord::RecordNotFound }
put :update, id: '1', post: {a: 'b'}
response.code.should == "404"
end
it "renders 403 when user does not have permission to edit post" do
stub(PostRepository).update('1', {a: 'b'}, mock_user) { raise SecurityTransgression }
put :update, id: '1', post: {a: 'b'}
response.code.should == "403"
end
it "renders 422 when post becomes invalid" do
stub(PostRepository).update('1', {a: 'b'}, mock_user) { raise ActiveRecord::RecordInvalid }
put :update, id: '1', post: {a: 'b'}
response.code.should == "422"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment