trailblazer 0.0.1 → 0.1.0

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.
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(",") %>