bullet_train-super_scaffolding 1.0.2 → 1.0.6

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