Skip to content

Instantly share code, notes, and snippets.

@armanm
Last active October 28, 2022 11:42
Show Gist options
  • Save armanm/293290d29f9188ed7f7705d6e84dcc1b to your computer and use it in GitHub Desktop.
Save armanm/293290d29f9188ed7f7705d6e84dcc1b to your computer and use it in GitHub Desktop.
Better isolation of controllers testing without using instance variables and checking assigns in specs
class ApplicationController < ActionController::Base
private
def on_error_render(action, assigns = nil)
yield
rescue StandardError
render action, assigns:, status: :internal_server_error
end
end
class HomeController < ApplicationController
def new
render :new, assigns: { user: User.new }
end
def create
user = User.new(name: params[:user][:name])
on_error_render(:new, user: user) do
user.save!
render :new, assigns: { user: user }
end
end
end
require 'rails_helper'
describe HomeController, type: :controller do
describe "GET new" do
it 'renders the new view' do
@user = double("user", name: "Foo")
expect(User).to receive(:new).with(no_args).and_return(@user)
expect(controller).to render_view_with(:new, assigns: {user: @user})
get :new
end
end
describe "POST create" do
it 'renders creates a new user and renderes the form' do
@user = double("user", name: "Foo")
expect(User).to receive(:new).with(name: "Foo").and_return(@user)
expect(@user).to receive(:save!)
expect(controller).to handle_error_with(:new, user: @user)
expect(controller).to render_view_with(:new, assigns: { user: @user })
post :create, params: {user: {name: "Foo"}}
end
end
end
<%= tag.mark(flash[:success]) if flash[:success] %>
<%= form_for @user, url: {action: "create"} do |f| %>
<%= f.text_field :name, placeholder: "what's your name" %>
<%= tag.mark(@user.errors.full_messages.join) if @user.errors.any? %>
<div><%= f.submit "Create" %></div>
<% end %>
RSpec.configure do |c|
c.include Module.new {
def render_view_with(*args)
receive(:render).with(*args).and_call_original
end
def handle_error_with(*args)
receive(:on_error_render).with(*args).and_call_original
end
}, type: :controller
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment