Permalink
Browse files

Initial version

  • Loading branch information...
0 parents commit ad0e9c3e9223723bf1494ca8ac7ddbc6d3e07d8c @jackc committed Apr 14, 2012
Showing with 246 additions and 0 deletions.
  1. +17 −0 .gitignore
  2. +1 −0 .rspec
  3. +4 −0 Gemfile
  4. +9 −0 Guardfile
  5. +22 −0 LICENSE
  6. +32 −0 README.md
  7. +2 −0 Rakefile
  8. +23 −0 command_model.gemspec
  9. +7 −0 lib/command_model.rb
  10. +39 −0 lib/command_model/model.rb
  11. +3 −0 lib/command_model/version.rb
  12. +85 −0 spec/model_spec.rb
  13. +2 −0 spec/spec_helper.rb
17 .gitignore
@@ -0,0 +1,17 @@
+*.gem
+*.rbc
+.bundle
+.config
+.yardoc
+Gemfile.lock
+InstalledFiles
+_yardoc
+coverage
+doc/
+lib/bundler/man
+pkg
+rdoc
+spec/reports
+test/tmp
+test/version_tmp
+tmp
1 .rspec
@@ -0,0 +1 @@
+--colour
4 Gemfile
@@ -0,0 +1,4 @@
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in command_model.gemspec
+gemspec
9 Guardfile
@@ -0,0 +1,9 @@
+# A sample Guardfile
+# More info at https://github.com/guard/guard#readme
+
+guard 'rspec', :version => 2 do
+ watch(%r{^spec/.+_spec\.rb$})
+ watch(%r{^lib/command_model/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
+ watch('spec/spec_helper.rb') { "spec" }
+end
+
22 LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2012 Jack Christensen
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 README.md
@@ -0,0 +1,32 @@
+# CommandModel
+
+CommandModel is a model implementation using ActiveModel to represent commands
+and the results of their execution.
+
+## Installation
+
+Add this line to your application's Gemfile:
+
+ gem 'command_model'
+
+And then execute:
+
+ $ bundle
+
+Or install it yourself as:
+
+ $ gem install command_model
+
+## Usage
+
+TODO: Write usage instructions here
+
+Example(s) User#change_login
+
+## Contributing
+
+1. Fork it
+2. Create your feature branch (`git checkout -b my-new-feature`)
+3. Commit your changes (`git commit -am 'Added some feature'`)
+4. Push to the branch (`git push origin my-new-feature`)
+5. Create new Pull Request
2 Rakefile
@@ -0,0 +1,2 @@
+#!/usr/bin/env rake
+require "bundler/gem_tasks"
23 command_model.gemspec
@@ -0,0 +1,23 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../lib/command_model/version', __FILE__)
+
+Gem::Specification.new do |gem|
+ gem.authors = ["Jack Christensen"]
+ gem.email = ["jack@jackchristensen.com"]
+ gem.description = %q{CommandModel integrates Rails validations with command objects}
+ gem.summary = %q{CommandModel integrates Rails validations with command objects. This allows errors from command execution to easily be handled with the familiar Rails validation system.}
+ gem.homepage = "https://github.com/JackC/command_model"
+
+ gem.files = `git ls-files`.split($\)
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
+ gem.name = "command_model"
+ gem.require_paths = ["lib"]
+ gem.version = CommandModel::VERSION
+
+ gem.add_dependency 'activemodel', "~> 3.2"
+
+ gem.add_development_dependency 'rspec', "~> 2.9.0"
+ gem.add_development_dependency 'guard', "~> 1.0.0"
+ gem.add_development_dependency 'guard-rspec', "~> 0.7.0"
+end
7 lib/command_model.rb
@@ -0,0 +1,7 @@
+require "active_model"
+
+require "command_model/version"
+require "command_model/model"
+
+module CommandModel
+end
39 lib/command_model/model.rb
@@ -0,0 +1,39 @@
+module CommandModel
+ class Model
+ include ActiveModel::Validations
+
+ def self.execute(attributes_or_command)
+ command = if attributes_or_command.kind_of? self
+ attributes_or_command
+ else
+ new(attributes_or_command)
+ end
+
+ yield command if command.valid?
+ command.execution_attempted!
+ command
+ end
+
+ def initialize(attributes={})
+ attributes.each do |k,v|
+ send "#{k}=", v
+ end
+ end
+
+ # Record that an attempt was made to execute this command whether or not
+ # it was successful.
+ def execution_attempted!
+ @execution_attempted = true
+ end
+
+ # True if execution has been attempted on this command
+ def execution_attempted?
+ @execution_attempted
+ end
+
+ # Command has been executed without errors
+ def success?
+ execution_attempted? && errors.empty?
+ end
+ end
+end
3 lib/command_model/version.rb
@@ -0,0 +1,3 @@
+module CommandModel
+ VERSION = "0.0.1"
+end
85 spec/model_spec.rb
@@ -0,0 +1,85 @@
+require 'spec_helper'
+
+class ExampleCommand < CommandModel::Model
+ attr_accessor :name
+
+ validates_presence_of :name
+end
+
+describe CommandModel::Model do
+ let(:example_command) { ExampleCommand.new :name => "John" }
+ let(:invalid_example_command) { ExampleCommand.new }
+
+ describe "self.execute" do
+ it "accepts object of same kind and returns it" do
+ ExampleCommand.execute(example_command) {}.should eq(example_command)
+ end
+
+ it "accepts attributes, creates object, and returns it" do
+ c = ExampleCommand.execute(:name => "John") {}
+ c.should be_kind_of(ExampleCommand)
+ c.name.should eq("John")
+ end
+
+ it "calls passed block when there are no validation errors on Model" do
+ block_ran = false
+ ExampleCommand.execute(example_command) { block_ran = true }
+ block_ran.should eq(true)
+ end
+
+ it "does not call passed block when there are validation errors on Model" do
+ block_ran = false
+ ExampleCommand.execute(invalid_example_command) { block_ran = true }
+ block_ran.should eq(false)
+ end
+
+ it "records execution attempt when there not no validation errors on Model" do
+ ExampleCommand.execute(example_command) {}
+ example_command.execution_attempted?.should eq(true)
+ end
+
+ it "records execution attempt when there are validation errors on Model" do
+ ExampleCommand.execute(invalid_example_command) {}
+ invalid_example_command.execution_attempted?.should eq(true)
+ end
+
+ it "is not successful if block adds error to Model" do
+ ExampleCommand.execute(example_command) do |command|
+ command.errors.add :base, "foo"
+ end
+
+ example_command.should_not be_success
+ end
+ end
+
+ describe "initialize" do
+ it "assigns attributes" do
+ m = ExampleCommand.new :name => "John"
+ m.name.should eq("John")
+ end
+ end
+
+ describe "execution_attempted!" do
+ it "sets execution_attempted? to true" do
+ example_command.execution_attempted!
+ example_command.execution_attempted?.should eq(true)
+ end
+ end
+
+ describe "success?" do
+ it "is false before execution" do
+ example_command.should_not be_success
+ end
+
+ it "is false after execution with errors" do
+ example_command.execution_attempted!
+ example_command.errors.add :base, "foo"
+ example_command.success?.should eq(false)
+ end
+
+ it "is true after execution without errors" do
+ example_command.execution_attempted!
+ example_command.success?.should eq(true)
+ end
+ end
+end
2 spec/spec_helper.rb
@@ -0,0 +1,2 @@
+require 'command_model'
+require 'rspec'

0 comments on commit ad0e9c3

Please sign in to comment.