creators 0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/creators/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "creators"
6
+ s.version = Creators::VERSION
7
+ s.authors = ["Itay Adler", "Shay Davidson", "Yonatan Bergman"]
8
+ s.email = ["itayadler@gmail.com", "shay.h.davidson@gmail.com", "lighthawky@gmail.com"]
9
+ s.homepage = "https://github.com/TheGiftsProject/creators"
10
+ s.summary = %q{Making it even nicer to manage Form data params in your Controller.}
11
+ s.description = %q{Creators are used to host code dealing with creation of new models and clean up the controllers. }
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.require_path = "lib"
15
+ s.test_files = Dir.glob('spec/lib/*_spec.rb')
16
+
17
+
18
+ s.add_dependency 'rails'
19
+ s.add_development_dependency 'rake'
20
+ s.add_development_dependency 'rspec'
21
+ end
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .idea
2
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create use 1.9.2@creators
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,103 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ creators (0.9)
5
+ rails
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ actionmailer (3.2.9)
11
+ actionpack (= 3.2.9)
12
+ mail (~> 2.4.4)
13
+ actionpack (3.2.9)
14
+ activemodel (= 3.2.9)
15
+ activesupport (= 3.2.9)
16
+ builder (~> 3.0.0)
17
+ erubis (~> 2.7.0)
18
+ journey (~> 1.0.4)
19
+ rack (~> 1.4.0)
20
+ rack-cache (~> 1.2)
21
+ rack-test (~> 0.6.1)
22
+ sprockets (~> 2.2.1)
23
+ activemodel (3.2.9)
24
+ activesupport (= 3.2.9)
25
+ builder (~> 3.0.0)
26
+ activerecord (3.2.9)
27
+ activemodel (= 3.2.9)
28
+ activesupport (= 3.2.9)
29
+ arel (~> 3.0.2)
30
+ tzinfo (~> 0.3.29)
31
+ activeresource (3.2.9)
32
+ activemodel (= 3.2.9)
33
+ activesupport (= 3.2.9)
34
+ activesupport (3.2.9)
35
+ i18n (~> 0.6)
36
+ multi_json (~> 1.0)
37
+ arel (3.0.2)
38
+ builder (3.0.4)
39
+ diff-lcs (1.1.3)
40
+ erubis (2.7.0)
41
+ hike (1.2.1)
42
+ i18n (0.6.1)
43
+ journey (1.0.4)
44
+ json (1.7.5)
45
+ mail (2.4.4)
46
+ i18n (>= 0.4.0)
47
+ mime-types (~> 1.16)
48
+ treetop (~> 1.4.8)
49
+ mime-types (1.19)
50
+ multi_json (1.3.7)
51
+ polyglot (0.3.3)
52
+ rack (1.4.1)
53
+ rack-cache (1.2)
54
+ rack (>= 0.4)
55
+ rack-ssl (1.3.2)
56
+ rack
57
+ rack-test (0.6.2)
58
+ rack (>= 1.0)
59
+ rails (3.2.9)
60
+ actionmailer (= 3.2.9)
61
+ actionpack (= 3.2.9)
62
+ activerecord (= 3.2.9)
63
+ activeresource (= 3.2.9)
64
+ activesupport (= 3.2.9)
65
+ bundler (~> 1.0)
66
+ railties (= 3.2.9)
67
+ railties (3.2.9)
68
+ actionpack (= 3.2.9)
69
+ activesupport (= 3.2.9)
70
+ rack-ssl (~> 1.3.2)
71
+ rake (>= 0.8.7)
72
+ rdoc (~> 3.4)
73
+ thor (>= 0.14.6, < 2.0)
74
+ rake (0.9.2.2)
75
+ rdoc (3.12)
76
+ json (~> 1.4)
77
+ rspec (2.11.0)
78
+ rspec-core (~> 2.11.0)
79
+ rspec-expectations (~> 2.11.0)
80
+ rspec-mocks (~> 2.11.0)
81
+ rspec-core (2.11.1)
82
+ rspec-expectations (2.11.3)
83
+ diff-lcs (~> 1.1.3)
84
+ rspec-mocks (2.11.3)
85
+ sprockets (2.2.1)
86
+ hike (~> 1.2)
87
+ multi_json (~> 1.0)
88
+ rack (~> 1.0)
89
+ tilt (~> 1.1, != 1.3.0)
90
+ thor (0.16.0)
91
+ tilt (1.3.3)
92
+ treetop (1.4.12)
93
+ polyglot
94
+ polyglot (>= 0.3.1)
95
+ tzinfo (0.3.35)
96
+
97
+ PLATFORMS
98
+ ruby
99
+
100
+ DEPENDENCIES
101
+ creators!
102
+ rake
103
+ rspec
data/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # Creators 0.9 [![Build Status](https://secure.travis-ci.org/TheGiftsProject/Creators.png)](http://travis-ci.org/TheGiftsProject/Creators)
2
+
3
+ Creators help to clean up your controllers from the model creation setup code.
4
+ For the most basic situations simply creating a Creator and passing into it the request params, will just work for
5
+ creating a new model, and if you'll require adding custom validations, slicing up garbage params or refining a new
6
+ Hash of params to be used for the Model attributes, then a Creator is the home for all that.
7
+
8
+ ## Installation
9
+
10
+ Just add the creators gem to your Gemfile
11
+
12
+ `gem 'creators'`
13
+
14
+ ## Usage
15
+
16
+ This example shows a very simple happy-sad flow for creating a project model using a creator.
17
+ You can access the newly created project model when the creation is successful or the errors array if it's not.
18
+
19
+ ```ruby
20
+ class ProjectsController < ApplicationController
21
+
22
+ def create
23
+ project_creator = ProjectCreator.new(params, current_user)
24
+ if project_creator.save
25
+ redirect_to project_url(project_creator.project)
26
+ else
27
+ logger.fatal "Could not create project. Error list: #{project_creator.errors.join(", "}")
28
+ redirect_to error_page_url
29
+ end
30
+ end
31
+
32
+ end
33
+ ```
34
+
35
+ ## Defining a creator
36
+
37
+ We recommend putting all your creator objects in `app/creators`.
38
+ The model class that's attached to the creator is deduced from the name of the class.
39
+
40
+ ```ruby
41
+ class ProjectCreator < Creators::Base
42
+
43
+ def initialize(raw_params, current_user)
44
+ @user = current_user
45
+ super(raw_params)
46
+ end
47
+
48
+ def before_build # optional
49
+ error("project", "must be an hash") unless @params[:project].is_a? Hash
50
+ end
51
+
52
+ def refine_params # optional
53
+ @params[:project]
54
+ end
55
+
56
+ def after_build # optional
57
+ project.members.build(refined_admin)
58
+ end
59
+
60
+ private
61
+
62
+ def refined_admin
63
+ {
64
+ :role => :admin,
65
+ :name => @user.name
66
+ }
67
+ end
68
+ end
69
+ ```
70
+
71
+ A Creator simply requires the `raw_params` from the request,
72
+ you can also add any other data that you might need.
73
+ For example in the ProjectsCreator we need the current_user.
74
+
75
+ The specific behavior of your Creator is defined in the `refine_params` method and the callback methods, that compose
76
+ the Save method Life Cycle. The Creator `save` method is divided into 2 main steps:
77
+
78
+ 1) `build` - This step simply instantiates a new model (Project in our example) and assigns to it the `raw_params` we've
79
+ passed to the Creator. The `refine_params` step by default just uses the `raw_params`, and it can be easily overrided by
80
+ using the `refine_params` method. (As shown in our example)
81
+ Callback methods: `before_build`, `after_build`
82
+
83
+ 2) `save` - Simply calls `@model.save`.
84
+ Callback methods: `before_save`, `after_save`
85
+
86
+ ```
87
+ |-- Save Life Cycle
88
+ |--|-- before_build
89
+ |--|-- refine_params
90
+ |--|-- after_build
91
+ |--|-- before_save
92
+ |--|-- after_save
93
+ ```
94
+
95
+
96
+ ## Want to update your model? No problems!
97
+
98
+ Here's an example for a creator for the Task model, it relates to the Project model with a belongs_to association.
99
+
100
+ ```ruby
101
+ class TasksController < ApplicationController
102
+
103
+ def update
104
+ current_task = current_project.tasks.find_by_id(params[:task][:id])
105
+
106
+ task_creator = TaskCreator.new(params, current_task)
107
+ if task_creator.save
108
+ render :json => task_creator.task
109
+ else
110
+ logger.fatal "Could not update task for project #{current_project.id}. Error list: #{task_creator.errors.join(", "}")
111
+ end
112
+ end
113
+
114
+ end
115
+
116
+ class TaskCreator < Creators::Base
117
+
118
+ def initialize(raw_params, current_task)
119
+ @task = task
120
+ super(raw_params, @task)
121
+ end
122
+
123
+ def refine_params
124
+ params[:task]
125
+ end
126
+
127
+ end
128
+
129
+ For update operations, if you pass to super a model as the 2nd argument, then that model will be used
130
+ in the build process instead of it creating a new one, in case that model isn't nil.
131
+
132
+ ## Requirements
133
+
134
+ Ruby 1.8.7+, Rails 3.0+.
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require 'rspec/core/rake_task'
2
+ RSpec::Core::RakeTask.new('spec')
3
+ task :default => :spec
@@ -0,0 +1,101 @@
1
+ require 'active_support/core_ext'
2
+
3
+ # Creators are used to host code dealing with creation of new models and clean up the controllers.
4
+ #
5
+ # EXAMPLE:
6
+ # class SomeCreator
7
+ # def refine_params
8
+ # # a hash with refined parameters required for the model.
9
+ # end
10
+ # end
11
+ #
12
+ # class SomeController
13
+ # def action
14
+ # model = SomeCreator.new(params)
15
+ # if model.save
16
+ # # good flow
17
+ # else
18
+ # # bad flow
19
+ # end
20
+ # end
21
+ # end
22
+ module Creators
23
+ class Base
24
+
25
+ class ErrorInParams < StandardError;end
26
+
27
+ def self.inherited(child_class)
28
+ child_class.class_eval do
29
+ class_name = child_class.to_s.gsub('Creator', '')
30
+ define_method :klass do
31
+ class_name.constantize
32
+ end
33
+
34
+ define_method class_name.underscore do
35
+ model
36
+ end
37
+ end
38
+ end
39
+
40
+ def initialize(raw_params = {}, model = nil)
41
+ @params = raw_params
42
+ @model = model
43
+ @errors = {}
44
+ end
45
+
46
+ def save
47
+ build
48
+ before_save
49
+ return false unless @model.save
50
+ after_save
51
+ true
52
+ rescue ErrorInParams => e
53
+ Log.error(e)
54
+ false
55
+ end
56
+
57
+ def model
58
+ @model
59
+ end
60
+
61
+ def errors
62
+ e = @errors
63
+ return e.merge(@model.errors()) if @model.present? and @model.errors().present?
64
+ e
65
+ end
66
+
67
+ def error(field, text)
68
+ @errors[field] = text
69
+ raise ErrorInParams.new("#{field}: #{text}")
70
+ end
71
+
72
+ protected
73
+
74
+ def build
75
+ before_build
76
+ build_model
77
+ after_build
78
+ end
79
+
80
+ def build_model
81
+ @model ||= klass.new()
82
+ @model.attributes = refine_params
83
+ end
84
+
85
+ def refine_params
86
+ @params
87
+ end
88
+
89
+ def before_build
90
+ end
91
+
92
+ def after_build
93
+ end
94
+
95
+ def before_save
96
+ end
97
+
98
+ def after_save
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,3 @@
1
+ module Creators
2
+ VERSION = 0.9
3
+ end
data/lib/creators.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'active_support/dependencies'
2
+ require 'creators/version'
3
+ require 'rails/engine'
4
+
5
+ module Creators
6
+ class Engine < ::Rails::Engine
7
+ initializer 'creators.autoload', :before => :set_autoload_paths do |app|
8
+ app.config.autoload_paths += Dir["#{config.root}/app/creators/**/"]
9
+ end
10
+ end
11
+ end
12
+
13
+ require 'creators/creator'
@@ -0,0 +1,151 @@
1
+ require 'spec_helper'
2
+
3
+ class Log
4
+ def self.error(exception)
5
+
6
+ end
7
+ end
8
+
9
+ describe Creators::Base do
10
+
11
+ class FakeModel
12
+ attr_reader :an_attribute, :another_attribute
13
+
14
+ def initialize(attribute = nil, another = nil)
15
+ @an_attribute = attribute
16
+ @another_attribute = another
17
+ end
18
+
19
+ def self.build
20
+ FakeModel.new
21
+ end
22
+
23
+ def attributes=(attributes)
24
+ end
25
+
26
+ def save
27
+ end
28
+
29
+ def errors
30
+ nil
31
+ end
32
+ end
33
+
34
+ class FakeModelCreator < Creators::Base
35
+ end
36
+
37
+ subject { FakeModelCreator.new }
38
+
39
+ describe :save do
40
+
41
+ context 'params are invalid' do
42
+ it 'should return false when raw params are invalid' do
43
+ subject.save.should be_false
44
+ end
45
+ end
46
+
47
+ context 'params are valid' do
48
+ before (:all) do
49
+ subject.stub(:before_build => true)
50
+ FakeModel.any_instance.stub(:save => true)
51
+ end
52
+
53
+ it 'should return true' do
54
+ subject.save.should be_true
55
+ end
56
+
57
+ it 'should have the new instance returned by the model method' do
58
+ subject.model.class.should == FakeModel
59
+ end
60
+
61
+ it 'should have an aliased method for the model named after the the creator name' do
62
+ subject.send(FakeModel.to_s.underscore).should == subject.model
63
+ end
64
+ end
65
+
66
+ context 'update existing model' do
67
+
68
+ let(:changed_attribute) { 1 }
69
+ let(:changing_attribute) { 2 }
70
+ let(:static_attribute) { 3 }
71
+ let(:old_model) { FakeModel.new(changed_attribute, static_attribute) }
72
+ subject { FakeModelCreator.new({:an_attribute => changing_attribute}, old_model)}
73
+
74
+ before (:each) do
75
+ old_model.stub(:validate_params => true)
76
+ subject.save
77
+ end
78
+
79
+ it 'should not create a new model after save' do
80
+ subject.model.should == old_model
81
+ end
82
+
83
+ it 'should change only attributes that were passed in the raw params' do
84
+ subject.model.an_attribute == changing_attribute
85
+ subject.model.another_attribute == static_attribute
86
+ end
87
+ end
88
+ end
89
+
90
+ describe :errors do
91
+ def error_before_build
92
+ def subject.before_build
93
+ error(:field, "text")
94
+ end
95
+ end
96
+
97
+ def error_during_refine_params
98
+ def subject.refine_params
99
+ error(:field, "text")
100
+ end
101
+ end
102
+
103
+ def error_after_build
104
+ def subject.after_build
105
+ error(:field, "text")
106
+ end
107
+ end
108
+
109
+ it "should return a hash with standard errors" do
110
+ subject.errors.should == {}
111
+ end
112
+
113
+ it "should fill in an error if an error occurs before build" do
114
+ error_before_build
115
+ subject.save.should be_false
116
+ subject.errors.should == {:field => "text"}
117
+ end
118
+
119
+ it "should fill in an error if an error during refinment " do
120
+ error_during_refine_params
121
+ subject.save.should be_false
122
+ subject.errors.should == {:field => "text"}
123
+ end
124
+
125
+ it "should fill in an error if an error after build " do
126
+ error_after_build
127
+ subject.save.should be_false
128
+ subject.errors.should == {:field => "text"}
129
+ end
130
+
131
+ it "should return a merged error hash of both the model.errors and validation errors" do
132
+ error_after_build
133
+ FakeModel.any_instance.stub(:errors => {:field2 => "txet"})
134
+ subject.save.should be_false
135
+ subject.errors.should == {:field => "text", :field2 => "txet"}
136
+ end
137
+
138
+ it "should return only model.errors if no validation errors" do
139
+ FakeModel.any_instance.stub(:errors => {:field2 => "txet"})
140
+ subject.save.should be_false
141
+ subject.errors.should == {:field2 => "txet"}
142
+ end
143
+
144
+ it "should log validation errors that happen" do
145
+ error_before_build
146
+ Log.should_receive(:error)
147
+ subject.save
148
+ end
149
+ end
150
+
151
+ end
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'creators'
4
+
5
+ RSpec.configure do |config|
6
+ config.treat_symbols_as_metadata_keys_with_true_values = true
7
+ config.run_all_when_everything_filtered = true
8
+ config.filter_run :focus
9
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: creators
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.9'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Itay Adler
9
+ - Shay Davidson
10
+ - Yonatan Bergman
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2012-11-14 00:00:00.000000000Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rails
18
+ requirement: &24302960 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *24302960
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: &24302540 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: *24302540
38
+ - !ruby/object:Gem::Dependency
39
+ name: rspec
40
+ requirement: &24302120 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ type: :development
47
+ prerelease: false
48
+ version_requirements: *24302120
49
+ description: ! 'Creators are used to host code dealing with creation of new models
50
+ and clean up the controllers. '
51
+ email:
52
+ - itayadler@gmail.com
53
+ - shay.h.davidson@gmail.com
54
+ - lighthawky@gmail.com
55
+ executables: []
56
+ extensions: []
57
+ extra_rdoc_files: []
58
+ files:
59
+ - .gemspec
60
+ - .gitignore
61
+ - .rspec
62
+ - .rvmrc
63
+ - Gemfile
64
+ - Gemfile.lock
65
+ - README.md
66
+ - Rakefile
67
+ - lib/creators.rb
68
+ - lib/creators/creator.rb
69
+ - lib/creators/version.rb
70
+ - spec/lib/creators/creator_spec.rb
71
+ - spec/spec_helper.rb
72
+ homepage: https://github.com/TheGiftsProject/creators
73
+ licenses: []
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 1.8.17
93
+ signing_key:
94
+ specification_version: 3
95
+ summary: Making it even nicer to manage Form data params in your Controller.
96
+ test_files: []