trailblazer 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -1
  3. data/.travis.yml +5 -0
  4. data/CHANGES.md +3 -0
  5. data/Gemfile +4 -0
  6. data/README.md +417 -16
  7. data/Rakefile +14 -0
  8. data/THOUGHTS +12 -0
  9. data/TODO.md +6 -0
  10. data/doc/Trb-The-Stack.png +0 -0
  11. data/doc/trb.jpg +0 -0
  12. data/gemfiles/Gemfile.rails +7 -0
  13. data/gemfiles/Gemfile.rails.lock +99 -0
  14. data/lib/trailblazer.rb +2 -0
  15. data/lib/trailblazer/autoloading.rb +5 -0
  16. data/lib/trailblazer/operation.rb +124 -0
  17. data/lib/trailblazer/operation/controller.rb +76 -0
  18. data/lib/trailblazer/operation/crud.rb +61 -0
  19. data/lib/trailblazer/operation/representer.rb +18 -0
  20. data/lib/trailblazer/operation/responder.rb +24 -0
  21. data/lib/trailblazer/operation/uploaded_file.rb +77 -0
  22. data/lib/trailblazer/operation/worker.rb +96 -0
  23. data/lib/trailblazer/version.rb +1 -1
  24. data/test/crud_test.rb +115 -0
  25. data/test/fixtures/apotomo.png +0 -0
  26. data/test/fixtures/cells.png +0 -0
  27. data/test/operation_test.rb +334 -0
  28. data/test/rails/controller_test.rb +175 -0
  29. data/test/rails/fake_app/app-cells/.gitkeep +0 -0
  30. data/test/rails/fake_app/cells.rb +21 -0
  31. data/test/rails/fake_app/config.rb +3 -0
  32. data/test/rails/fake_app/controllers.rb +101 -0
  33. data/test/rails/fake_app/models.rb +13 -0
  34. data/test/rails/fake_app/rails_app.rb +57 -0
  35. data/test/rails/fake_app/song/operations.rb +63 -0
  36. data/test/rails/fake_app/views/bands/show.html.erb +1 -0
  37. data/test/rails/fake_app/views/songs/new.html.erb +1 -0
  38. data/test/rails/test_helper.rb +4 -0
  39. data/test/responder_test.rb +77 -0
  40. data/test/test_helper.rb +15 -0
  41. data/test/uploaded_file_test.rb +85 -0
  42. data/test/worker_test.rb +116 -0
  43. data/trailblazer.gemspec +10 -2
  44. metadata +160 -23
@@ -0,0 +1,175 @@
1
+ # BUNDLE_GEMFILE=gemfiles/Gemfile.rails bundle exec rake rails
2
+ require 'test_helper'
3
+
4
+ ActionController::TestCase.class_eval do
5
+ setup do
6
+ @routes = Rails.application.routes
7
+ end
8
+ end
9
+
10
+ class GenericResponderTest < ActionController::TestCase
11
+ tests SongsController
12
+
13
+ setup do
14
+ @routes = Rails.application.routes
15
+ end
16
+
17
+ test "Create with params" do
18
+ post :create_with_params, {song: {title: "You're Going Down", length: 120}}
19
+ assert_response 302
20
+
21
+ song = Song.last
22
+ assert_equal "A Beautiful Indifference", song.title
23
+ assert_equal nil, song.length # params overwritten from controller.
24
+ end
25
+ end
26
+
27
+ # overriding Controller#process_params.
28
+ class ProcessParamsTest < ActionController::TestCase
29
+ tests BandsController
30
+
31
+ setup do
32
+ @routes = Rails.application.routes
33
+ end
34
+
35
+ test "Create with overridden #process_params" do
36
+ post :create, band: {name: "Kreator"}
37
+
38
+ band = Band.last
39
+ assert_equal "Kreator", band.name
40
+ assert_equal "Essen", band.locality
41
+ end
42
+ end
43
+
44
+ class ResponderRespondTest < ActionController::TestCase
45
+ tests SongsController
46
+
47
+ setup do
48
+ @routes = Rails.application.routes
49
+ end
50
+
51
+ # HTML
52
+ # #respond Create [valid]
53
+ test "Create [html/valid]" do
54
+ post :create, {song: {title: "You're Going Down"}}
55
+ assert_redirected_to song_path(Song.last)
56
+ end
57
+
58
+ test "Create [html/invalid]" do
59
+ post :create, {song: {title: ""}}
60
+ assert_equal @response.body, "{:title=&gt;[&quot;can&#39;t be blank&quot;]}"
61
+ end
62
+
63
+ test "Delete [html/valid]" do
64
+ song = Song::Create[song: {title: "You're Going Down"}].model
65
+ delete :destroy, id: song.id
66
+ assert_redirected_to songs_path
67
+ # assert that model is deleted.
68
+ end
69
+
70
+ test "respond with block [html/valid]" do
71
+ post :create_with_block, {song: {title: "You're Going Down"}}
72
+ assert_equal "block run, valid: true", response.body
73
+ end
74
+
75
+ test "respond with block [html/invalid]" do
76
+ post :create_with_block, {song: {title: ""}}
77
+ assert_equal "block run, valid: false", response.body
78
+ end
79
+
80
+ # JSON
81
+ test "Delete [json/valid]" do
82
+ song = Song::Create[song: {title: "You're Going Down"}].model
83
+ delete :destroy, id: song.id, format: :json
84
+ assert_response 204 # no content.
85
+ end
86
+
87
+ # JS
88
+ test "Delete [js/valid]" do
89
+ song = Song::Create[song: {title: "You're Going Down"}].model
90
+ assert_raises ActionView::MissingTemplate do
91
+ # js wants to render destroy.js.erb
92
+ delete :destroy, id: song.id, format: :js
93
+ end
94
+ end
95
+
96
+ test "Delete with formats [js/valid]" do
97
+ song = Song::Create[song: {title: "You're Going Down"}].model
98
+
99
+ delete :destroy_with_formats, id: song.id, format: :js
100
+ assert_response 200
101
+ assert_equal "Song slayer!", response.body
102
+ end
103
+
104
+ # TODO: #present
105
+ # TODO: #run
106
+
107
+ # describe "#run" do
108
+ # test "#run" do
109
+
110
+ # end
111
+ # end
112
+
113
+
114
+
115
+ end
116
+
117
+
118
+ class ResponderRunTest < ActionController::TestCase
119
+ tests BandsController
120
+
121
+ test "[html/valid]" do
122
+ put :update, {id: 1, band: {name: "Nofx"}}
123
+ assert_equal "no block: Nofx, Essen", response.body
124
+ end
125
+
126
+ test "with block [html/valid]" do
127
+ put :update_with_block, {id: 1, band: {name: "Nofx"}}
128
+ assert_equal "[valid] with block: Nofx, Essen", response.body
129
+ end
130
+
131
+ test "with block [html/invalid]" do
132
+ put :update_with_block, {id: 1, band: {name: ""}}
133
+ end
134
+ end
135
+
136
+ #present.
137
+ class ControllerPresentTest < ActionController::TestCase
138
+ tests BandsController
139
+
140
+ # let (:band) { }
141
+
142
+ test "#present" do
143
+ band = Band::Create[band: {name: "Nofx"}].model
144
+
145
+ get :show, id: band.id
146
+
147
+ assert_equal "bands/show.html: Band,Band,true,Band::Create,Essen\n", response.body
148
+ end
149
+
150
+ test "#present [JSON]" do
151
+ band = Band::Create[band: {name: "Nofx"}].model
152
+
153
+ get :show, id: band.id, format: :json
154
+ assert_equal "{\"name\":\"Nofx\"}", response.body
155
+ end
156
+ end
157
+
158
+
159
+ # #form.
160
+ class ControllerFormTest < ActionController::TestCase
161
+ tests BandsController
162
+
163
+ test "#form" do
164
+ get :new
165
+
166
+ assert_select "form input#band_name"
167
+ assert_select "b", ",Band,true,Band::Create"
168
+ end
169
+
170
+ test "#form with block" do
171
+ get :new_with_block
172
+
173
+ assert_select "b", "Band,Band,true,Band::Create,Essen"
174
+ end
175
+ end
File without changes
@@ -0,0 +1,21 @@
1
+ class UserCell < Cell::Rails
2
+ include Kaminari::Cells
3
+
4
+ def show(users)
5
+ @users = users
6
+
7
+ render :inline => <<-ERB
8
+ <%= paginate @users %>
9
+ ERB
10
+ end
11
+ end
12
+
13
+ class ViewModelCell < Cell::ViewModel
14
+ include Kaminari::Cells
15
+
16
+ def show
17
+ render :inline => <<-ERB
18
+ <%= paginate model %>
19
+ ERB
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ # database
2
+ ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}}
3
+ ActiveRecord::Base.establish_connection('test')
@@ -0,0 +1,101 @@
1
+ # controllers
2
+ class ApplicationController < ActionController::Base
3
+ append_view_path "test/rails/fake_app/views"
4
+ end
5
+
6
+ class SongsController < ApplicationController
7
+ respond_to :json, :js
8
+
9
+ def index
10
+ @users = Song.all.page params[:page]
11
+ render inline: <<-ERB
12
+ <%= render_cell(:user, :show, @users) %>
13
+ ERB
14
+ end
15
+
16
+ include Trailblazer::Operation::Controller
17
+ respond_to :html
18
+
19
+ def create
20
+ respond Song::Create
21
+ end
22
+
23
+ def create_with_params
24
+ respond Song::Create, song: {title: "A Beautiful Indifference"}
25
+ end
26
+
27
+ def create_with_block
28
+ respond Song::Create do |op, formats|
29
+ return render text: "block run, valid: #{op.valid?}"
30
+ end
31
+ end
32
+
33
+ def destroy
34
+ respond Song::Delete
35
+ end
36
+
37
+ def destroy_with_formats
38
+ respond Song::Delete do |op, formats|
39
+ formats.js { render text: "#{op.model.class} slayer!" }
40
+ end
41
+ end
42
+ end
43
+
44
+ class BandsController < ApplicationController
45
+ include Trailblazer::Operation::Controller
46
+ respond_to :html, :json
47
+
48
+ def show
49
+ present Band::Create do |op|
50
+ @klass = op.model.class
51
+ @locality = params[:band][:locality]
52
+ end # respond_to
53
+ end
54
+
55
+ def new
56
+ form Band::Create
57
+
58
+ render inline: <<-ERB
59
+ <%= form_for @form do |f| %>
60
+ <%= f.text_field :name %>
61
+ <% end %>
62
+
63
+ <b><%= [@klass, @model.class, @form.is_a?(Reform::Form), @operation.class].join(",") %></b>
64
+ ERB
65
+ end
66
+
67
+ def new_with_block
68
+ form Band::Create do |op|
69
+ @klass = op.model.class
70
+ @locality = params[:band][:locality]
71
+ end
72
+
73
+ render inline: <<-ERB
74
+ <b><%= [@klass, @model.class, @form.is_a?(Reform::Form), @operation.class, @locality].join(",") %></b>
75
+ ERB
76
+ end
77
+
78
+ def create
79
+ respond Band::Create
80
+ end
81
+
82
+ def update
83
+ run Band::Create
84
+
85
+ render text: "no block: #{@operation.model.name}, #{params[:band][:locality]}"
86
+ end
87
+
88
+ def update_with_block
89
+ run Band::Create do |op|
90
+ return render text: "[valid] with block: #{op.model.name}, #{params[:band][:locality]}"
91
+ end
92
+
93
+ render text: "[invalid] with block: #{@operation.model.name}, #{params[:band][:locality]}"
94
+ end
95
+
96
+ private
97
+ def process_params!(params) # this is where you set :current_user, etc.
98
+ params[:band] ||= {}
99
+ params[:band][:locality] = "Essen"
100
+ end
101
+ end
@@ -0,0 +1,13 @@
1
+ # models
2
+ class Song < ActiveRecord::Base
3
+ end
4
+
5
+ # migrations
6
+ class CreateAllTables < ActiveRecord::Migration
7
+ def self.up
8
+ create_table(:songs) { |t| t.string :title; t.integer :length }
9
+ create_table(:bands) { |t| t.string :name; t.string :locality }
10
+ end
11
+ end
12
+ ActiveRecord::Migration.verbose = false
13
+ CreateAllTables.up
@@ -0,0 +1,57 @@
1
+ # BUNDLE_GEMFILE=gemfiles/Gemfile.rails bundle exec rake rails
2
+ # TODO: how does rails handle all the different rake test tasks?
3
+
4
+ # require 'rails/all'
5
+ require 'action_controller/railtie'
6
+ require 'action_view/railtie'
7
+ require 'active_record'
8
+
9
+ require 'fake_app/config'
10
+
11
+
12
+ # config
13
+ app = Class.new(Rails::Application)
14
+ app.config.secret_token = '3b7cd727ee24e8444053437c36cc66c4'
15
+ app.config.session_store :cookie_store, :key => '_myapp_session'
16
+ app.config.active_support.deprecation = :log
17
+ app.config.eager_load = false
18
+ # Rais.root
19
+ app.config.root = File.dirname(__FILE__)
20
+ Rails.backtrace_cleaner.remove_silencers!
21
+ app.initialize!
22
+
23
+ # routes
24
+ app.routes.draw do
25
+ resources :songs do
26
+ member do # argh.
27
+ delete :destroy_with_formats
28
+ end
29
+
30
+ collection do
31
+ post :create_with_params
32
+ post :create_with_block
33
+ end
34
+ end
35
+
36
+ resources :bands do
37
+ collection do
38
+ post :create
39
+ get :new_with_block
40
+ end
41
+
42
+ member do
43
+ post :update_with_block
44
+ end
45
+ end
46
+ end
47
+
48
+ require 'trailblazer/operation/responder'
49
+ require 'trailblazer/operation/controller'
50
+ require 'trailblazer/operation/representer'
51
+
52
+ require 'fake_app/controllers'
53
+ require 'fake_app/models'
54
+ require 'fake_app/song/operations.rb'
55
+
56
+ # helpers
57
+ Object.const_set(:ApplicationHelper, Module.new)
@@ -0,0 +1,63 @@
1
+ class Song < ActiveRecord::Base
2
+ class Create < Trailblazer::Operation
3
+ include CRUD
4
+ include Responder
5
+ model Song, :create
6
+
7
+
8
+ contract do
9
+ property :title, validates: {presence: true}
10
+ property :length
11
+ end
12
+
13
+ def process(params)
14
+ validate(params[:song]) do
15
+ contract.save
16
+ end
17
+ end
18
+ end
19
+
20
+
21
+ class Delete < Create
22
+ action :find
23
+
24
+ def process(params)
25
+ model.destroy
26
+ self
27
+ end
28
+ end
29
+ end
30
+
31
+ class Band < ActiveRecord::Base
32
+ class Create < Trailblazer::Operation
33
+ include CRUD, Responder
34
+ model Band, :create
35
+
36
+ contract do
37
+ include Reform::Form::ActiveModel
38
+ model Band
39
+
40
+ property :name, validates: {presence: true}
41
+ property :locality
42
+ end
43
+
44
+ def process(params)
45
+ validate(params[:band]) do
46
+ contract.save
47
+ end
48
+ end
49
+
50
+ class JSON < self
51
+ action :find
52
+ include Representer
53
+ # self.representer_class = Class.new(contract_class)
54
+ # representer_class do
55
+ # include Reform::Form::JSON
56
+ # end
57
+ end
58
+
59
+ builds do |params|
60
+ JSON if params[:format] == "json"
61
+ end
62
+ end
63
+ end
@@ -0,0 +1 @@
1
+ bands/show.html: <%= [@klass, @model.class, @form.is_a?(Reform::Form), @operation.class, @locality].join(",") %>