Skip to content

Commit

Permalink
all specs pass - updated README and macros now with namespace and mon…
Browse files Browse the repository at this point in the history
…goid support
  • Loading branch information
kristianmandrup committed Aug 14, 2012
1 parent ab9b13c commit c822464
Show file tree
Hide file tree
Showing 10 changed files with 206 additions and 36 deletions.
33 changes: 32 additions & 1 deletion README.md
Expand Up @@ -6,7 +6,7 @@ The current integrations are for:

* [mongoid](https://github.com/mongoid/mongoid)

The gem is designed to simplify designing commands for REST actions and also includes some useful macros.
The gem is designed to simplify designing commands for REST actions and includes some useful macros to facilitate common patterns.

## Mongoid imperator

Expand Down Expand Up @@ -167,6 +167,37 @@ module ServicesController
end
```

Often you will want commands namespace scoped however. This is supported via the `:ns` option.

```ruby
module ServicesController

class SignIn < Action
include Imperator::Command::MethodFactory

def run
sign_in.perform
end

command_method :sign_in, ns: self.parent
end
end
```

Creates a `#sign_in_command` with namespaced scoping:

```ruby
module ServicesController
class SignIn < Action
def sign_in_command
@sign_in_command ||= Services::SignInCommand.new initiator: self
end
end
end
```

This is the recommended pattern for linking Focused Controller actions to Imperator commands.

## Rest Commands

The class `Imperator::Command::Rest` can be used as a base class for REST CUD commands (Create, Update, Delete). This class includes the module `Imperator::Command::RestHelper` which includes a number of useful methods for defining typical REST action behavior for an Imperator Command.
Expand Down
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
0.1.1
0.2.0
37 changes: 25 additions & 12 deletions lib/imperator/command/class_factory.rb
Expand Up @@ -14,7 +14,7 @@ def default_parent clazz
end

def get_default_parent
@default_default_parent ||= ::Imperator::Command
@default_parent ||= ::Imperator::Command
end

# Usage:
Expand All @@ -27,12 +27,17 @@ def build_command action, model, options = {}, &block
clazz = parent ? Class.new(parent) : Class.new
Object.const_set clazz_name, clazz
clazz = self.const_get(clazz_name)
clazz.class_eval do
attributes_for(model, :except => options[:except]) if options[:auto_attributes]
if options[:auto_attributes]
clazz.instance_eval do
if respond_to? :attributes_for
attributes_for(model, :except => options[:except], :only => options[:only])
end
end
end
if block_given?
clazz.class_eval &block
clazz.instance_eval &block
end
clazz
end

# Usage:
Expand All @@ -41,7 +46,7 @@ def build_command action, model, options = {}, &block
# end
def rest_command action, model, options = {}, &block
options.reverse_merge! default_options
options[:parent] ||= default_rest_class
options[:parent] ||= get_default_rest_class(model)
rest_commands_for(model, options, &block) and return if action.to_sym == :all
if rest_actions.include? action.to_sym
action_name = "#{action}_command_for"
Expand All @@ -53,10 +58,18 @@ def rest_command action, model, options = {}, &block

attr_writer :default_rest_class

def get_default_rest_class model
model.ancestors.include?(Mongoid::Document) ? default_mongoid_rest_class : default_rest_class
end

def default_rest_class
@default_rest_class ||= Imperator::Command::Rest
end

def default_mongoid_rest_class
@default_mongoid_rest_class ||= Imperator::Mongoid::Command::Rest
end

def reset_rest_class
@default_rest_class = Imperator::Command::Rest
end
Expand All @@ -76,26 +89,26 @@ def rest_actions

def create_command_for model, options = {}, &block
options[:parent] ||= default_rest_class
build_command :create, model, options do
c = build_command :create, model, options do
create_action
instance_eval &block if block_given?
end
c.class_eval &block if block_given?
end

def update_command_for model, options = {}, &block
options[:parent] ||= default_rest_class
build_command :update, model, options do
update_action
instance_eval &block if block_given?
c = build_command :update, model, options do
update_action
end
c.class_eval &block if block_given?
end

def delete_command_for model, options = {}, &block
options[:parent] ||= default_rest_class
build_command :delete, model, options do
c = build_command :delete, model, options do
delete_action
instance_eval &block if block_given?
end
c.class_eval &block if block_given?
end

def rest_commands_for model, options = {}, &block
Expand Down
6 changes: 4 additions & 2 deletions lib/imperator/command/method_factory.rb
@@ -1,10 +1,12 @@
class Imperator::Command
module MethodFactory
def command_method command, options = {}
namespace = (options[:ns] || '').to_s
namespace.sub! /Controller$/, ''
define_method "#{command}_command" do
instance_var = "@#{command}_command"
unless instance_variable_get(instance_var)
clazz = "#{command.to_s.camelize}Command".constantize
unless instance_variable_get(instance_var)
clazz = [namespace, "#{command.to_s.camelize}Command"].join('::').constantize
instance_variable_set instance_var, clazz.new(options.merge initiator: self)
end
end
Expand Down
80 changes: 67 additions & 13 deletions spec/imperator-ext/command/class_factory_spec.rb
Expand Up @@ -2,6 +2,10 @@

class UpdateRestCommand < Imperator::Command::Rest
end
class CreateRestCommand < Imperator::Command::Rest
end
class DeleteRestCommand < Imperator::Command::Rest
end

class Post
end
Expand All @@ -18,9 +22,68 @@ class User
class Foo
end

class UpdatePostCommand < Imperator::Command::Rest
class Payment
end

describe Imperator::Command::ClassFactory do
subject { Imperator::Command::ClassFactory }

describe '.rest_command' do
context 'update' do
before :all do
subject.default_rest_class = Imperator::Command::Rest
subject.rest_command :update, Article, :parent => UpdateRestCommand, :auto_attributes => true do
def hello
"hello"
end
end
end

context 'UpdateArticleCommand created' do
let(:command) { UpdateArticleCommand.new }

specify { UpdateArticleCommand.superclass.should == UpdateRestCommand }
specify { command.hello.should == "hello" }
end
end

context 'create' do
before :all do
subject.default_rest_class = Imperator::Command::Rest
subject.rest_command :create, Article, :parent => CreateRestCommand, :auto_attributes => true do
def hello
"hello"
end
end
end

context 'CreateArticleCommand created' do
let(:command) { CreateArticleCommand.new }

specify { CreateArticleCommand.superclass.should == CreateRestCommand }
specify { command.hello.should == "hello" }
end
end

context 'delete' do
before :all do
subject.default_rest_class = Imperator::Command::Rest
subject.rest_command :delete, Article, :parent => DeleteRestCommand, :auto_attributes => true do
def hello
"hello"
end
end
end

context 'DeleteArticleCommand created' do
let(:command) { DeleteArticleCommand.new }

specify { DeleteArticleCommand.superclass.should == DeleteRestCommand }
specify { command.hello.should == "hello" }
end
end
end
end

describe Imperator::Command::ClassFactory do

Expand All @@ -37,10 +100,10 @@ class UpdatePostCommand < Imperator::Command::Rest

describe '.rest_command' do
before :all do
subject.rest_command :update, Post
subject.rest_command :update, Payment
end

specify { UpdatePostCommand.superclass.should == Imperator::Command::Rest }
specify { UpdatePaymentCommand.superclass.should == Imperator::Command::Rest }

describe ':all' do
before :all do
Expand All @@ -63,16 +126,7 @@ class UpdatePostCommand < Imperator::Command::Rest
subject.default_rest_class = UpdateRestCommand
end

its(:default_rest_class) { should == UpdateRestCommand }

describe '.rest_command' do
before :all do
subject.default_rest_class = UpdateRestCommand
subject.rest_command :update, Article
end

specify { UpdateArticleCommand.superclass.should == UpdateRestCommand }
end
its(:default_rest_class) { should == UpdateRestCommand }
end
end

Expand Down
36 changes: 35 additions & 1 deletion spec/imperator-ext/command/method_factory_spec.rb
Expand Up @@ -7,6 +7,26 @@ class Commander
class UpdateCommand < Imperator::Command
end

module Landlord
module Account
class PayCommand < Imperator::Command
end
end
end

module Landlord
module AccountController
class Action # imperator action
end

class Pay < Action # imperator action
extend Imperator::Command::MethodFactory

command_method :pay, object: 'hello', ns: self.parent
end
end
end

describe Imperator::Command::MethodFactory do
subject { clazz.new }

Expand All @@ -22,9 +42,23 @@ class UpdateCommand < Imperator::Command

describe '.command_method(command, options)' do
before do
clazz.command_method :update, object: 'hello'
clazz.command_method :create, object: 'hello'
end

its(:update_command) { should be_a(Imperator::Command) }
end

describe 'with namespace :ns option' do
before do
clazz.command_method :pay, object: 'hello', ns: Landlord::Account
end

specify { subject.pay_command.class.to_s.should == 'Landlord::Account::PayCommand' }
end

describe 'with namespace :ns option as self.parent' do
subject { Landlord::AccountController::Pay }

specify { subject.new.pay_command.class.to_s.should == 'Landlord::Account::PayCommand' }
end
end
1 change: 1 addition & 0 deletions spec/imperator-ext/command/rest_helper_spec.rb
Expand Up @@ -2,5 +2,6 @@
require 'imperator-ext/shared_ex/rest_helper_ex'

describe Imperator::Command::RestHelper do

it_behaves_like "a rest helper"
end
5 changes: 2 additions & 3 deletions spec/imperator-ext/mongoid/command_spec.rb
Expand Up @@ -5,7 +5,6 @@
subject { clazz }
let(:clazz) { Imperator::Mongoid::Command }

it_behaves_like "an attribute helper"


it_behaves_like 'an attribute helper'
it_behaves_like 'a mongoid rest command'
end
29 changes: 26 additions & 3 deletions spec/imperator-ext/shared_ex/attribute_helper_ex.rb
@@ -1,3 +1,5 @@
# require 'imperator/command/macros'

class Person
include Mongoid::Document

Expand All @@ -14,18 +16,39 @@ class ShowPersonCommand < Imperator::Mongoid::Command
attributes_for Person, except: :age
end

shared_examples 'a mongoid rest command' do
context 'update' do
before :all do
Imperator::Command::ClassFactory.use do |factory|
# factory.default_rest_class = Imperator::Mongoid::Command::Rest
factory.rest_command :create, Person, :auto_attributes => true do
def hello
"hello"
end
end
end
end

context 'CreatePersonCommand created' do
let(:command) { CreatePersonCommand.new }

specify { CreatePersonCommand.superclass.should == Imperator::Mongoid::Command::Rest }
specify { command.hello.should == "hello" }
end
end
end

shared_examples "an attribute helper" do
describe 'includes all Mongoid model fields' do
subject { UpdatePersonCommand.attribute_set }

its(:sym_names) { should include(:name, :title, :age) }
its(:names) { should include :name, :title, :age }
end

describe 'includes all Mongoid model fields :except age' do
subject { ShowPersonCommand.attribute_set }

its(:sym_names) { should include(:name, :title) }
its(:sym_names) { should_not include(:age) }
its(:names) { should include :name, :title }
its(:names) { should_not include :age }
end
end

0 comments on commit c822464

Please sign in to comment.