Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
moonmaster9000 committed Aug 1, 2012
1 parent e9a08f4 commit f163ed1
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 4 deletions.
65 changes: 65 additions & 0 deletions ar.rb
Original file line number Original file line Diff line number Diff line change
@@ -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

Binary file added db/test.db
Binary file not shown.
63 changes: 63 additions & 0 deletions lib/frill/active_record/association_decorator.rb
Original file line number Original file line Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions lib/frill/active_record/association_proxy.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,9 @@
module Frill
module ActiveRecord
class CollectionProxy
def initialize(collection, context)
end
end
end
end

8 changes: 4 additions & 4 deletions lib/frill/frill.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ def self.reset!
end end


def self.decorate object, context def self.decorate object, context
decorators.each do |d| decorators.each do |d|
object.extend d if d.frill? object, context object.extend d if d.frill? object, context
end end


object object
end end


module ClassMethods module ClassMethods
Expand Down
113 changes: 113 additions & 0 deletions spec/frill_active_relation_spec.rb
Original file line number Original file line Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions spec/lib/frill/active_record/association_proxy_spec.rb
Original file line number Original file line Diff line number Diff line change
@@ -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.