bullet_train-super_scaffolding 1.0.0 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff4575c2ac8fe4254a40902558258c4b6987ced04ee50bc7506a829c43c0150a
4
- data.tar.gz: b64e648b62b67455633ea076b597c1cf9689d8a044755f1c28114622ea48dbe3
3
+ metadata.gz: b74d02debf9e4e33f53350fccef42b9ebdc719a55388d164ffed4936e891ada6
4
+ data.tar.gz: f54b12ae6b42083f23ad6cfec6a948c0648d3baf640308e8c31f9f1c60a45d95
5
5
  SHA512:
6
- metadata.gz: c9ca623c19afc3d40a8d235f976c47c4d84eb91e230430c88c0f020109a77dee26f1a82f8b81932a79472947d42c3bec24e14c049227c0253e89c76557a1f9cb
7
- data.tar.gz: 6aa2b5a0b6792eb701fb81926280eda270787773a11c053e433edb1a58e61c4f4c7eb7a1c0d474b0766832c5679607cbcc10e5dc6f4f32f852bdcc54a0ba17b6
6
+ metadata.gz: 0ad73bfd8032dc0cf35e81a6c2fba7a6e2fb16cb75b1ac512590dd30658b38f0a8c81cb0c02436ad9104ee560234adafb1130e8d9bd59dc9da457908ff16b5a1
7
+ data.tar.gz: 6a3eb155cd4b23d821e0e2bf2482d59253fad99452de3d4236fd8d28f8ebdb50f4c257f665cbe432125b013f54f1b2846ea8dd5d99d227f4d1b8d666a7c9dab9
@@ -0,0 +1,13 @@
1
+ module BulletTrain
2
+ module SuperScaffolding
3
+ class Scaffolder
4
+ attr_accessor :argv
5
+
6
+ def initialize(argv, options)
7
+ # Just setting these like this so the code we moved around still runs.
8
+ self.argv = argv
9
+ @options = options
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,44 @@
1
+ module BulletTrain
2
+ module SuperScaffolding
3
+ module Scaffolders
4
+ class CrudFieldScaffolder < Scaffolder
5
+ def run
6
+ unless argv.count >= 2
7
+ puts ""
8
+ puts "🚅 usage: bin/super-scaffold crud-field <Model> <attribute:type> <attribute:type> ... [options]"
9
+ puts ""
10
+ puts "E.g. add a description and body to Pages:"
11
+ puts " rails g migration add_description_etc_to_pages description:text body:text"
12
+ puts " bin/super-scaffold crud-field Page description:text body:text"
13
+ puts ""
14
+ puts "Options:"
15
+ puts ""
16
+ puts " --skip-table: Only add to the new/edit form and show view."
17
+ puts ""
18
+ exit
19
+ end
20
+
21
+ # We pass this value to parents to create a new Scaffolding::Transformer because
22
+ # we don't actually need knowledge of the parent to add the new field.
23
+ parents = [""]
24
+ child = argv[0]
25
+
26
+ # get all the attributes.
27
+ attributes = argv[1..-1]
28
+
29
+ check_required_options_for_attributes('crud-field', attributes, child)
30
+
31
+ transformer = Scaffolding::Transformer.new(child, parents, @options)
32
+ transformer.add_attributes_to_various_views(attributes, type: :crud_field)
33
+
34
+ transformer.additional_steps.uniq.each_with_index do |additional_step, index|
35
+ color, message = additional_step
36
+ puts ""
37
+ puts "#{index + 1}. #{message}".send(color)
38
+ end
39
+ puts ""
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,65 @@
1
+ module BulletTrain
2
+ module SuperScaffolding
3
+ module Scaffolders
4
+ class CrudScaffolder < Scaffolder
5
+ def run
6
+ unless argv.count >= 3
7
+ puts ""
8
+ puts "🚅 usage: bin/super-scaffold crud <Model> <ParentModel[s]> <attribute:type> <attribute:type> ..."
9
+ puts ""
10
+ puts "E.g. a Team has many Sites with some attributes:"
11
+ puts " rails g model Site team:references name:string url:text"
12
+ puts " bin/super-scaffold crud Site Team name:string url:text"
13
+ puts ""
14
+ puts "E.g. a Section belongs to a Page, which belongs to a Site, which belongs to a Team:"
15
+ puts " rails g model Section page:references title:text body:text"
16
+ puts " bin/super-scaffold crud Section Page,Site,Team title:text body:text"
17
+ puts ""
18
+ puts "E.g. an Image belongs to either a Page or a Site:"
19
+ puts " Doable! See https://bit.ly/2NvO8El for a step by step guide."
20
+ puts ""
21
+ puts "E.g. Pages belong to a Site and are sortable via drag-and-drop:"
22
+ puts " rails g model Page site:references name:string path:text"
23
+ puts " bin/super-scaffold crud Page Site,Team name:text path:text --sortable"
24
+ puts ""
25
+ puts "🏆 Protip: Commit your other changes before running Super Scaffolding so it's easy to undo if you (or we) make any mistakes."
26
+ puts "If you do that, you can reset to your last commit state by using `git checkout .` and `git clean -d -f` ."
27
+ puts ""
28
+ puts "Give it a shot! Let us know if you have any trouble with it! ✌️"
29
+ puts ""
30
+ exit
31
+ end
32
+
33
+ child = argv[0]
34
+ parents = argv[1] ? argv[1].split(",") : []
35
+ parents = parents.map(&:classify).uniq
36
+ parent = parents.first
37
+
38
+ unless parents.include?("Team")
39
+ raise "Parents for #{child} should trace back to the Team model, but Team wasn't provided. Please confirm that all of the parents tracing back to the Team model are present and try again.\n" +
40
+ "E.g.:\n" +
41
+ "rails g model Section page:references title:text body:text\n" +
42
+ "bin/super-scaffold crud Section Page,Site,Team title:text body:text\n"
43
+ end
44
+
45
+ # get all the attributes.
46
+ attributes = argv[2..-1]
47
+
48
+ check_required_options_for_attributes('crud', attributes, child, parent)
49
+
50
+ binding.pry
51
+
52
+ transformer = Scaffolding::Transformer.new(child, parents, @options)
53
+ transformer.scaffold_crud(attributes)
54
+
55
+ transformer.additional_steps.each_with_index do |additional_step, index|
56
+ color, message = additional_step
57
+ puts ""
58
+ puts "#{index + 1}. #{message}".send(color)
59
+ end
60
+ puts ""
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,96 @@
1
+ module BulletTrain
2
+ module SuperScaffolding
3
+ module Scaffolders
4
+ class JoinModelScaffolder < Scaffolder
5
+ def run
6
+ unless argv.count >= 3
7
+ puts ""
8
+ puts "🚅 usage: bin/super-scaffold join-model <JoinModel> <left_association> <right_association>"
9
+ puts ""
10
+ puts "E.g. Add project-specific tags to a project:"
11
+ puts ""
12
+ puts " Given the following example models:".blue
13
+ puts ""
14
+ puts " rails g model Project team:references name:string description:text"
15
+ puts " bin/super-scaffold crud Project Team name:text_field description:trix_editor"
16
+ puts ""
17
+ puts " rails g model Projects::Tag team:references name:string"
18
+ puts " bin/super-scaffold crud Projects::Tag Team name:text_field"
19
+ puts ""
20
+ puts " 1️⃣ Use the standard Rails model generator to generate the join model:".blue
21
+ puts ""
22
+ puts " rails g model Projects::AppliedTag project:references tag:references"
23
+ puts ""
24
+ puts " 👋 Don't run migrations yet! Sometimes Super Scaffolding updates them for you.".yellow
25
+ puts ""
26
+ puts " 2️⃣ Use `join-model` scaffolding to prepare the join model for use in `crud-field` scaffolding:".blue
27
+ puts ""
28
+ puts " bin/super-scaffold join-model Projects::AppliedTag project_id[class_name=Project] tag_id[class_name=Projects::Tag]"
29
+ puts ""
30
+ puts " 3️⃣ Now you can use `crud-field` scaffolding to actually add the field to the form of the parent model:".blue
31
+ puts ""
32
+ puts " bin/super-scaffold crud-field Project tag_ids:super_select[class_name=Projects::Tag]"
33
+ puts ""
34
+ puts " 👋 Heads up! There will be one follow-up step output by this command that you need to take action on."
35
+ puts ""
36
+ puts " 4️⃣ Now you can run your migrations.".blue
37
+ exit
38
+ end
39
+
40
+ child = argv[0]
41
+ primary_parent = argv[1].split("class_name=").last.split(",").first.split("]").first
42
+ secondary_parent = argv[2].split("class_name=").last.split(",").first.split("]").first
43
+
44
+ # There should only be two attributes.
45
+ attributes = [argv[1], argv[2]]
46
+
47
+ # Pretend we're doing a `super_select` scaffolding because it will do the correct thing.
48
+ attributes = attributes.map { |attribute| attribute.gsub("\[", ":super_select\[") }
49
+ attributes = attributes.map { |attribute| attribute.gsub("\]", ",required\]") }
50
+
51
+ transformer = Scaffolding::Transformer.new(child, [primary_parent], @options)
52
+
53
+ # We need this transformer to reflect on the class names _just_ between e.g. `Project` and `Projects::Tag`, without the join model.
54
+ has_many_through_transformer = Scaffolding::Transformer.new(secondary_parent, [primary_parent], @options)
55
+
56
+ # We need this transformer to reflect on the association between `Projects::Tag` and `Projects::AppliedTag` backwards.
57
+ inverse_transformer = Scaffolding::Transformer.new(child, [secondary_parent], @options)
58
+
59
+ # We need this transformer to reflect on the class names _just_ between e.g. `Projects::Tag` and `Project`, without the join model.
60
+ inverse_has_many_through_transformer = Scaffolding::Transformer.new(primary_parent, [secondary_parent], @options)
61
+
62
+ # However, for the first attribute, we actually don't need the scope validator (and can't really implement it).
63
+ attributes[0] = attributes[0].gsub("\]", ",unscoped\]")
64
+
65
+ has_many_through_association = has_many_through_transformer.transform_string("completely_concrete_tangible_things")
66
+ source = transformer.transform_string("absolutely_abstract_creative_concept.valid_$HAS_MANY_THROUGH_ASSOCIATION")
67
+ source.gsub!("$HAS_MANY_THROUGH_ASSOCIATION", has_many_through_association)
68
+
69
+ # For the second one, we don't want users to have to define the list of valid options in the join model, so we do this:
70
+ attributes[1] = attributes[1].gsub("\]", ",source=#{source}\]")
71
+
72
+ # This model hasn't been crud scaffolded, so a bunch of views are skipped here, but that's OK!
73
+ # It does what we need on the files that exist.
74
+ transformer.add_scaffolding_hooks_to_model
75
+
76
+ transformer.suppress_could_not_find = true
77
+ transformer.add_attributes_to_various_views(attributes, type: :crud_field)
78
+ transformer.suppress_could_not_find = false
79
+
80
+ # Add the `has_many ... through:` association in both directions.
81
+ transformer.add_has_many_through_associations(has_many_through_transformer)
82
+ inverse_transformer.add_has_many_through_associations(inverse_has_many_through_transformer)
83
+
84
+ additional_steps = (transformer.additional_steps + has_many_through_transformer.additional_steps + inverse_transformer.additional_steps + inverse_has_many_through_transformer.additional_steps).uniq
85
+
86
+ additional_steps.each_with_index do |additional_step, index|
87
+ color, message = additional_step
88
+ puts ""
89
+ puts "#{index + 1}. #{message}".send(color)
90
+ end
91
+ puts ""
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,173 @@
1
+ module BulletTrain
2
+ module SuperScaffolding
3
+ module Scaffolders
4
+ class OauthProviderScaffolder < Scaffolder
5
+ def run
6
+ unless argv.count >= 5
7
+ puts ""
8
+ puts "🚅 usage: bin/super-scaffold oauth-provider <omniauth_gem> <gems_provider_name> <our_provider_name> <PROVIDER_API_KEY_IN_ENV> <PROVIDER_API_SECRET_IN_ENV> [options]"
9
+ puts ""
10
+ puts "E.g. what we'd do to start Stripe off (if we didn't already do it):"
11
+ puts " bin/super-scaffold oauth-provider omniauth-stripe-connect stripe_connect Oauth::StripeAccount STRIPE_CLIENT_ID STRIPE_SECRET_KEY --icon=ti-money"
12
+ puts ""
13
+ puts "E.g. what we actually did to start Shopify off:"
14
+ puts " bin/super-scaffold oauth-provider omniauth-shopify-oauth2 shopify Oauth::ShopifyAccount SHOPIFY_API_KEY SHOPIFY_API_SECRET_KEY --icon=ti-shopping-cart"
15
+ puts ""
16
+ puts "Options:"
17
+ puts ""
18
+ puts " --icon={ti-*}: Specify an icon."
19
+ puts ""
20
+ puts "For a list of readily available provider strategies, see https://github.com/omniauth/omniauth/wiki/List-of-Strategies ."
21
+ puts ""
22
+ exit
23
+ end
24
+
25
+ _, omniauth_gem, gems_provider_name, our_provider_name, api_key, api_secret = *ARGV
26
+
27
+ unless match = our_provider_name.match(/Oauth::(.*)Account/)
28
+ puts "\n🚨 Your provider name must match the pattern of `Oauth::{Name}Account`, e.g. `Oauth::StripeAccount`\n".red
29
+ return
30
+ end
31
+
32
+ options = {
33
+ omniauth_gem: omniauth_gem,
34
+ gems_provider_name: gems_provider_name,
35
+ our_provider_name: match[1],
36
+ api_key: api_key,
37
+ api_secret: api_secret
38
+ }
39
+
40
+ unless File.exist?(oauth_transform_string("./app/models/oauth/stripe_account.rb", options)) &&
41
+ File.exist?(oauth_transform_string("./app/models/integrations/stripe_installation.rb", options)) &&
42
+ File.exist?(oauth_transform_string("./app/models/webhooks/incoming/oauth/stripe_account_webhook.rb", options))
43
+ puts ""
44
+ puts oauth_transform_string("🚨 Before doing the actual Super Scaffolding, you'll need to generate the models like so:", options).red
45
+ puts ""
46
+ puts oauth_transform_string(" rails g model Oauth::StripeAccount uid:string data:jsonb user:references", options).red
47
+ puts oauth_transform_string(" rails g model Integrations::StripeInstallation team:references oauth_stripe_account:references name:string", options).red
48
+ puts oauth_transform_string(" rails g model Webhooks::Incoming::Oauth::StripeAccountWebhook data:jsonb processed_at:datetime verified_at:datetime oauth_stripe_account:references", options).red
49
+ puts ""
50
+ puts "However, don't do the `rake db:migrate` until after you re-run Super Scaffolding, as it will need to update some settings in those migrations.".red
51
+ puts ""
52
+ return
53
+ end
54
+
55
+ icon_name = nil
56
+ if @options["icon"].present?
57
+ icon_name = @options["icon"]
58
+ else
59
+ puts "OK, great! Let's do this! By default providers will appear with a dollar symbol,"
60
+ puts "but after you hit enter I'll open a page where you can view other icon options."
61
+ puts "When you find one you like, hover your mouse over it and then come back here and"
62
+ puts "and enter the name of the icon you want to use."
63
+ response = STDIN.gets.chomp
64
+ `open http://light.pinsupreme.com/icon_fonts_themefy.html`
65
+ puts ""
66
+ puts "Did you find an icon you wanted to use? Enter the name here or hit enter to just"
67
+ puts "use the dollar symbol:"
68
+ icon_name = STDIN.gets.chomp
69
+ puts ""
70
+ unless icon_name.length > 0 || icon_name.downcase == "y"
71
+ icon_name = "icon-puzzle"
72
+ end
73
+ end
74
+
75
+ options[:icon] = icon_name
76
+
77
+ [
78
+
79
+ # User OAuth.
80
+ "./app/models/oauth/stripe_account.rb",
81
+ "./app/models/webhooks/incoming/oauth/stripe_account_webhook.rb",
82
+ "./app/controllers/account/oauth/stripe_accounts_controller.rb",
83
+ "./app/controllers/webhooks/incoming/oauth/stripe_account_webhooks_controller.rb",
84
+ "./app/views/account/oauth/stripe_accounts",
85
+ "./test/models/oauth/stripe_account_test.rb",
86
+ "./test/factories/oauth/stripe_accounts.rb",
87
+ "./config/locales/en/oauth/stripe_accounts.en.yml",
88
+ "./app/views/devise/shared/oauth/_stripe.html.erb",
89
+
90
+ # Team Integration.
91
+ "./app/models/integrations/stripe_installation.rb",
92
+ # './app/serializers/api/v1/integrations/stripe_installation_serializer.rb',
93
+ "./app/controllers/account/integrations/stripe_installations_controller.rb",
94
+ "./app/views/account/integrations/stripe_installations",
95
+ "./test/models/integrations/stripe_installation_test.rb",
96
+ "./test/factories/integrations/stripe_installations.rb",
97
+ "./config/locales/en/integrations/stripe_installations.en.yml",
98
+
99
+ # Webhook.
100
+ "./app/models/webhooks/incoming/oauth/stripe_account_webhook.rb",
101
+ "./app/controllers/webhooks/incoming/oauth/stripe_account_webhooks_controller.rb"
102
+
103
+ ].each do |name|
104
+ if File.directory?(name)
105
+ oauth_scaffold_directory(name, options)
106
+ else
107
+ oauth_scaffold_file(name, options)
108
+ end
109
+ end
110
+
111
+ oauth_scaffold_add_line_to_file("./app/views/devise/shared/_oauth.html.erb", "<%= render 'devise/shared/oauth/stripe', verb: verb if stripe_enabled? %>", "<%# 🚅 super scaffolding will insert new oauth providers above this line. %>", options, prepend: true)
112
+ oauth_scaffold_add_line_to_file("./app/views/account/users/edit.html.erb", "<%= render 'account/oauth/stripe_accounts/index', context: @user, stripe_accounts: @user.oauth_stripe_accounts if stripe_enabled? %>", "<% # 🚅 super scaffolding will insert new oauth providers above this line. %>", options, prepend: true)
113
+ oauth_scaffold_add_line_to_file("./config/initializers/devise.rb", "config.omniauth :stripe_connect, ENV['STRIPE_CLIENT_ID'], ENV['STRIPE_SECRET_KEY'], {\n ## specify options for your oauth provider here, e.g.:\n # scope: 'read_products,read_orders,write_content',\n }\n", "# 🚅 super scaffolding will insert new oauth providers above this line.", options, prepend: true)
114
+ oauth_scaffold_add_line_to_file("./app/controllers/account/oauth/omniauth_callbacks_controller.rb", "def stripe_connect\n callback(\"Stripe\", team_id_from_env)\n end\n", "# 🚅 super scaffolding will insert new oauth providers above this line.", options, prepend: true)
115
+ oauth_scaffold_add_line_to_file("./app/models/team.rb", "has_many :integrations_stripe_installations, class_name: 'Integrations::StripeInstallation', dependent: :destroy if stripe_enabled?", "# 🚅 add oauth providers above.", options, prepend: true)
116
+ oauth_scaffold_add_line_to_file("./app/models/user.rb", "has_many :oauth_stripe_accounts, class_name: 'Oauth::StripeAccount' if stripe_enabled?", "# 🚅 add oauth providers above.", options, prepend: true)
117
+ oauth_scaffold_add_line_to_file("./config/locales/en/oauth.en.yml", "stripe_connect: Stripe", "# 🚅 super scaffolding will insert new oauth providers above this line.", options, prepend: true)
118
+ oauth_scaffold_add_line_to_file("./app/views/account/shared/_menu.html.erb", "<%= render 'account/integrations/stripe_installations/menu_item' if stripe_enabled? %>", "<%# 🚅 super scaffolding will insert new oauth providers above this line. %>", options, prepend: true)
119
+ oauth_scaffold_add_line_to_file("./config/routes.rb", "resources :stripe_account_webhooks if stripe_enabled?", "# 🚅 super scaffolding will insert new oauth provider webhooks above this line.", options, prepend: true)
120
+ oauth_scaffold_add_line_to_file("./config/routes.rb", "resources :stripe_accounts if stripe_enabled?", "# 🚅 super scaffolding will insert new oauth providers above this line.", options, prepend: true)
121
+ oauth_scaffold_add_line_to_file("./config/routes.rb", "resources :stripe_installations if stripe_enabled?", "# 🚅 super scaffolding will insert new integration installations above this line.", options, prepend: true)
122
+ oauth_scaffold_add_line_to_file("./Gemfile", "gem 'omniauth-stripe-connect'", "# 🚅 super scaffolding will insert new oauth providers above this line.", options, prepend: true)
123
+ oauth_scaffold_add_line_to_file("./lib/bullet_train.rb", "def stripe_enabled?\n ENV['STRIPE_CLIENT_ID'].present? && ENV['STRIPE_SECRET_KEY'].present?\nend\n", "# 🚅 super scaffolding will insert new oauth providers above this line.", options, prepend: true)
124
+ oauth_scaffold_add_line_to_file("./lib/bullet_train.rb", "stripe_enabled?,", "# 🚅 super scaffolding will insert new oauth provider checks above this line.", options, prepend: true)
125
+ oauth_scaffold_add_line_to_file("./app/models/ability.rb", "if stripe_enabled?
126
+ can [:read, :create, :destroy], Oauth::StripeAccount, user_id: user.id
127
+ can :manage, Integrations::StripeInstallation, team_id: user.team_ids
128
+ can :destroy, Integrations::StripeInstallation, oauth_stripe_account: {user_id: user.id}
129
+ end
130
+ ", "# 🚅 super scaffolding will insert any new oauth providers above.", options, prepend: true)
131
+
132
+ # find the database migration that defines this relationship.
133
+ migration_file_name = `grep "create_table #{oauth_transform_string(":oauth_stripe_accounts", options)}" db/migrate/*`.split(":").first
134
+ legacy_replace_in_file(migration_file_name, "null: false", "null: true")
135
+
136
+ migration_file_name = `grep "create_table #{oauth_transform_string(":integrations_stripe_installations", options)}" db/migrate/*`.split(":").first
137
+ legacy_replace_in_file(migration_file_name,
138
+ oauth_transform_string("t.references :oauth_stripe_account, null: false, foreign_key: true", options),
139
+ oauth_transform_string('t.references :oauth_stripe_account, null: false, foreign_key: true, index: {name: "index_stripe_installations_on_oauth_stripe_account_id"}', options))
140
+
141
+ migration_file_name = `grep "create_table #{oauth_transform_string(":webhooks_incoming_oauth_stripe_account_webhooks", options)}" db/migrate/*`.split(":").first
142
+ legacy_replace_in_file(migration_file_name, "null: false", "null: true")
143
+ legacy_replace_in_file(migration_file_name, "foreign_key: true", 'foreign_key: true, index: {name: "index_stripe_webhooks_on_oauth_stripe_account_id"}')
144
+
145
+ puts ""
146
+ puts "🎉"
147
+ puts ""
148
+ puts "You'll probably need to `bundle install`.".green
149
+ puts ""
150
+ puts "If the OAuth provider asks you for some whitelisted callback URLs, the URL structure for those is as so:"
151
+ puts ""
152
+ path = "users/auth/stripe_connect/callback"
153
+ puts oauth_transform_string(" https://yourdomain.co/#{path}", options)
154
+ puts oauth_transform_string(" https://yourtunnel.ngrok.io/#{path}", options)
155
+ puts oauth_transform_string(" http://localhost:3000/#{path}", options)
156
+ puts ""
157
+ puts "If you're able to specify an endpoint to receive webhooks from this provider, use this URL:"
158
+ puts ""
159
+ path = "webhooks/incoming/oauth/stripe_account_webhooks"
160
+ puts oauth_transform_string(" https://yourdomain.co/#{path}", options)
161
+ puts oauth_transform_string(" https://yourtunnel.ngrok.io/#{path}", options)
162
+ puts oauth_transform_string(" http://localhost:3000/#{path}", options)
163
+ puts ""
164
+ puts ""
165
+ puts "If you'd like to edit how your Bullet Train application refers to this provider, just edit the locale file at `config/locales/en/oauth.en.yml`."
166
+ puts ""
167
+ puts "And finally, if you need to specify any custom authorizations or options for your OAuth integration with this provider, you can configure those in `config/initializers/devise.rb`."
168
+ puts ""
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
@@ -1,5 +1,5 @@
1
1
  module BulletTrain
2
2
  module SuperScaffolding
3
- VERSION = "1.0.0"
3
+ VERSION = "1.0.4"
4
4
  end
5
5
  end
@@ -1,8 +1,26 @@
1
1
  require "bullet_train/super_scaffolding/version"
2
2
  require "bullet_train/super_scaffolding/engine"
3
+ require "bullet_train/super_scaffolding/scaffolder"
4
+ require "bullet_train/super_scaffolding/scaffolders/crud_scaffolder"
5
+ require "bullet_train/super_scaffolding/scaffolders/crud_field_scaffolder"
6
+ require "bullet_train/super_scaffolding/scaffolders/join_model_scaffolder"
7
+ require "bullet_train/super_scaffolding/scaffolders/oauth_provider_scaffolder"
3
8
 
4
9
  module BulletTrain
5
10
  module SuperScaffolding
6
- # Your code goes here...
11
+ mattr_accessor :template_paths, default: []
12
+ mattr_accessor :scaffolders, default: {
13
+ "crud" => "BulletTrain::SuperScaffolding::Scaffolders::CrudScaffolder",
14
+ "crud-field" => "BulletTrain::SuperScaffolding::Scaffolders::CrudFieldScaffolder",
15
+ "join-model" => "BulletTrain::SuperScaffolding::Scaffolders::JoinModelScaffolder",
16
+ "oauth-provider" => "BulletTrain::SuperScaffolding::Scaffolders::OauthProviderScaffolder",
17
+ }
18
+
19
+ class Runner
20
+ def run
21
+ # Make `rake` invocation compatible with how this was run historically.
22
+ require "scaffolding/script"
23
+ end
24
+ end
7
25
  end
8
26
  end
@@ -1,3 +1,57 @@
1
+ def legacy_replace_in_file(file, before, after)
2
+ puts "Replacing in '#{file}'."
3
+ target_file_content = File.read(file)
4
+ target_file_content.gsub!(before, after)
5
+ File.write(file, target_file_content)
6
+ end
7
+
8
+ def legacy_add_line_to_file(file, content, hook, child, parent, options = {})
9
+ increase_indent = options[:increase_indent]
10
+ add_before = options[:add_before]
11
+ add_after = options[:add_after]
12
+
13
+ transformed_file_name = file
14
+ transformed_content = content
15
+ transform_hook = hook
16
+
17
+ target_file_content = File.read(transformed_file_name)
18
+
19
+ if target_file_content.include?(transformed_content)
20
+ puts "No need to update '#{transformed_file_name}'. It already has '#{transformed_content}'."
21
+ else
22
+ new_target_file_content = []
23
+ target_file_content.split("\n").each do |line|
24
+ if /#{Regexp.escape(transform_hook)}\s*$/.match?(line)
25
+
26
+ if add_before
27
+ new_target_file_content << "#{line} #{add_before}"
28
+ else
29
+ unless options[:prepend]
30
+ new_target_file_content << line
31
+ end
32
+ end
33
+
34
+ # get leading whitespace.
35
+ line =~ /^(\s*).*#{Regexp.escape(transform_hook)}.*/
36
+ leading_whitespace = $1
37
+ new_target_file_content << "#{leading_whitespace}#{" " if increase_indent}#{transformed_content}"
38
+
39
+ new_target_file_content << "#{leading_whitespace}#{add_after}" if add_after
40
+
41
+ if options[:prepend]
42
+ new_target_file_content << line
43
+ end
44
+ else
45
+ new_target_file_content << line
46
+ end
47
+ end
48
+
49
+ puts "Updating '#{transformed_file_name}'."
50
+
51
+ File.write(transformed_file_name, new_target_file_content.join("\n") + "\n")
52
+ end
53
+ end
54
+
1
55
  def encode_double_replacement_fix(string)
2
56
  string.chars.join("~!@BT@!~")
3
57
  end
@@ -1,66 +1,11 @@
1
- require "active_support/inflector"
2
- require "fileutils"
3
- require "pry"
4
- require "colorize"
5
-
6
- require_relative "#{APP_ROOT}/config/initializers/inflections"
7
-
8
1
  # TODO these methods were removed from the global scope in super scaffolding and moved to `Scaffolding::Transformer`,
9
2
  # but oauth provider scaffolding hasn't been updated yet.
10
3
 
11
- def legacy_replace_in_file(file, before, after)
12
- puts "Replacing in '#{file}'."
13
- target_file_content = File.read(file)
14
- target_file_content.gsub!(before, after)
15
- File.write(file, target_file_content)
16
- end
17
-
18
- def legacy_add_line_to_file(file, content, hook, child, parent, options = {})
19
- increase_indent = options[:increase_indent]
20
- add_before = options[:add_before]
21
- add_after = options[:add_after]
22
-
23
- transformed_file_name = file
24
- transformed_content = content
25
- transform_hook = hook
26
-
27
- target_file_content = File.read(transformed_file_name)
28
-
29
- if target_file_content.include?(transformed_content)
30
- puts "No need to update '#{transformed_file_name}'. It already has '#{transformed_content}'."
31
- else
32
- new_target_file_content = []
33
- target_file_content.split("\n").each do |line|
34
- if /#{Regexp.escape(transform_hook)}\s*$/.match?(line)
35
-
36
- if add_before
37
- new_target_file_content << "#{line} #{add_before}"
38
- else
39
- unless options[:prepend]
40
- new_target_file_content << line
41
- end
42
- end
43
-
44
- # get leading whitespace.
45
- line =~ /^(\s*).*#{Regexp.escape(transform_hook)}.*/
46
- leading_whitespace = $1
47
- new_target_file_content << "#{leading_whitespace}#{" " if increase_indent}#{transformed_content}"
48
-
49
- new_target_file_content << "#{leading_whitespace}#{add_after}" if add_after
50
-
51
- if options[:prepend]
52
- new_target_file_content << line
53
- end
54
- else
55
- new_target_file_content << line
56
- end
57
- end
58
-
59
- puts "Updating '#{transformed_file_name}'."
60
-
61
- File.write(transformed_file_name, new_target_file_content.join("\n") + "\n")
62
- end
63
- end
4
+ require "scaffolding"
5
+ require "scaffolding/transformer"
6
+ require "scaffolding/class_names_transformer"
7
+ require "scaffolding/oauth_providers"
8
+ require "scaffolding/routes_file_manipulator"
64
9
 
65
10
  # filter out options.
66
11
  argv = []
@@ -78,6 +23,11 @@ ARGV.each do |arg|
78
23
  end
79
24
  end
80
25
 
26
+ def standard_protip
27
+ puts "🏆 Protip: Commit your other changes before running Super Scaffolding so it's easy to undo if you (or we) make any mistakes."
28
+ puts "If you do that, you can reset to your last commit state by using `git checkout .` and `git clean -d -f` ."
29
+ end
30
+
81
31
  def check_required_options_for_attributes(scaffolding_type, attributes, child, parent = nil)
82
32
  attributes.each do |attribute|
83
33
  parts = attribute.split(":")
@@ -132,11 +82,9 @@ def show_usage
132
82
  puts ""
133
83
  puts "Supported types of scaffolding:"
134
84
  puts ""
135
- puts " crud"
136
- puts " crud-field"
137
- puts " join-model"
138
- puts " oauth-provider"
139
- puts " breadcrumbs"
85
+ BulletTrain::SuperScaffolding.scaffolders.each do |key, _|
86
+ puts " #{key}"
87
+ end
140
88
  puts ""
141
89
  puts "Try \`bin/super-scaffold [type]` for usage examples.".blue
142
90
  puts ""
@@ -145,394 +93,16 @@ end
145
93
  # grab the _type_ of scaffold we're doing.
146
94
  scaffolding_type = argv.shift
147
95
 
148
- # if we're doing the classic super scaffolding ..
149
- if scaffolding_type == "crud"
150
-
151
- unless argv.count >= 3
152
- puts ""
153
- puts "🚅 usage: bin/super-scaffold crud <Model> <ParentModel[s]> <attribute:type> <attribute:type> ..."
154
- puts ""
155
- puts "E.g. a Team has many Sites with some attributes:"
156
- puts " rails g model Site team:references name:string url:text"
157
- puts " bin/super-scaffold crud Site Team name:string url:text"
158
- puts ""
159
- puts "E.g. a Section belongs to a Page, which belongs to a Site, which belongs to a Team:"
160
- puts " rails g model Section page:references title:text body:text"
161
- puts " bin/super-scaffold crud Section Page,Site,Team title:text body:text"
162
- puts ""
163
- puts "E.g. an Image belongs to either a Page or a Site:"
164
- puts " Doable! See https://bit.ly/2NvO8El for a step by step guide."
165
- puts ""
166
- puts "E.g. Pages belong to a Site and are sortable via drag-and-drop:"
167
- puts " rails g model Page site:references name:string path:text"
168
- puts " bin/super-scaffold crud Page Site,Team name:text path:text --sortable"
169
- puts ""
170
- puts "🏆 Protip: Commit your other changes before running Super Scaffolding so it's easy to undo if you (or we) make any mistakes."
171
- puts "If you do that, you can reset to your last commit state by using `git checkout .` and `git clean -d -f` ."
172
- puts ""
173
- puts "Give it a shot! Let us know if you have any trouble with it! ✌️"
174
- puts ""
175
- exit
176
- end
177
-
178
- child = argv[0]
179
- parents = argv[1] ? argv[1].split(",") : []
180
- parents = parents.map(&:classify).uniq
181
- parent = parents.first
182
-
183
- unless parents.include?("Team")
184
- raise "Parents for #{child} should trace back to the Team model, but Team wasn't provided. Please confirm that all of the parents tracing back to the Team model are present and try again.\n" +
185
- "E.g.:\n" +
186
- "rails g model Section page:references title:text body:text\n" +
187
- "bin/super-scaffold crud Section Page,Site,Team title:text body:text\n"
188
- end
189
-
190
- # get all the attributes.
191
- attributes = argv[2..-1]
192
-
193
- check_required_options_for_attributes(scaffolding_type, attributes, child, parent)
194
-
195
- transformer = Scaffolding::Transformer.new(child, parents, @options)
196
- transformer.scaffold_crud(attributes)
197
-
198
- transformer.additional_steps.each_with_index do |additional_step, index|
199
- color, message = additional_step
200
- puts ""
201
- puts "#{index + 1}. #{message}".send(color)
202
- end
203
- puts ""
204
-
205
- elsif scaffolding_type == "crud-field"
206
-
207
- unless argv.count >= 2
208
- puts ""
209
- puts "🚅 usage: bin/super-scaffold crud-field <Model> <attribute:type> <attribute:type> ... [options]"
210
- puts ""
211
- puts "E.g. add a description and body to Pages:"
212
- puts " rails g migration add_description_etc_to_pages description:text body:text"
213
- puts " bin/super-scaffold crud-field Page description:text body:text"
214
- puts ""
215
- puts "Options:"
216
- puts ""
217
- puts " --skip-table: Only add to the new/edit form and show view."
218
- puts ""
219
- exit
220
- end
221
-
222
- # We pass this value to parents to create a new Scaffolding::Transformer because
223
- # we don't actually need knowledge of the parent to add the new field.
224
- parents = [""]
225
- child = argv[0]
226
-
227
- # get all the attributes.
228
- attributes = argv[1..-1]
229
-
230
- check_required_options_for_attributes(scaffolding_type, attributes, child)
231
-
232
- transformer = Scaffolding::Transformer.new(child, parents, @options)
233
- transformer.add_attributes_to_various_views(attributes, type: :crud_field)
234
-
235
- transformer.additional_steps.uniq.each_with_index do |additional_step, index|
236
- color, message = additional_step
237
- puts ""
238
- puts "#{index + 1}. #{message}".send(color)
239
- end
240
- puts ""
241
-
242
- elsif scaffolding_type == "join-model"
243
-
244
- unless argv.count >= 3
245
- puts ""
246
- puts "🚅 usage: bin/super-scaffold join-model <JoinModel> <left_association> <right_association>"
247
- puts ""
248
- puts "E.g. Add project-specific tags to a project:"
249
- puts ""
250
- puts " Given the following example models:".blue
251
- puts ""
252
- puts " rails g model Project team:references name:string description:text"
253
- puts " bin/super-scaffold crud Project Team name:text_field description:trix_editor"
254
- puts ""
255
- puts " rails g model Projects::Tag team:references name:string"
256
- puts " bin/super-scaffold crud Projects::Tag Team name:text_field"
257
- puts ""
258
- puts " 1️⃣ Use the standard Rails model generator to generate the join model:".blue
259
- puts ""
260
- puts " rails g model Projects::AppliedTag project:references tag:references"
261
- puts ""
262
- puts " 👋 Don't run migrations yet! Sometimes Super Scaffolding updates them for you.".yellow
263
- puts ""
264
- puts " 2️⃣ Use `join-model` scaffolding to prepare the join model for use in `crud-field` scaffolding:".blue
265
- puts ""
266
- puts " bin/super-scaffold join-model Projects::AppliedTag project_id[class_name=Project] tag_id[class_name=Projects::Tag]"
267
- puts ""
268
- puts " 3️⃣ Now you can use `crud-field` scaffolding to actually add the field to the form of the parent model:".blue
269
- puts ""
270
- puts " bin/super-scaffold crud-field Project tag_ids:super_select[class_name=Projects::Tag]"
271
- puts ""
272
- puts " 👋 Heads up! There will be one follow-up step output by this command that you need to take action on."
273
- puts ""
274
- puts " 4️⃣ Now you can run your migrations.".blue
275
- exit
276
- end
277
-
278
- child = argv[0]
279
- primary_parent = argv[1].split("class_name=").last.split(",").first.split("]").first
280
- secondary_parent = argv[2].split("class_name=").last.split(",").first.split("]").first
281
-
282
- # There should only be two attributes.
283
- attributes = [argv[1], argv[2]]
284
-
285
- # Pretend we're doing a `super_select` scaffolding because it will do the correct thing.
286
- attributes = attributes.map { |attribute| attribute.gsub("\[", ":super_select\[") }
287
- attributes = attributes.map { |attribute| attribute.gsub("\]", ",required\]") }
288
-
289
- transformer = Scaffolding::Transformer.new(child, [primary_parent], @options)
290
-
291
- # We need this transformer to reflect on the class names _just_ between e.g. `Project` and `Projects::Tag`, without the join model.
292
- has_many_through_transformer = Scaffolding::Transformer.new(secondary_parent, [primary_parent], @options)
293
-
294
- # We need this transformer to reflect on the association between `Projects::Tag` and `Projects::AppliedTag` backwards.
295
- inverse_transformer = Scaffolding::Transformer.new(child, [secondary_parent], @options)
296
-
297
- # We need this transformer to reflect on the class names _just_ between e.g. `Projects::Tag` and `Project`, without the join model.
298
- inverse_has_many_through_transformer = Scaffolding::Transformer.new(primary_parent, [secondary_parent], @options)
299
-
300
- # However, for the first attribute, we actually don't need the scope validator (and can't really implement it).
301
- attributes[0] = attributes[0].gsub("\]", ",unscoped\]")
302
-
303
- has_many_through_association = has_many_through_transformer.transform_string("completely_concrete_tangible_things")
304
- source = transformer.transform_string("absolutely_abstract_creative_concept.valid_$HAS_MANY_THROUGH_ASSOCIATION")
305
- source.gsub!("$HAS_MANY_THROUGH_ASSOCIATION", has_many_through_association)
306
-
307
- # For the second one, we don't want users to have to define the list of valid options in the join model, so we do this:
308
- attributes[1] = attributes[1].gsub("\]", ",source=#{source}\]")
309
-
310
- # This model hasn't been crud scaffolded, so a bunch of views are skipped here, but that's OK!
311
- # It does what we need on the files that exist.
312
- transformer.add_scaffolding_hooks_to_model
313
-
314
- transformer.suppress_could_not_find = true
315
- transformer.add_attributes_to_various_views(attributes, type: :crud_field)
316
- transformer.suppress_could_not_find = false
317
-
318
- # Add the `has_many ... through:` association in both directions.
319
- transformer.add_has_many_through_associations(has_many_through_transformer)
320
- inverse_transformer.add_has_many_through_associations(inverse_has_many_through_transformer)
321
-
322
- additional_steps = (transformer.additional_steps + has_many_through_transformer.additional_steps + inverse_transformer.additional_steps + inverse_has_many_through_transformer.additional_steps).uniq
323
-
324
- additional_steps.each_with_index do |additional_step, index|
325
- color, message = additional_step
326
- puts ""
327
- puts "#{index + 1}. #{message}".send(color)
328
- end
329
- puts ""
330
-
331
- elsif scaffolding_type == "breadcrumbs"
332
-
333
- unless argv.count == 2
334
- puts ""
335
- puts "🚅 usage: bin/super-scaffold breadcrumbs <Model> <ParentModel[s]>"
336
- puts ""
337
- puts "Heads up! You only need to use this if you generated your views before the new Bullet Train breadcrumbs implementation came into effect.".green
338
- puts ""
339
- puts "E.g. create updated breadcrumbs for Pages:"
340
- puts " bin/super-scaffold breadcrumbs Page Site,Team"
341
- puts ""
342
- puts "When Super Scaffolding breadcrumbs, you have to specify the entire path of the immediate parent back to Team."
343
- puts ""
344
- exit
345
- end
346
-
347
- child = argv[0]
348
- parents = argv[1] ? argv[1].split(",") : []
349
- parents = parents.map(&:classify).uniq
350
- parent = parents.first
351
-
352
- unless parents.include?("Team")
353
- raise "Parents for #{child} should trace back to the Team model, but Team wasn't provided. Please confirm that all of the parents tracing back to the Team model are present and try again.\n" +
354
- "E.g.:\n" +
355
- "bin/super-scaffold breadcrumbs Page Site,Team\n"
356
- end
357
-
358
- # get all the attributes.
359
- transformer = Scaffolding::Transformer.new(child, parents, @options)
360
- transformer.scaffold_new_breadcrumbs(child, parents)
361
-
362
- elsif scaffolding_type == "oauth-provider"
363
-
364
- unless argv.count >= 5
365
- puts ""
366
- puts "🚅 usage: bin/super-scaffold oauth-provider <omniauth_gem> <gems_provider_name> <our_provider_name> <PROVIDER_API_KEY_IN_ENV> <PROVIDER_API_SECRET_IN_ENV> [options]"
367
- puts ""
368
- puts "E.g. what we'd do to start Stripe off (if we didn't already do it):"
369
- puts " bin/super-scaffold oauth-provider omniauth-stripe-connect stripe_connect Oauth::StripeAccount STRIPE_CLIENT_ID STRIPE_SECRET_KEY --icon=ti-money"
370
- puts ""
371
- puts "E.g. what we actually did to start Shopify off:"
372
- puts " bin/super-scaffold oauth-provider omniauth-shopify-oauth2 shopify Oauth::ShopifyAccount SHOPIFY_API_KEY SHOPIFY_API_SECRET_KEY --icon=ti-shopping-cart"
373
- puts ""
374
- puts "Options:"
375
- puts ""
376
- puts " --icon={ti-*}: Specify an icon."
377
- puts ""
378
- puts "For a list of readily available provider strategies, see https://github.com/omniauth/omniauth/wiki/List-of-Strategies ."
379
- puts ""
380
- exit
381
- end
382
-
383
- _, omniauth_gem, gems_provider_name, our_provider_name, api_key, api_secret = *ARGV
384
-
385
- unless match = our_provider_name.match(/Oauth::(.*)Account/)
386
- puts "\n🚨 Your provider name must match the pattern of `Oauth::{Name}Account`, e.g. `Oauth::StripeAccount`\n".red
387
- return
388
- end
389
-
390
- options = {
391
- omniauth_gem: omniauth_gem,
392
- gems_provider_name: gems_provider_name,
393
- our_provider_name: match[1],
394
- api_key: api_key,
395
- api_secret: api_secret
396
- }
397
-
398
- unless File.exist?(oauth_transform_string("./app/models/oauth/stripe_account.rb", options)) &&
399
- File.exist?(oauth_transform_string("./app/models/integrations/stripe_installation.rb", options)) &&
400
- File.exist?(oauth_transform_string("./app/models/webhooks/incoming/oauth/stripe_account_webhook.rb", options))
401
- puts ""
402
- puts oauth_transform_string("🚨 Before doing the actual Super Scaffolding, you'll need to generate the models like so:", options).red
403
- puts ""
404
- puts oauth_transform_string(" rails g model Oauth::StripeAccount uid:string data:jsonb user:references", options).red
405
- puts oauth_transform_string(" rails g model Integrations::StripeInstallation team:references oauth_stripe_account:references name:string", options).red
406
- puts oauth_transform_string(" rails g model Webhooks::Incoming::Oauth::StripeAccountWebhook data:jsonb processed_at:datetime verified_at:datetime oauth_stripe_account:references", options).red
407
- puts ""
408
- puts "However, don't do the `rake db:migrate` until after you re-run Super Scaffolding, as it will need to update some settings in those migrations.".red
409
- puts ""
410
- return
411
- end
412
-
413
- icon_name = nil
414
- if @options["icon"].present?
415
- icon_name = @options["icon"]
416
- else
417
- puts "OK, great! Let's do this! By default providers will appear with a dollar symbol,"
418
- puts "but after you hit enter I'll open a page where you can view other icon options."
419
- puts "When you find one you like, hover your mouse over it and then come back here and"
420
- puts "and enter the name of the icon you want to use."
421
- response = STDIN.gets.chomp
422
- `open http://light.pinsupreme.com/icon_fonts_themefy.html`
423
- puts ""
424
- puts "Did you find an icon you wanted to use? Enter the name here or hit enter to just"
425
- puts "use the dollar symbol:"
426
- icon_name = STDIN.gets.chomp
427
- puts ""
428
- unless icon_name.length > 0 || icon_name.downcase == "y"
429
- icon_name = "icon-puzzle"
430
- end
431
- end
432
-
433
- options[:icon] = icon_name
434
-
435
- [
436
-
437
- # User OAuth.
438
- "./app/models/oauth/stripe_account.rb",
439
- "./app/models/webhooks/incoming/oauth/stripe_account_webhook.rb",
440
- "./app/controllers/account/oauth/stripe_accounts_controller.rb",
441
- "./app/controllers/webhooks/incoming/oauth/stripe_account_webhooks_controller.rb",
442
- "./app/views/account/oauth/stripe_accounts",
443
- "./test/models/oauth/stripe_account_test.rb",
444
- "./test/factories/oauth/stripe_accounts.rb",
445
- "./config/locales/en/oauth/stripe_accounts.en.yml",
446
- "./app/views/devise/shared/oauth/_stripe.html.erb",
447
-
448
- # Team Integration.
449
- "./app/models/integrations/stripe_installation.rb",
450
- # './app/serializers/api/v1/integrations/stripe_installation_serializer.rb',
451
- "./app/controllers/account/integrations/stripe_installations_controller.rb",
452
- "./app/views/account/integrations/stripe_installations",
453
- "./test/models/integrations/stripe_installation_test.rb",
454
- "./test/factories/integrations/stripe_installations.rb",
455
- "./config/locales/en/integrations/stripe_installations.en.yml",
456
-
457
- # Webhook.
458
- "./app/models/webhooks/incoming/oauth/stripe_account_webhook.rb",
459
- "./app/controllers/webhooks/incoming/oauth/stripe_account_webhooks_controller.rb"
460
-
461
- ].each do |name|
462
- if File.directory?(name)
463
- oauth_scaffold_directory(name, options)
464
- else
465
- oauth_scaffold_file(name, options)
466
- end
467
- end
468
-
469
- oauth_scaffold_add_line_to_file("./app/views/devise/shared/_oauth.html.erb", "<%= render 'devise/shared/oauth/stripe', verb: verb if stripe_enabled? %>", "<%# 🚅 super scaffolding will insert new oauth providers above this line. %>", options, prepend: true)
470
- oauth_scaffold_add_line_to_file("./app/views/account/users/edit.html.erb", "<%= render 'account/oauth/stripe_accounts/index', context: @user, stripe_accounts: @user.oauth_stripe_accounts if stripe_enabled? %>", "<% # 🚅 super scaffolding will insert new oauth providers above this line. %>", options, prepend: true)
471
- oauth_scaffold_add_line_to_file("./config/initializers/devise.rb", "config.omniauth :stripe_connect, ENV['STRIPE_CLIENT_ID'], ENV['STRIPE_SECRET_KEY'], {\n ## specify options for your oauth provider here, e.g.:\n # scope: 'read_products,read_orders,write_content',\n }\n", "# 🚅 super scaffolding will insert new oauth providers above this line.", options, prepend: true)
472
- oauth_scaffold_add_line_to_file("./app/controllers/account/oauth/omniauth_callbacks_controller.rb", "def stripe_connect\n callback(\"Stripe\", team_id_from_env)\n end\n", "# 🚅 super scaffolding will insert new oauth providers above this line.", options, prepend: true)
473
- oauth_scaffold_add_line_to_file("./app/models/team.rb", "has_many :integrations_stripe_installations, class_name: 'Integrations::StripeInstallation', dependent: :destroy if stripe_enabled?", "# 🚅 add oauth providers above.", options, prepend: true)
474
- oauth_scaffold_add_line_to_file("./app/models/user.rb", "has_many :oauth_stripe_accounts, class_name: 'Oauth::StripeAccount' if stripe_enabled?", "# 🚅 add oauth providers above.", options, prepend: true)
475
- oauth_scaffold_add_line_to_file("./config/locales/en/oauth.en.yml", "stripe_connect: Stripe", "# 🚅 super scaffolding will insert new oauth providers above this line.", options, prepend: true)
476
- oauth_scaffold_add_line_to_file("./app/views/account/shared/_menu.html.erb", "<%= render 'account/integrations/stripe_installations/menu_item' if stripe_enabled? %>", "<%# 🚅 super scaffolding will insert new oauth providers above this line. %>", options, prepend: true)
477
- oauth_scaffold_add_line_to_file("./config/routes.rb", "resources :stripe_account_webhooks if stripe_enabled?", "# 🚅 super scaffolding will insert new oauth provider webhooks above this line.", options, prepend: true)
478
- oauth_scaffold_add_line_to_file("./config/routes.rb", "resources :stripe_accounts if stripe_enabled?", "# 🚅 super scaffolding will insert new oauth providers above this line.", options, prepend: true)
479
- oauth_scaffold_add_line_to_file("./config/routes.rb", "resources :stripe_installations if stripe_enabled?", "# 🚅 super scaffolding will insert new integration installations above this line.", options, prepend: true)
480
- oauth_scaffold_add_line_to_file("./Gemfile", "gem 'omniauth-stripe-connect'", "# 🚅 super scaffolding will insert new oauth providers above this line.", options, prepend: true)
481
- oauth_scaffold_add_line_to_file("./lib/bullet_train.rb", "def stripe_enabled?\n ENV['STRIPE_CLIENT_ID'].present? && ENV['STRIPE_SECRET_KEY'].present?\nend\n", "# 🚅 super scaffolding will insert new oauth providers above this line.", options, prepend: true)
482
- oauth_scaffold_add_line_to_file("./lib/bullet_train.rb", "stripe_enabled?,", "# 🚅 super scaffolding will insert new oauth provider checks above this line.", options, prepend: true)
483
- oauth_scaffold_add_line_to_file("./app/models/ability.rb", "if stripe_enabled?
484
- can [:read, :create, :destroy], Oauth::StripeAccount, user_id: user.id
485
- can :manage, Integrations::StripeInstallation, team_id: user.team_ids
486
- can :destroy, Integrations::StripeInstallation, oauth_stripe_account: {user_id: user.id}
487
- end
488
- ", "# 🚅 super scaffolding will insert any new oauth providers above.", options, prepend: true)
489
-
490
- # find the database migration that defines this relationship.
491
- migration_file_name = `grep "create_table #{oauth_transform_string(":oauth_stripe_accounts", options)}" db/migrate/*`.split(":").first
492
- legacy_replace_in_file(migration_file_name, "null: false", "null: true")
493
-
494
- migration_file_name = `grep "create_table #{oauth_transform_string(":integrations_stripe_installations", options)}" db/migrate/*`.split(":").first
495
- legacy_replace_in_file(migration_file_name,
496
- oauth_transform_string("t.references :oauth_stripe_account, null: false, foreign_key: true", options),
497
- oauth_transform_string('t.references :oauth_stripe_account, null: false, foreign_key: true, index: {name: "index_stripe_installations_on_oauth_stripe_account_id"}', options))
498
-
499
- migration_file_name = `grep "create_table #{oauth_transform_string(":webhooks_incoming_oauth_stripe_account_webhooks", options)}" db/migrate/*`.split(":").first
500
- legacy_replace_in_file(migration_file_name, "null: false", "null: true")
501
- legacy_replace_in_file(migration_file_name, "foreign_key: true", 'foreign_key: true, index: {name: "index_stripe_webhooks_on_oauth_stripe_account_id"}')
502
-
503
- puts ""
504
- puts "🎉"
505
- puts ""
506
- puts "You'll probably need to `bundle install`.".green
507
- puts ""
508
- puts "If the OAuth provider asks you for some whitelisted callback URLs, the URL structure for those is as so:"
509
- puts ""
510
- path = "users/auth/stripe_connect/callback"
511
- puts oauth_transform_string(" https://yourdomain.co/#{path}", options)
512
- puts oauth_transform_string(" https://yourtunnel.ngrok.io/#{path}", options)
513
- puts oauth_transform_string(" http://localhost:3000/#{path}", options)
514
- puts ""
515
- puts "If you're able to specify an endpoint to receive webhooks from this provider, use this URL:"
516
- puts ""
517
- path = "webhooks/incoming/oauth/stripe_account_webhooks"
518
- puts oauth_transform_string(" https://yourdomain.co/#{path}", options)
519
- puts oauth_transform_string(" https://yourtunnel.ngrok.io/#{path}", options)
520
- puts oauth_transform_string(" http://localhost:3000/#{path}", options)
521
- puts ""
522
- puts ""
523
- puts "If you'd like to edit how your Bullet Train application refers to this provider, just edit the locale file at `config/locales/en/oauth.en.yml`."
524
- puts ""
525
- puts "And finally, if you need to specify any custom authorizations or options for your OAuth integration with this provider, you can configure those in `config/initializers/devise.rb`."
526
- puts ""
527
-
96
+ if BulletTrain::SuperScaffolding.scaffolders.include?(scaffolding_type)
97
+ scaffolder = BulletTrain::SuperScaffolding.scaffolders[scaffolding_type].constantize
98
+ scaffolder.new(argv, @options).run
528
99
  elsif argv.count > 1
529
-
530
100
  puts ""
531
101
  puts "👋"
532
102
  puts "The command line options for Super Scaffolding have changed slightly:".yellow
533
103
  puts "To use the original Super Scaffolding that you know and love, use the `crud` option.".yellow
534
- show_usage
535
104
 
105
+ show_usage
536
106
  else
537
107
  if ARGV.first.present?
538
108
  puts ""
@@ -106,6 +106,18 @@ class Scaffolding::Transformer
106
106
  decode_double_replacement_fix(string)
107
107
  end
108
108
 
109
+ def resolve_template_path(file)
110
+ # Figure out the actual location of the file.
111
+ # Originally all the potential source files were in the repository alongside the application.
112
+ # Now the files could be provided by an included Ruby gem, so we allow those Ruby gems to register their base
113
+ # path and then we check them in order to see which template we should use.
114
+ BulletTrain::SuperScaffolding.template_paths.reverse.map do |base_path|
115
+ base_path = Pathname.new(base_path)
116
+ resolved_path = base_path.join(file).to_s
117
+ File.exists?(resolved_path) ? resolved_path : file
118
+ end.compact.first
119
+ end
120
+
109
121
  def get_transformed_file_content(file)
110
122
  transformed_file_content = []
111
123
 
@@ -115,7 +127,7 @@ class Scaffolding::Transformer
115
127
  parents_to_repeat_for = []
116
128
  gathered_lines_for_repeating = nil
117
129
 
118
- File.open(file).each_line do |line|
130
+ File.open(resolve_template_path(file)).each_line do |line|
119
131
  if line.include?("# 🚅 skip when scaffolding.")
120
132
  next
121
133
  end
@@ -213,9 +225,9 @@ class Scaffolding::Transformer
213
225
  puts "Proceeding to generate '#{transformed_directory_name}'."
214
226
  end
215
227
 
216
- Dir.foreach(directory) do |file|
228
+ Dir.foreach(resolve_template_path(directory)) do |file|
217
229
  file = "#{directory}/#{file}"
218
- unless File.directory?(file)
230
+ unless File.directory?(resolve_template_path(file))
219
231
  scaffold_file(file)
220
232
  end
221
233
  end
@@ -1175,7 +1187,7 @@ class Scaffolding::Transformer
1175
1187
  end
1176
1188
 
1177
1189
  files.each do |name|
1178
- if File.directory?(name)
1190
+ if File.directory?(resolve_template_path(name))
1179
1191
  scaffold_directory(name)
1180
1192
  else
1181
1193
  scaffold_file(name)
data/lib/scaffolding.rb CHANGED
@@ -1,8 +1,2 @@
1
1
  module Scaffolding
2
2
  end
3
-
4
- require_relative "scaffolding/oauth_providers"
5
- require_relative "scaffolding/transformer"
6
- require_relative "scaffolding/class_names_transformer"
7
- require_relative "scaffolding/routes_file_manipulator"
8
- require_relative "scaffolding/runner"
@@ -1,4 +1,12 @@
1
- # desc "Explaining what the task does"
2
- # task :bullet_train_super_scaffolding do
3
- # # Task goes here
4
- # end
1
+ namespace :bullet_train do
2
+ desc "Next-level code generation"
3
+ task :super_scaffolding, [:all_options] => :environment do |t, arguments|
4
+ ARGV.pop while ARGV.any?
5
+
6
+ arguments[:all_options]&.split&.each do |argument|
7
+ ARGV.push(argument)
8
+ end
9
+
10
+ BulletTrain::SuperScaffolding::Runner.new.run
11
+ end
12
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet_train-super_scaffolding
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-31 00:00:00.000000000 Z
11
+ date: 2022-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -38,6 +38,11 @@ files:
38
38
  - config/routes.rb
39
39
  - lib/bullet_train/super_scaffolding.rb
40
40
  - lib/bullet_train/super_scaffolding/engine.rb
41
+ - lib/bullet_train/super_scaffolding/scaffolder.rb
42
+ - lib/bullet_train/super_scaffolding/scaffolders/crud_field_scaffolder.rb
43
+ - lib/bullet_train/super_scaffolding/scaffolders/crud_scaffolder.rb
44
+ - lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb
45
+ - lib/bullet_train/super_scaffolding/scaffolders/oauth_provider_scaffolder.rb
41
46
  - lib/bullet_train/super_scaffolding/version.rb
42
47
  - lib/scaffolding.rb
43
48
  - lib/scaffolding/class_names_transformer.rb