h1. 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”:ruby.simapse.com/2008/08/test.html has been used to great effect.

h2. Basic Usage

Define each context specific module

<pre> 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 </pre>

Then bind these modules to one or more contexts

<pre> class Project

contextualize
contexts :view, :control # using naming conventions
context :admin, Admin::ProjectControl

end </pre>

Now you can operate on the object according to the context you are in

<pre> 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 </pre>

h2. Usage in Rails

in Gemfile

<pre> gem ‘contextualize’ </pre>

In a Rails project, you should use the following file structure

<pre> + app

+ contexts
    project_view.rb
    project_control.rb
  + admin
      project_view.rb

+ models
  project.rb

</pre>

<pre> 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 </pre>

h2. 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

<pre> gem ‘decent_exposure’ gem ‘contextualize’ </pre>

<pre> 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 </pre>

Enjoy!

h2. Contributing to contextualize

h2. Copyright

Copyright © 2011 Kristian Mandrup. See LICENSE.txt for further details.