Skip to content

Instantly share code, notes, and snippets.

@sebthemonster
Created May 22, 2012 14:22
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 sebthemonster/2769377 to your computer and use it in GitHub Desktop.
Save sebthemonster/2769377 to your computer and use it in GitHub Desktop.
A Module to decoupling persistence from business model
module Persistence
module Mapper
extend ActiveSupport::Concern
included do
extend ActiveModel::Naming
include ActiveModel::Conversion
end
module ClassMethods
def find(id)
new.tap do |model|
model.persistence = persistence_class.find(id)
end
end
def method_missing(meth, *args, &blk)
persistence_class.send meth, *args, &blk
end
def persistence_class
@persistence_class ||= ("Persistence::#{name}".constantize rescue nil)
end
private
def persistence_class=(klass)
@persistence_class = (klass.is_a?(String) ? klass.constantize : klass)
@persistence_class
end
end
attr_accessor :persistence
def initialize(obj = nil)
raise "a persistence class is needed. Create one Persistence::#{self.to_model} or specify it with persistence_class= method." if self.class.persistence_class.nil?
if obj.is_a? self.class.persistence_class
@persistence = obj
else
@persistence = self.class.persistence_class.new obj
end
super
end
def create attrs
attrs.each do |k,v|
self.public_send "#{k}=", v
end
self.save!
end
def method_missing(meth, *args)
unless @persistence
@persistence = self.class.persistence_class.new
end
@persistence.send(meth, *args)
end
end
#module Base
# include ActiveSupport::Concern
# def to_model(klass)
# klass
# end
#end
end
require "spec_helper"
require_relative '../../lib/persistence_mapper'
describe Persistence::Mapper do
class Persistence::Model; end
subject do
class Model
include Persistence::Mapper
end
Model
end
let(:persistence_class) { stub(:persistence).as_null_object }
context "ClassMethods" do
context '#persistence_class' do
it "should set automatically persistence to a Persistence class by default" do
subject.persistence_class.should == Persistence::Model
end
it "should set automatically persistence to nil if Persistence Class doesn't exist" do
class MyClass; include Persistence::Mapper; end
MyClass.persistence_class.should be_nil
end
end
context "#method_missing" do
it "should delegate chain methods to persistence" do
subject.send( :persistence_class=, persistence_class)
persistence_class.should_receive(:unknown_method)
subject.unknown_method
end
end
end
context 'InstanceMethods' do
let(:object) { subject.new }
let(:persistence) { stub(:persistence).as_null_object }
before {
subject.stub(:persistence_class).and_return(Persistence::Model)
}
it "should raise an error if has no persistence_class" do
subject.stub(:persistence_class).and_return(nil)
expect { subject.new }.should raise_error
end
it "should initialize with a new persistence object" do
Persistence::Model.should_receive(:new)
subject.new
end
it "should delegate methods to persistence object" do
Persistence::Model.stub(:new).and_return(persistence)
persistence.should_receive(:unknown_method)
object.unknown_method
end
end
end
#models/article.rb :
require 'persistence_mapper'
require_relative '../persistence/lotissement'
class Article
include Persistence::Mapper
end
#persistence/article.rb :
module Persistence
class Article < ActiveRecord::Base
belongs_to :author
validates_presence_of :title
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment