Contextualize
Adds the ability to add and remove specific modules to an object depending on the current context This can fx be used for Models in a MVC pattern, where the model could have different behavior depending on the context it operates in, fx if is currently accessed in a View or a Controller, or even depending on the scope (fx Admin) etc.
This way, a lot of the typical scenarios for helper methods can be avoided. Instead you simply create an ‘app/contexts’ folder for modules that define contextual behavior for the models. You can further subdivision these contexts as needed. This can even be used to redefine the logic of a method depending on the context it operates in.
The Decorator Pattern with Mixology has been used to great effect.
Basic Usage
Define each context specific module
module ProjectView
# display the best project
def show_best
# calls method :best
end
end
module ProjectControl
# select the best project
def best
end
end
module Admin
module ProjectControl
# admin specific logic to select the best project!
def best
end
end
end
# Only in order to faciliatet demonstrating results below!
class Object
def own_methods
methods - Object.methods
end
end
Then bind these modules to one or more contexts
class Project
contextualize
contexts :view, :control # using naming conventions
context :admin, Admin::ProjectControl
end
Now you can operate on the object according to the context you are in
project = Project.new
# add :view context
project.add_context :view
project.add_contexts :view, :control
# use the view context methods now available
project.own_methods.should include('view')
project.view.should == "view"
# remove the :view context
project.remove_context :view
project.remove_contexts :view, :control
# the methods of the view context are no longer available!
lambda {project.view}.should raise_error
# operate on object within one or more contexts
project.context_scope :view do |project|
project.view.should == "view"
end
# contexts are automatically removed from object when block terminates
lambda {project.view}.should raise_error
project.context_scope :view, :control do |project|
# ...
end
Usage in Rails
in Gemfile
gem 'contextualize'
In a Rails project, you should use the following file structure
+ app
+ contexts
project_view.rb
project_control.rb
+ admin
project_view.rb
+ models
project.rb
class ProjectsController < ApplicationController
# "simulated" exposure
def project
@project ||= begin
p = params[:id] ? Project.find(params[:id]) : Project.new(params[:project])
p.add_icontext :view
end
end
helper_method project
hide_action project
def projects
@projects ||= Project.all.add_icontext :view
end
helper_method projects
hide_action projects
def index
end
def show
end
...
end
Using decent_exposure integration
Contextualize monkey-patches the #expose method of the decent_exposure gem to add the icontext :view to each model (if present)
in Gemfile
gem 'decent_exposure'
gem 'contextualize'
class ProjectsController < ApplicationController
expose(:projects) { Project.all }
expose(:project)
def index
end
def show
end
def new
end
def edit
end
def create
if project.save
redirect_to project, notice: 'Project was successfully created.'
else
render action: "new"
end
end
def update
if project.update_attributes(params[:project])
redirect_to project, notice: 'Project was successfully updated.'
else
render action: "edit"
end
end
def destroy
project.destroy
redirect_to projects_url
end
end
Enjoy!
Contributing to contextualize
- Check out the latest master to make sure the feature hasn’t been implemented or the bug hasn’t been fixed yet
- Check out the issue tracker to make sure someone already hasn’t requested it and/or contributed it
- Fork the project
- Start a feature/bugfix branch
- Commit and push until you are happy with your contribution
- Make sure to add tests for it. This is important so I don’t break it in a future version unintentionally.
- Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
Copyright
Copyright © 2011 Kristian Mandrup. See LICENSE.txt for further details.