def lookup_context
ActionView::LookupContext.new(self.class._view_paths)
end
def view_renderer
ActionView::Renderer.new(lookup_context)
end
def _render_template(options)
view_renderer.render(view_context, options)
end
Slide 25
Slide 25 text
def view_context
ActionView::Base.new(view_renderer, view_assigns, self)
end
Slide 26
Slide 26 text
Maybe templates
could be rendered
in the controller
context?
Slide 27
Slide 27 text
class BasicController < ActionController::Base
include ActionView::Context # STEP 1
before_filter :_prepare_context # STEP 2
def hello_world
@value = "Hello"
end
protected
def view_context # STEP 3
self
end
def __controller_method__
"controller context!"
end
end
Slide 28
Slide 28 text
# app/views/basic/hello_world.html.erb
<%= @value %> from <%= __controller_method__ %>
# would return...
Hello from controller context!
class PostsController < ApplicationController
use ActiveRecord::IdentityMap::Middleware, :only => :index
# ...
end
# And this builds the middleware stack ...
PostsController.action(:index)
Slide 53
Slide 53 text
def self.action(name)
middleware_stack.build(name.to_s) do |env|
new.dispatch(name, ActionDispatch::Request.new(env))
end
end
Slide 54
Slide 54 text
def self.action(name, klass = ActionDispatch::Request)
middleware_stack.build(name.to_s) do |env|
new.dispatch(name, klass.new(env))
end
end
ActiveRecord::Base.connection.increment_open_transactions
ActiveRecord::Base.connection.begin_db_transaction
at_exit do
ActiveRecord::Base.connection.rollback_db_transaction
ActiveRecord::Base.connection.decrement_open_transactions
end
Slide 58
Slide 58 text
Instead provide a
hook...
Slide 59
Slide 59 text
class ActiveRecord::Railtie < Rails::Railtie
console do |sandbox|
if sandbox
require "active_record/railties/console_sandbox"
end
ActiveRecord::Base.logger = Logger.new(STDERR)
end
end
Slide 60
Slide 60 text
Liskov
Substitution
Principle
Slide 61
Slide 61 text
“Derived classes
must be
substitutable for
their base classes”
- Uncle Bob
Slide 62
Slide 62 text
“Derived classes
must be
substitutable for
their base classes”
- Uncle Bob
Slide 63
Slide 63 text
@rack_app.call
•Receives a hash
•Returns an array with
status code, headers and
an object that responds
Slide 64
Slide 64 text
Define
substitutable but
also don’t violate
the principle
Slide 65
Slide 65 text
Datamapper
x
Active Record
Slide 66
Slide 66 text
Active Model
User.model_name
user.persisted?
user.valid?
user.errors
user.to_key
user.to_param
Slide 67
Slide 67 text
How do we ensure
substitutability?
Slide 68
Slide 68 text
ActiveModel::Lint::Tests
Slide 69
Slide 69 text
class LintTest < ActiveSupport::TestCase
include ActiveModel::Lint::Tests
def setup
@model = SomeDatamapperModel.new
end
end
Slide 70
Slide 70 text
Interface
Segregation
Principle
Slide 71
Slide 71 text
“Make fine grained
interfaces that are client
specific”
- Uncle Bob
Slide 72
Slide 72 text
“Clients should depend
on as narrow protocol as
possible”
- Jim Weirich
Slide 73
Slide 73 text
Active Model
User.model_name
user.persisted?
user.valid?
user.errors
user.to_key
user.to_param
Slide 74
Slide 74 text
How do we ensure
a narrow protocol?
Slide 75
Slide 75 text
class MyPost < ActiveRecord::Base
end
my_post = MyPost.new
assert_equal "my_posts/1", url_for(my_post)