Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial commit

  • Loading branch information...
commit afa318ee6c93a0e716e3921bcf1c1166325855b8 0 parents
@svenfuchs authored
54 README.textile
@@ -0,0 +1,54 @@
+h1. Vertical code slices based on ActiveSupport Dependencies
+
+ActiveSupport::Slices allows to lazily autoload "slices" (or extensions) of Ruby files.
+
+E.g. whenever the application requires the file @foo/bar/user.rb@ through ActiveSupport::Dependencies then it will load all files @foo/bar/user_slice.rb@ that are placed anywhere in the @autoload_paths@.
+
+h2. Installation
+
+To hook up ActiveSupport::Slices just include the gem and @require 'active_support/slices'@.
+
+h2. Usage
+
+Given the following files:
+
+<pre>
+engine-1/app/models/user_slice.rb
+engine-2/app/models/user.rb
+engine-3/app/models/user_slice.rb
+</pre>
+
+If the application requires "user.rb" either through
+
+1. using the (not yet defined) @User@ constant directly or
+2. using @require_dependency 'user'@
+
+... then ActiveSupport::Dependencies will load @engine-2/app/models/user.rb@ first and ActiveSupport::Slices will load both @engine-1/app/models/user_slice.rb@ and @engine-2/app/models/user_slice.rb@ second.
+
+h2. Rational
+
+The Rails < 2.3 engines plugin defined the term "engine" as a "full vertical application slice". When Rails 2.3 included engines it went a few steps back and only implemented most of the core features, making an "engine" rather a "pimped plugin". Today in Rails 3 we have engines that are *way* more powerful and flexible than what we had before - in short they're just "done right" now.
+
+If you want to use Rails 3 engines to build full application slices there still is a single, crucial feature missing: the ability to mix first-class-citizen code slices from various engines automatically without having one engine know too much about other engines.
+
+For example:
+
+Let's say we have a bunch of engines that contribute small applications (say, a blog and a ticket tracker) and only share a few things, maybe a User model. So, we'd have engines like: user, blog, tickets. Obviously users have many blog posts and many tickets.
+
+Now, when the blog engine is installed the User.should have_many(:posts). When the tickets engine is installed the User.should have_many(:tickets). But obviously this needs to be defined in the blog and tickets engines, not in the user engine where the User class is defined.
+
+So, the blog and tickets engines somehow need to reopen the User class and add that association:
+
+<pre>
+# somewhere in the blog engine
+User.has_many :posts
+
+# somewhere in the tickets engine
+User.has_many :tickets
+</pre>
+
+Ideally we want these code bits to be placed in the app/models directories because that's the place where people look for model code. And we want these bits to be lazy loaded whenever the application loads the User model.
+
+Also see "this discussion":https://gist.github.com/b7733d5fea89d2dd37ca
+
+
10 Rakefile
@@ -0,0 +1,10 @@
+require 'rake'
+require 'rake/testtask'
+
+Rake::TestTask.new do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = false
+end
+
+task :default => :test
17 activesupport-slices.gemspec
@@ -0,0 +1,17 @@
+$:.unshift File.expand_path('../lib', __FILE__)
+require 'active_support/slices/version'
+
+Gem::Specification.new do |s|
+ s.name = "activesupport-slices"
+ s.version = ActiveSupport::Slices::VERSION
+ s.authors = ["Sven Fuchs"]
+ s.email = "svenfuchs@artweb-design.de"
+ s.homepage = "http://github.com/svenfuchs/activesupport-slices"
+ s.summary = "Lazy loaded vertical code slices based on ActiveSupport Dependencies"
+ s.description = "Lazy loaded vertical code slices based on ActiveSupport Dependencies."
+
+ s.files = Dir.glob("lib/**/**")
+ s.platform = Gem::Platform::RUBY
+ s.require_path = 'lib'
+ s.rubyforge_project = '[none]'
+end
39 lib/active_support/slices.rb
@@ -0,0 +1,39 @@
+require 'active_support'
+require 'active_support/slices/dependencies'
+require 'active_support/slices/rails' if defined?(Rails)
+
+module ActiveSupport
+ module Slices
+ mattr_accessor :slices
+ self.slices = {}
+
+ def paths
+ Dependencies.autoload_paths
+ end
+
+ def load(filename)
+ filename = local(filename)
+ if slices.key?(filename)
+ slices[filename].each { |slice| Dependencies.load(slice) }
+ end
+ end
+
+ def register
+ Dir["{#{paths.join(',')}}/**/*_slice*.rb"].each do |path|
+ filename = local(path).sub('_slice', '')
+ slices[filename] ||= []
+ slices[filename] << path
+ end
+ end
+
+ def local(path)
+ path.sub(pattern, '')
+ end
+
+ def pattern
+ @pattern || %r((#{paths.join('|')})/)
+ end
+
+ extend self
+ end
+end
12 lib/active_support/slices/dependencies.rb
@@ -0,0 +1,12 @@
+require 'active_support/dependencies'
+
+module ActiveSupport
+ module Dependencies
+ def require_or_load_with_slices(*args)
+ require_or_load_without_slices(*args).tap do |result|
+ Slices.load(args.first) if result
+ end
+ end
+ alias_method_chain :require_or_load, :slices
+ end
+end
7 lib/active_support/slices/rails.rb
@@ -0,0 +1,7 @@
+module Slices
+ class Railtie < Rails::Railtie
+ initializer 'activesupport.slices.register' do |app|
+ ActiveSupport::Slices.register
+ end
+ end
+end
5 lib/active_support/slices/version.rb
@@ -0,0 +1,5 @@
+module ActiveSupport
+ module Slices
+ VERSION = "0.0.1"
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.