creators 0.9

Sign up to get free protection for your applications and to get access to all the features.
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: []