disco-railties 0.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +1 -0
  4. data/bin/disco +7 -0
  5. data/bin/drails +3 -0
  6. data/lib/disco/app_disco_loader.rb +62 -0
  7. data/lib/disco/cli.rb +11 -0
  8. data/lib/disco/commands/application.rb +43 -0
  9. data/lib/disco/commands/destroy.rb +12 -0
  10. data/lib/disco/commands/domainserver.rb +6 -0
  11. data/lib/disco/commands/generate.rb +12 -0
  12. data/lib/disco/commands/projectionserver.rb +9 -0
  13. data/lib/disco/commands/server.rb +22 -0
  14. data/lib/disco/commands.rb +70 -0
  15. data/lib/disco/generators.rb +48 -0
  16. data/lib/disco/server/domain_server.rb +26 -0
  17. data/lib/disco/server/projection_servers.rb +26 -0
  18. data/lib/generators/disco/app/USAGE +14 -0
  19. data/lib/generators/disco/app/app_generator.rb +140 -0
  20. data/lib/generators/disco/app/templates/app/controllers/event_source_controller.rb +16 -0
  21. data/lib/generators/disco/app/templates/bin/disco +3 -0
  22. data/lib/generators/disco/app/templates/config/disco.yml +27 -0
  23. data/lib/generators/disco/app/templates/config/initializers/build_validations_registry.rb +19 -0
  24. data/lib/generators/disco/app/templates/config/initializers/create_domain.rb +5 -0
  25. data/lib/generators/disco/app/templates/db/seeds.rb +14 -0
  26. data/lib/generators/disco/command/USAGE +11 -0
  27. data/lib/generators/disco/command/command_generator.rb +69 -0
  28. data/lib/generators/disco/command/templates/command.rb.erb +24 -0
  29. data/lib/generators/disco/command/templates/event.rb.erb +11 -0
  30. data/lib/generators/disco/command_processor/USAGE +1 -0
  31. data/lib/generators/disco/command_processor/command_processor_generator.rb +22 -0
  32. data/lib/generators/disco/command_processor/templates/command_processor.rb +5 -0
  33. data/lib/generators/disco/domain.rb +19 -0
  34. data/lib/generators/disco/event_name.rb +52 -0
  35. data/lib/generators/disco/migration/USAGE +41 -0
  36. data/lib/generators/disco/migration/migration_generator.rb +27 -0
  37. data/lib/generators/disco/migration/templates/create_table_migration.rb +19 -0
  38. data/lib/generators/disco/model/USAGE +17 -0
  39. data/lib/generators/disco/model/model_generator.rb +29 -0
  40. data/lib/generators/disco/model/templates/domain_model.rb +5 -0
  41. data/lib/generators/disco/model/templates/model.rb +5 -0
  42. data/lib/generators/disco/processor_name.rb +48 -0
  43. data/lib/generators/disco/projection/USAGE +13 -0
  44. data/lib/generators/disco/projection/projection_generator.rb +19 -0
  45. data/lib/generators/disco/projection/templates/domain_projection.rb +9 -0
  46. data/lib/generators/disco/projection/templates/domain_projection_test.rb +6 -0
  47. data/lib/generators/disco/projection/templates/projection.rb +9 -0
  48. data/lib/generators/disco/projection/templates/projection_test.rb +6 -0
  49. data/lib/generators/disco/scaffold/USAGE +27 -0
  50. data/lib/generators/disco/scaffold/scaffold_generator.rb +91 -0
  51. data/lib/generators/disco/scaffold/templates/_eventstream.js.erb +16 -0
  52. data/lib/generators/disco/scaffold_controller/USAGE +1 -0
  53. data/lib/generators/disco/scaffold_controller/scaffold_controller_generator.rb +27 -0
  54. data/lib/generators/disco/scaffold_controller/templates/controller.rb +68 -0
  55. data/lib/generators/disco/scaffold_controller/templates/controller_test.rb +45 -0
  56. data/lib/generators/disco/use_domain_option.rb +54 -0
  57. data/lib/rails-disco/railtie.rb +8 -0
  58. data/lib/rails-disco/tasks.rb +1 -0
  59. data/lib/rails-disco/version.rb +10 -0
  60. data/lib/tasks/db.rake +222 -0
  61. data/lib/tasks/split.rake +94 -0
  62. metadata +161 -0
@@ -0,0 +1,69 @@
1
+ require 'generators/disco/processor_name.rb'
2
+ require 'generators/disco/event_name.rb'
3
+ require 'generators/disco/domain.rb'
4
+
5
+ module Disco
6
+ module Generators
7
+ class CommandGenerator < Rails::Generators::NamedBase
8
+ source_root File.expand_path('../templates', __FILE__)
9
+ argument :attributes, type: :array, default: [], banner: 'attribute attribute'
10
+ class_option :skip_model, type: :boolean, default: false, desc: 'Skip active model from the command'
11
+ class_option :model_name, type: :string, desc: 'Name of the active model behind the command'
12
+ class_option :persisted, type: :boolean, default: false, desc: 'Does the command update an existing model'
13
+ include ProcessorName
14
+ include EventName
15
+ include Domain
16
+
17
+ def create_command_file
18
+ template 'command.rb.erb', File.join('app/commands', class_path, "#{file_name}_command.rb")
19
+ end
20
+
21
+ def create_related_event_file
22
+ return if skip_event?
23
+ raise 'do not use id as attribute, this is reserved for the event id itself' if attributes_names.include? 'id'
24
+ template 'event.rb.erb', File.join('app/events', event_class_path, "#{event_file_name}_event.rb")
25
+ end
26
+
27
+ hook_for :command_processor, require: true do |hook|
28
+ unless skip_processor?
29
+ invoke hook, [processor_file_path], %w(-s --skip-namespace)
30
+ add_to_command_processor
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def add_to_command_processor
37
+ return if skip_processor? || (behavior == :revoke)
38
+ content = "
39
+
40
+ process #{class_name}Command do |command|
41
+ command.is_valid_do { event #{event_class_name}Event.new command.to_hash }
42
+ end"
43
+ file = File.join('domain/command_processors', processor_domain_class_path, "#{processor_file_name}_processor.rb")
44
+ inject_into_file file, content, after: /(\s)*include(\s)*ActiveDomain::CommandProcessor/
45
+ end
46
+
47
+ protected
48
+
49
+ def skip_model?
50
+ options[:skip_model]
51
+ end
52
+
53
+ def model_name
54
+ options[:model_name]
55
+ end
56
+
57
+ def persisted?
58
+ options[:persisted]
59
+ end
60
+
61
+ private
62
+
63
+ # allow this generator to be called multiple times
64
+ def invoke_command(command, *args) #:nodoc:
65
+ command.run(self, *args)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,24 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Command
3
+ <%- unless skip_model? -%>
4
+ include ActiveModel::Model
5
+ <%- end -%>
6
+ include ActiveEvent::Command
7
+ attributes <%= (['id'] + attributes_names).map{|x| ":#{x}"}.join(', ') %>
8
+ <%- if !model_name.blank? && !skip_model? -%>
9
+
10
+ def self.model_name
11
+ @_model_name ||= begin
12
+ namespace = self.parents.detect do |n|
13
+ n.respond_to?(:use_relative_model_naming?) && n.use_relative_model_naming?
14
+ end
15
+ ActiveModel::Name.new(self, namespace, <%= model_name.inspect %>)
16
+ end
17
+ end
18
+ <%- end -%>
19
+ <%- if persisted? && ! skip_model? -%>
20
+
21
+ def persisted?; true end
22
+ <%- end -%>
23
+ end
24
+ <% end -%>
@@ -0,0 +1,11 @@
1
+ <% module_namespacing do -%>
2
+ class <%= event_class_name %>Event
3
+ include ActiveEvent::EventType
4
+ attributes <%= (['id'] + attributes_names).map{|x| ":#{x}"}.join(', ') %>
5
+ <%- unless attributes_names.empty? -%>
6
+ def values
7
+ attributes_except :id
8
+ end
9
+ <%- end -%>
10
+ end
11
+ <% end -%>
@@ -0,0 +1 @@
1
+ Not intended for extern use!
@@ -0,0 +1,22 @@
1
+ require 'generators/disco/domain.rb'
2
+
3
+ module Disco
4
+ module Generators
5
+ class CommandProcessorGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path('../templates', __FILE__)
7
+ include Domain
8
+ hide!
9
+
10
+ def create_command_processor_file
11
+ template 'command_processor.rb', File.join('domain/command_processors', domain_class_path, "#{file_name}_processor.rb")
12
+ end
13
+
14
+ private
15
+
16
+ # allow this generator to be called multiple times
17
+ def invoke_command(command, *args) #:nodoc:
18
+ command.run(self, *args)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ module <%= Rails::Generators.namespace.name if Rails::Generators.namespace.present? %>Domain
2
+ class <%= class_name %>Processor
3
+ include ActiveDomain::CommandProcessor
4
+ end
5
+ end
@@ -0,0 +1,19 @@
1
+ require 'active_support/concern'
2
+
3
+ module Disco
4
+ module Generators
5
+ module Domain
6
+ extend ActiveSupport::Concern
7
+
8
+ def domain_class_path
9
+ @domain_calss_path ||= class_path_domain class_path
10
+ end
11
+
12
+ protected
13
+
14
+ def class_path_domain(class_path)
15
+ (Array.new class_path).unshift 'domain'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,52 @@
1
+ require 'active_support/concern'
2
+
3
+ module Disco
4
+ module Generators
5
+ module EventName
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ class_option :event, type: :string, default: nil, desc: "name of the event (defaults to NAME)"
10
+ class_option :skip_event, type: :boolean, default: false, desc: "skip event generation"
11
+ end
12
+
13
+ def initialize(args, *options)
14
+ super
15
+ assign_event_name!(event_name)
16
+ end
17
+
18
+ protected
19
+
20
+ attr_reader :event_file_name
21
+ attr_reader :event_class_path
22
+
23
+ def skip_event?
24
+ options[:skip_event]
25
+ end
26
+
27
+ def event_name
28
+ options[:event] || name
29
+ end
30
+
31
+ def event_class_name
32
+ (event_class_path + [event_file_name]).map!{ |m| m.camelize }.join('::')
33
+ end
34
+
35
+ def event_file_path
36
+ @event_file_path ||= (event_class_path + [event_file_name]).join('/')
37
+ end
38
+
39
+ def event_domain_class_path
40
+ @event_domain_class_path ||= class_path_domain event_class_path
41
+ end
42
+
43
+ private
44
+
45
+ def assign_event_name!(event_name)
46
+ @event_class_path = event_name.include?('/') ? event_name.split('/') : event_name.split('::')
47
+ @event_class_path.map! &:underscore
48
+ @event_file_name = @event_class_path.pop
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,41 @@
1
+ Description:
2
+ Stubs out a new database migration for ActiveRecord. Pass the migration name, either
3
+ CamelCased or under_scored, and an optional list of attribute pairs as arguments.
4
+
5
+ A migration class is generated in db/migrate prefixed by a timestamp of the current date and time.
6
+
7
+ You can name your migration in either of these formats to generate add/remove
8
+ column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable
9
+
10
+ Example:
11
+ `disco generate migration AddSslFlag`
12
+
13
+ If the current date is May 14, 2008 and the current time 09:09:12, this creates the AddSslFlag migration
14
+ db/migrate/20080514090912_add_ssl_flag.rb
15
+
16
+ `disco generate migration AddSslFlag --domain`
17
+
18
+ Under the same conditions as above, this creates the AddSslFlag migration
19
+ db/migrate_domain/20080514090912_add_ssl_flag.rb
20
+
21
+ `disco generate migration AddTitleBodyToPost title:string body:text published:boolean`
22
+
23
+ This will create the AddTitleBodyToPost in db/migrate/20080514090912_add_title_body_to_post.rb with this in the Change migration:
24
+
25
+ add_column :posts, :title, :string
26
+ add_column :posts, :body, :text
27
+ add_column :posts, :published, :boolean
28
+
29
+ Migration names containing JoinTable will generate join tables for use with
30
+ has_and_belongs_to_many associations.
31
+
32
+ Example:
33
+ `disco g migration CreateMediaJoinTable artists musics:uniq`
34
+
35
+ will create the migration
36
+
37
+ create_join_table :artists, :musics do |t|
38
+ # t.index [:artist_id, :music_id]
39
+ t.index [:music_id, :artist_id], unique: true
40
+ end
41
+
@@ -0,0 +1,27 @@
1
+ require 'rails/generators/active_record/migration/migration_generator'
2
+ require 'generators/disco/use_domain_option.rb'
3
+
4
+ module Disco
5
+ module Generators
6
+ class MigrationGenerator < ActiveRecord::Generators::MigrationGenerator
7
+ source_root File.expand_path('../templates', __FILE__)
8
+ include UseDomainOption
9
+
10
+ def create_migration_file
11
+ set_local_assigns!
12
+ validate_file_name!
13
+ migration_template @migration_template, "db/#{migration_dir}/#{file_name}.rb"
14
+ end
15
+
16
+ private
17
+
18
+ def migration_dir
19
+ if use_domain?
20
+ 'migrate_domain'
21
+ else
22
+ 'migrate'
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration
2
+ def change
3
+ create_table :<%= table_name %> do |t|
4
+ <% attributes.each do |attribute| -%>
5
+ <% if attribute.password_digest? -%>
6
+ t.string :password_digest<%= attribute.inject_options %>
7
+ <% else -%>
8
+ t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
9
+ <% end -%>
10
+ <% end -%>
11
+ <% if options[:timestamps] %>
12
+ t.timestamps
13
+ <% end -%>
14
+ end
15
+ <% attributes_with_index.each do |attribute| -%>
16
+ add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
17
+ <% end -%>
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ Description:
2
+ Generates a Model and a Projection for it.
3
+
4
+ Example:
5
+ disco generate model Thing [attr1:type, attr2:type]
6
+
7
+ This will create:
8
+ app/projection/thing_projection.rb
9
+ app/models/thing.rb
10
+ db/migrate/create_thing.rb
11
+
12
+ disco generate model Thing [attr1:type, attr2:type] --domain
13
+
14
+ This will create:
15
+ domain/projections/domain/thing_projection.rb
16
+ domain/models/domain/thing.rb
17
+ db/migrate_domain/create_thing.rb
@@ -0,0 +1,29 @@
1
+ require 'generators/disco/use_domain_option.rb'
2
+
3
+ module Disco
4
+ module Generators
5
+ class ModelGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path('../templates', __FILE__)
7
+ argument :attributes, type: :array, default: [], banner: 'field[:type] field[:type]'
8
+ include UseDomainOption
9
+
10
+ hook_for :projection, require: true do |hook|
11
+ invoke hook, [name]
12
+ end
13
+
14
+ def create_model_file
15
+ template use_domain('model.rb'), use_domain_class_file_path('models', "#{file_name}.rb")
16
+ end
17
+
18
+ hook_for :migration, require: true do |hook|
19
+ invoke hook, ["create_#{table_name}", *attributes]
20
+ end
21
+
22
+ private
23
+
24
+ # do not parse - keep attributes for forwarding to migration
25
+ def parse_attributes!
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,5 @@
1
+ module <%= Rails::Generators.namespace.name if Rails::Generators.namespace.present? %>Domain
2
+ class <%= class_name %> < ActiveRecord::Base
3
+ self.table_name = '<%=table_name %>'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %> < ActiveRecord::Base
3
+ self.table_name = '<%=table_name %>'
4
+ end
5
+ <% end -%>
@@ -0,0 +1,48 @@
1
+ require 'active_support/concern'
2
+
3
+ module Disco
4
+ module Generators
5
+ module ProcessorName
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ class_option :processor, type: :string, default: nil, desc: "class_name of the command processor (defaults to NAME)"
10
+ class_option :skip_processor, type: :boolean, default: false, desc: "Skip command processor generation"
11
+ end
12
+
13
+ def initialize(args, *options)
14
+ super
15
+ assign_processor_names!(processor_name)
16
+ end
17
+
18
+ protected
19
+
20
+ attr_reader :processor_file_name
21
+ attr_reader :processor_class_path
22
+
23
+ def skip_processor?
24
+ options[:skip_processor]
25
+ end
26
+
27
+ def processor_name
28
+ options[:processor] || name
29
+ end
30
+
31
+ def processor_file_path
32
+ @processor_file_path ||= (processor_class_path + [processor_file_name]).join('/')
33
+ end
34
+
35
+ def processor_domain_class_path
36
+ @processor_domain_class_path ||= class_path_domain processor_class_path
37
+ end
38
+
39
+ private
40
+
41
+ def assign_processor_names!(processor_name)
42
+ @processor_class_path = processor_name.include?('/') ? processor_name.split('/') : processor_name.split('::')
43
+ @processor_class_path.map! &:underscore
44
+ @processor_file_name = @processor_class_path.pop
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,13 @@
1
+ Description:
2
+ Generates a projection with handlers for the given events.
3
+
4
+ Example:
5
+ disco generate projection Thing [event event]
6
+
7
+ This will create:
8
+ app/projection/thing_projection.rb
9
+
10
+ disco generate projection Thing [event event] --domain
11
+
12
+ This will create:
13
+ domain/projections/domain/thing_projection.rb
@@ -0,0 +1,19 @@
1
+ require 'generators/disco/use_domain_option.rb'
2
+
3
+ module Disco
4
+ module Generators
5
+ class ProjectionGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path('../templates', __FILE__)
7
+ argument :events, type: :array, default: [], banner: 'event event'
8
+ include UseDomainOption
9
+
10
+ def create_projection_file
11
+ template use_domain('projection.rb'), use_domain_class_file_path('projections', "#{plural_file_name}_projection.rb")
12
+ end
13
+
14
+ def create_test_files
15
+ template use_domain('projection_test.rb'), File.join('test/projections', use_domain_class_path, "#{plural_file_name}_projection_test.rb")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ module <%= Rails::Generators.namespace.name if Rails::Generators.namespace.present? %>Domain
2
+ class <%= class_name %>Projection
3
+ include ActiveDomain::Projection
4
+ <% events.each do |event| %>
5
+ def <%= event.underscore.split('/') * '__' %>(event)
6
+ end
7
+ <% end %>
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ require 'test_helper'
2
+
3
+ module <%= Rails::Generators.namespace.name if Rails::Generators.namespace.present? %>Domain
4
+ class <%= plural_name.camelcase %>ProjectionTest < ActiveSupport::TestCase
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Projection
3
+ include ActiveProjection::ProjectionType
4
+ <% events.each do |event| %>
5
+ def <%= event.underscore.split('/') * '__' %>(event)
6
+ end
7
+ <% end %>
8
+ end
9
+ <% end -%>
@@ -0,0 +1,6 @@
1
+ require 'test_helper'
2
+
3
+ <% module_namespacing do -%>
4
+ class <%= plural_name.camelcase %>ProjectionTest < ActiveSupport::TestCase
5
+ end
6
+ <% end -%>
@@ -0,0 +1,27 @@
1
+ Description:
2
+ Scaffolds a complete resource with models, migration, projections, controller, views
3
+ commands, events and command_processor.
4
+
5
+ Example:
6
+ disco generate scaffold Thing [attr1:type, attr2:type]
7
+
8
+ This will create:
9
+ app/controllers/things_controller
10
+ app/commands/create_thing_command.rb
11
+ app/commands/update_thing_command.rb
12
+ app/commands/delete_thing_command.rb
13
+ domain/command_processors/thing_processor.rb
14
+ app/events/created_thing_event.rb
15
+ app/events/updated_thing_event.rb
16
+ app/events/deleted_thing_event.rb
17
+ app/projections/things_projection.rb
18
+ db/migrate/create_things.rb
19
+ app/models/thing.rb
20
+ app/helpers/things_helper.rb
21
+ app/views/things/_eventstream.js.erb
22
+ app/views/things/_form.html.erb
23
+ app/views/things/edit.html.erb
24
+ app/views/things/index.html.erb
25
+ app/views/things/new.html.erb
26
+ app/views/things/show.html.erb
27
+ a resource route
@@ -0,0 +1,91 @@
1
+ require 'generators/disco/processor_name.rb'
2
+ require 'generators/disco/domain.rb'
3
+
4
+ module Disco
5
+ module Generators
6
+ class ScaffoldGenerator < Rails::Generators::NamedBase
7
+ source_root File.expand_path('../templates', __FILE__)
8
+ argument :attributes, type: :array, default: [], banner: 'field[:type] field[:type]'
9
+ include ProcessorName
10
+ include Domain
11
+
12
+ hook_for :model, in: :disco, require: true
13
+
14
+ hook_for :command, in: :disco, require: true do |hook|
15
+ %w(create update delete).each do |action|
16
+ args = [(class_path + ["#{action}_#{file_name}"]) * '/']
17
+ args += attributes_names unless action == 'delete'
18
+ opts = ["--event=#{(class_path + ["#{action}d_#{file_name}"]) * '/'}"]
19
+ opts << "--processor=#{processor_name}" unless skip_processor?
20
+ opts << '--skip_model' if action == 'delete'
21
+ opts << "--model_name=#{class_name}"
22
+ opts << '--persisted' if action == 'update'
23
+ invoke hook, args, opts
24
+ add_to_projections(action)
25
+ end
26
+ add_to_command_processor
27
+ end
28
+
29
+ def add_routes
30
+ routing_code = ''
31
+ class_path.each_with_index do |namespace, index|
32
+ add_line_with_indent routing_code, (index + 1), "namespace :#{namespace} do"
33
+ end
34
+ add_line_with_indent routing_code, (class_path.length + 1), "resources :#{plural_name}"
35
+ class_path.each_with_index do |_, index|
36
+ add_line_with_indent routing_code, (class_path.length - index), 'end'
37
+ end
38
+ route routing_code[2..-1]
39
+ end
40
+
41
+ hook_for :scaffold_controller, in: :disco, require: true do |hook|
42
+ invoke hook
43
+ add_event_stream_to_views
44
+ end
45
+
46
+ def copy_event_stream_client
47
+ # ensure if app was created before this was default
48
+ copy_file '_eventstream.js.erb', 'app/views/application/eventstream/_eventstream.js.erb', verbose: false, skip: true
49
+ end
50
+
51
+ protected
52
+
53
+ def add_event_stream_to_views
54
+ return if behavior == :revoke
55
+ include_text = '<%= javascript_tag render partial: \'application/eventstream/eventstream\', formats: [:js], locals: {event_id: @event_id} %>'
56
+ prepend_to_file File.join('app/views', class_path, plural_file_name, 'index.html.erb'), include_text
57
+ prepend_to_file File.join('app/views', class_path, plural_file_name, 'show.html.erb'), include_text
58
+ end
59
+
60
+ def add_to_command_processor
61
+ return if behavior == :revoke
62
+ content = "\n command.id = ActiveDomain::UniqueCommandIdRepository.new_for command.class.name"
63
+ insert_into_file File.join('domain/command_processors', domain_class_path, "#{processor_file_name}_processor.rb"), content, after: /(\s)*process(\s)*(.)*CreateCommand(.)*/
64
+ end
65
+
66
+ def add_to_projections(action)
67
+ return if behavior == :revoke
68
+ event_func = (class_path + ["#{action}d_#{file_name}_event"]) * '__'
69
+ content = "
70
+
71
+ def #{event_func}(event)
72
+ #{method_bodies[action.to_sym]}
73
+ end"
74
+ indent(content) if namespaced?
75
+ inject_into_file File.join('app/projections', class_path, "#{plural_file_name}_projection.rb"), content, after: /(\s)*include(\s)*ActiveProjection::ProjectionType/
76
+ end
77
+
78
+ def method_bodies
79
+ @method_bodies ||= {
80
+ create: "#{class_name}.create! event.values.merge(id: event.id)",
81
+ update: "#{class_name}.find(event.id).update! event.values",
82
+ delete: "#{class_name}.find(event.id).destroy!",
83
+ }
84
+ end
85
+
86
+ def add_line_with_indent(target, indent, str)
87
+ target << "#{' ' * indent}#{str}\n"
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,16 @@
1
+ <% if event_id.present? %>
2
+ $(document).ready(function () {
3
+ setTimeout(function () {
4
+ var source = new EventSource('/event_stream');
5
+ source.addEventListener('refresh', function (e) {
6
+ var event = JSON.parse(e.data);
7
+ if (<%= event_id %> == event.id){
8
+ window.location.reload();
9
+ }else if (<%= event_id %> < event.id){
10
+ source.removeEventListener('refresh');
11
+ source.close();
12
+ }
13
+ });
14
+ }, 1);
15
+ });
16
+ <% end %>
@@ -0,0 +1 @@
1
+ Not intended for extern use!
@@ -0,0 +1,27 @@
1
+ require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
2
+ module Disco
3
+ module Generators
4
+ class ScaffoldControllerGenerator < Rails::Generators::ScaffoldControllerGenerator
5
+ source_root File.expand_path('../templates', __FILE__)
6
+ hide!
7
+
8
+ # the normal test_framework will not cover our usecase
9
+ remove_hook_for :test_framework
10
+ def create_test_files
11
+ template 'controller_test.rb', File.join('test/controllers', controller_class_path, "#{controller_file_name}_controller_test.rb")
12
+ end
13
+
14
+ protected
15
+
16
+ def command_class_name(command)
17
+ (class_path + ["#{command}_#{file_name}"]).map(&:camelize) * '::'
18
+ end
19
+
20
+ private
21
+
22
+ def params_string
23
+ attributes.map { |x| "#{x.name}: params[:#{singular_table_name}][:#{x.name}]" }.join(', ')
24
+ end
25
+ end
26
+ end
27
+ end