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