Skip to content

Instantly share code, notes, and snippets.

@sklppr
Last active May 16, 2019 20:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sklppr/e0f6d89cdb97cb1e5382cadc64b17d4f to your computer and use it in GitHub Desktop.
Save sklppr/e0f6d89cdb97cb1e5382cadc64b17d4f to your computer and use it in GitHub Desktop.
Separating model from ActiveRecord with delegation/decorator pattern.
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
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