Permalink
Browse files

WIP

  • Loading branch information...
1 parent e9a08f4 commit f163ed1b4b644600152fa9047c6d318927381ca9 @moonmaster9000 committed Aug 1, 2012
View
65 ar.rb
@@ -0,0 +1,65 @@
+require 'active_record'
+require 'sqlite3'
+
+ActiveRecord::Base.establish_connection(
+ adapter: 'sqlite3',
+ database: 'db/test.db'
+)
+
+%w(posts blogs comments).each do |table|
+ ActiveRecord::Base.connection.execute(
+ %(
+ DROP TABLE
+ IF EXISTS
+ #{table}
+ )
+ )
+end
+
+ActiveRecord::Base.connection.execute(
+ %(
+ CREATE TABLE
+ posts(
+ id INTEGER,
+ blog_id INTEGER,
+ PRIMARY KEY(id ASC)
+ )
+ )
+)
+
+ActiveRecord::Base.connection.execute(
+ %(
+ CREATE TABLE
+ blogs(
+ id INTEGER,
+ name VARCHAR,
+ PRIMARY KEY(id ASC)
+ )
+ )
+)
+
+ActiveRecord::Base.connection.execute(
+ %(
+ CREATE TABLE
+ comments(
+ id INTEGER,
+ post_id INTEGER,
+ PRIMARY KEY(id ASC)
+ )
+ )
+)
+
+
+class Post < ActiveRecord::Base
+ belongs_to :blog
+ has_many :comments
+end
+
+class Blog < ActiveRecord::Base
+ has_many :posts
+end
+
+class Comment < ActiveRecord::Base
+ belongs_to :post
+end
+
View
Binary file not shown.
@@ -0,0 +1,63 @@
+module Frill
+ module ActiveRecord
+ class AssociationDecorator
+ def self.decorate(object, context)
+ new(object, context).decorate
+ end
+
+ def initialize(object, context)
+ @object = object
+ @context = context
+ end
+
+ def decorate
+ embed_context_in_object
+ decorate_associations
+ end
+
+ private
+ def embed_context_in_object
+ frill_context = @context
+
+ object.extend(
+ Module.new do
+ private
+ define_method(:__frill_context) do
+ frill_context
+ end
+ end
+ )
+ end
+
+ def decorate_associations
+ object.class.reflect_on_all_associations.each do |association|
+ if association.collection?
+ object.extend(
+ Module.new.tap do |mod|
+ mod.class_eval <<-EVAL
+ def #{association.name}
+ Frill::ActiveRecord::CollectionProxy.new(super, __frill_context)
+ end
+ EVAL
+ end
+ )
+ else
+ object.extend(
+ Module.new.tap do |mod|
+ mod.class_eval <<-EVAL
+ def #{association.name}
+ association = super
+ return nil unless association
+ Frill.decorate association, __frill_context
+ end
+ EVAL
+ end
+ )
+ end
+ end
+ end
+
+ attr_reader :object, :context
+ end
+ end
+end
@@ -0,0 +1,9 @@
+module Frill
+ module ActiveRecord
+ class CollectionProxy
+ def initialize(collection, context)
+ end
+ end
+ end
+end
+
View
@@ -13,11 +13,11 @@ def self.reset!
end
def self.decorate object, context
- decorators.each do |d|
- object.extend d if d.frill? object, context
- end
+ decorators.each do |d|
+ object.extend d if d.frill? object, context
+ end
- object
+ object
end
module ClassMethods
@@ -0,0 +1,113 @@
+require 'active_record'
+require 'sqlite3'
+
+ActiveRecord::Base.establish_connection(
+ adapter: 'sqlite3',
+ database: 'db/test.db'
+)
+
+%w(posts blogs comments).each do |table|
+ ActiveRecord::Base.connection.execute(
+ %(
+ DROP TABLE
+ IF EXISTS
+ #{table}
+ )
+ )
+end
+
+ActiveRecord::Base.connection.execute(
+ %(
+ CREATE TABLE
+ posts(
+ id INTEGER,
+ blog_id INTEGER,
+ PRIMARY KEY(id ASC)
+ )
+ )
+)
+
+ActiveRecord::Base.connection.execute(
+ %(
+ CREATE TABLE
+ blogs(
+ id INTEGER,
+ name VARCHAR,
+ PRIMARY KEY(id ASC)
+ )
+ )
+)
+
+ActiveRecord::Base.connection.execute(
+ %(
+ CREATE TABLE
+ comments(
+ id INTEGER,
+ post_id INTEGER,
+ PRIMARY KEY(id ASC)
+ )
+ )
+)
+
+require_relative '../lib/frill/active_record/association_decorator'
+
+class Post < ActiveRecord::Base
+ belongs_to :blog
+ has_many :comments
+end
+
+class Blog < ActiveRecord::Base
+ has_many :posts
+end
+
+class Comment < ActiveRecord::Base
+ belongs_to :post
+end
+
+describe Frill::ActiveRecord::AssociationDecorator do
+ before { Post.destroy_all; Blog.destroy_all; Comment.destroy_all }
+ before { Frill.reset! }
+
+ let!(:post) do
+ Post.create.tap do |p|
+ p.blog = Blog.create
+ p.save
+ end
+ end
+
+ let!(:decorated_module) do
+ Module.new do
+ include Frill
+
+ def self.frill?(*)
+ true
+ end
+ end
+ end
+
+ describe ".decorate(object, context)" do
+ context "given an ActiveRecord object" do
+ it "should decorate associated objects" do
+ Frill::ActiveRecord::AssociationDecorator.decorate post, double(:context)
+ blog_eigenclass = class << post.blog; self; end
+ blog_eigenclass.included_modules.should include decorated_module
+ end
+
+ it "should not attempt to decorate nil associations" do
+ comment = Comment.create
+ Frill::ActiveRecord::AssociationDecorator.decorate comment, double(:context)
+ post_eigenclass = class << comment.post; self; end
+ post_eigenclass.included_modules.should_not include decorated_module
+ end
+
+ it "should lazily decorate collection associations" do
+ post.comments << Comment.create << Comment.create
+ Frill::ActiveRecord::AssociationDecorator.decorate post, double(:context)
+ comments = post.comments
+ comment = comments.first
+ comment_eigenclass = class << comment; self; end
+ comment_eigenclass.included_modules.should include decorated_module
+ end
+ end
+ end
+end
@@ -0,0 +1,9 @@
+require_relative '../../../../lib/frill/active_record/association_proxy'
+
+module Frill
+ module ActiveRecord
+ describe CollectionProxy do
+
+ end
+ end
+end

0 comments on commit f163ed1

Please sign in to comment.