Last active
August 29, 2015 13:56
-
-
Save ntl/8904880 to your computer and use it in GitHub Desktop.
The idea here is to give you a simple method that can define your ivar for you, protecting against `nil` proactively, and record the location where the ivar was defined. Best part is, if someone looks for where `#expose` is defined, they'll be happy to find out it's not in a gem. Easy to modify/understand.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Instead of ditching ivars, just make them easier to discover: | |
class ApplicationController < ActionController::Base | |
private | |
# Expose an object as an ivar to your views. Explodes if you try to assign nil. | |
# | |
# Use: | |
# | |
# admin = Admin.find_by(email: "[email protected]") | |
# | |
# expose(admin) # Defines @admin, because admin.class is Admin | |
# expose(admin, as: "@user") # Overrides default ivar name | |
# expose(admin, permit_nil: true) # Does *not* blow up if admin is nil | |
# | |
def expose(object, as: "@#{object.class.name.underscore}", permit_nil: false) | |
if instance_variable_defined?(as) | |
raise "Instance variable #{as} already defined!" | |
end | |
if object.nil? && permit_nil | |
raise "Tried to expose #{as} as nil!" | |
end | |
unless Rails.env.production? | |
exposed_variables[as] = OpenStruct.new(object: object, source: caller_locations[1]) | |
end | |
instance_variable_set as, object | |
end | |
def exposed_variables | |
# Add the underscores before and after to indicate that this variable is srs bsns. | |
@__exposed_variables__ ||= {} | |
end | |
def source_for_ivar(ivar) | |
exposed_variables.find { |k,v| v.object == ivar }.try(:source) | |
end | |
end | |
# Usage | |
class OrdersController < ApplicationController | |
def show | |
order = Order.find(params[:id]) | |
expose order | |
end | |
end | |
# When you want to override the name: | |
class OrdersController < ApplicationController | |
def show | |
order = PaypalOrder.find(params[:id]) | |
expose order, as: "@order" | |
end | |
end | |
# Now, your view can go back to using ivars, knowing that @order will never be nil, | |
# and that if you ever need to know where it came from, you can find it. | |
# app/views/orders/show.html.erb | |
# | |
# <dl> | |
# <dt>Order Number</dt> | |
# <dt><%= @order.id %></dt> | |
# </dl> |
expose(self)
is probably a bad practice.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Of course, this should really be a
Concern
Also, nothing is stopping anyone on your project from not using
#expose
, but my aim was for the least invasive solution keeping to the "rails way."