Last active
May 16, 2019 20:34
-
-
Save sklppr/e0f6d89cdb97cb1e5382cadc64b17d4f to your computer and use it in GitHub Desktop.
Separating model from ActiveRecord with delegation/decorator pattern.
This file contains hidden or 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
require "forwardable" | |
module ActiveRecord | |
class Base | |
def save | |
puts "SAVED #{name}" | |
end | |
end | |
end | |
class Person | |
attr_reader :name | |
def initialize(name) | |
@name = name | |
end | |
end | |
class PersonRecord < ActiveRecord::Base | |
extend Forwardable | |
def_delegators :@person, :name | |
def initialize(person) | |
@person = person | |
end | |
end | |
p = Person.new("John Doe") | |
pr = PersonRecord.new(p) | |
pr.save |
This file contains hidden or 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
require "forwardable" | |
# fake AR implementation | |
module ActiveRecord | |
class Base | |
def save | |
puts instance_variables.collect { |var| "#{var}: #{instance_variable_get(var)}" } | |
end | |
end | |
end | |
# Generic wrapper for AR records | |
class Record < ActiveRecord::Base | |
def initialize(target) | |
@target = target | |
end | |
attr_reader :target | |
# avoid having to explicitly delegate everything | |
def method_missing(method_name, *args, &block) | |
@target.respond_to?(method_name) ? @target.send(method_name, *args, &block) : super | |
end | |
# bonus: explicit delegation of metaprogramming features | |
extend Forwardable | |
delegate [:instance_variables, :instance_variable_get, :instance_variable_set] => :@target | |
end | |
# model class | |
class Person | |
# may include ActiveModel stuff here | |
attr_reader :name | |
def initialize(name) | |
@name = name | |
end | |
end | |
# record class | |
class PersonRecord < Record | |
# only AR stuff (e.g. relations) | |
end | |
p = Person.new("John Doe") | |
pr = PersonRecord.new(p) | |
pr.save |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment