-
Notifications
You must be signed in to change notification settings - Fork 94
Support controllers_path generator option for controller and manifest tasks. #152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
lib/tasks/stimulus_tasks.rake
Outdated
| end | ||
|
|
||
| def controllers_path | ||
| js_root = Rails.application.config.generators.options.dig(:stimulus, :js_root) || "app/javascript" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't js_root always be set, given that you have a default for the class_option? If so, I don't think we need to repeat the default here. And in fact, I'd just inline the entire call in the Rails.root.join.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love the idea of using the class_option, however the value in Rails.application.config.generators is not set on the class without instantiating an instance with the options. I actually quite like this approach as the default is only in one place:
def controllers_path
Rails.root.join(StimulusGenerator.new(['stimulus'], generator_options, {}).options.js_root, "controllers")
end
def generator_options
Rails.application.config.generators.options.dig(:stimulus)
endI also had to add the following require statement to load StimulusGenerator.
# stimulus_tasks.rake
require "generators/stimulus/stimulus_generator"
# This worked in the rake task, but perhaps more appropriate in stimulus_generator.rb
# Let me know if its better to have them in the rake task instead of the generator.
require 'rails/generators'
require 'rails/generators/actions'
require "rails/generators/named_base" # already presentThis also eliminates needing to add :environment to the rake tasks for a reason I do not fully grok, but I'm totally ok with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed up this change. LMK what you think.
However this pans out, thanks for the code review 👍
| source_root File.expand_path("templates", __dir__) | ||
|
|
||
| class_option :skip_manifest, type: :boolean, default: false, desc: "Don't update the stimulus manifest" | ||
| class_option :js_root, type: :string, default: 'app/javascript', desc: "Root path for javascript files" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Always use " instead of ' for strings.
484cc45 to
66187f7
Compare
lib/tasks/stimulus_tasks.rake
Outdated
|
|
||
| task :display do | ||
| puts Stimulus::Manifest.generate_from(Rails.root.join("app/javascript/controllers")) | ||
| Stimulus::Manifest.generate_from(Stimulus::Tasks.controllers_path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why remove the puts here? That would remove the actual display of the Manifest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Habit because I'm usually beaten with a stick for leaving puts in code, but realize that was there to begin with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
puts for debugging is definitely not something you want to ship, but this puts is in service of what the task does: Display the manifest to the user on the terminal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dhh What are your thoughts adding a puts to stimulus:manifest:update to avoid surprise when js_root is not default?
desc "Update the Stimulus manifest (will overwrite controllers/index.js)"
task :update do
puts "Updating stimulus manifest in #{Stimulus::Tasks.controllers_path.relative_path_from(Rails.root)}"
manifest = Stimulus::Manifest.generate_from(Stimulus::Tasks.controllers_path)
....➜ rails stimulus:manifest:update 08:55:33
Updating stimulus manifest in app/frontend/controllers
lib/tasks/stimulus_tasks.rake
Outdated
| Rails.root.join(StimulusGenerator.new(["stimulus"], generator_options, {}).options.js_root, "controllers") | ||
| end | ||
|
|
||
| def generator_options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this isn't called anywhere else, I'd just inline it in controllers_path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if there's line length limit enforced but we're at 154 as a oneliner:
def controllers_path
Rails.root.join(StimulusGenerator.new(["stimulus"], Rails.application.config.generators.options.dig(:stimulus), {}).options.js_root, "controllers")
endThis feels ok to me.
def controllers_path
generator_options = Rails.application.config.generators.options.dig(:stimulus)
Rails.root.join(StimulusGenerator.new(["stimulus"], generator_options, {}).options.js_root, "controllers")
endI do like this because the arguments to .join pop and isnt' any longer than line 8.
def controllers_path
Rails.root.join(
StimulusGenerator.new(["stimulus"], Rails.application.config.generators.options.dig(:stimulus), {}).options.js_root,
"controllers"
)
endNot technically inline but easier to work with (e.g. debug) assigning generator_options since it's a pretty long method chain.
def controllers_path
generator_options = Rails.application.config.generators.options.dig(:stimulus)
Rails.root.join(
StimulusGenerator.new(["stimulus"], generator_options, {}).options.js_root,
"controllers"
)
endWanted to provide some options for you to view. To avoid back and forth I'll push up option 4 since it's easiest on the eyes and avoids the super long method chain. Happy to change if you prefer one of the others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like:
def controllers_path
generator = StimulusGenerator.new(["stimulus"], Rails.application.config.generators.options.dig(:stimulus), {})
Rails.root.join generator.options.js_root, "controllers"
end|
Made some changes. Think we probably need to add a test for this, though. |
|
Thanks for the updates. I've updated the title and original post to reference How can I avoid Two follow up questions:
|
|
I've fixed the test issue. Merge with main, and then you can run bin/test. Yes, we should document this. Not sure what you mean about observing |
The templates use by |
|
Don't think that matters. Since this is being run on "rails new" before you even get a chance to change the setting. I mean, of course, if you opted out of Hotwire, and then added it back later, then ok. But seems unlikely. |
|
Got side tracked with life but I should have some tests up by before next week. |
f761714 to
f057e18
Compare
|
@dhh Pushed up some tests and added validations for blank and absolute controller path ( blank path becomes absolute because we concatenate with I could also see using default when blank and converting absolute paths to relative by removing any leading file system separators. It's a trade off between strictness and ergonomics. I personally prefer the latter. As far as documentation, I only updated USAGE to give an example of controllers-path. I feel like the README should have a section detailing generator configuration that includes |
| desc "Update the Stimulus manifest (will overwrite controllers/index.js)" | ||
| task :update do | ||
| Stimulus::Manifest.write_index_from(Rails.root.join("app/javascript/controllers")) | ||
| task update: :environment do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to add the environment task as a dependency? It doesn't seem necessary.
| end | ||
|
|
||
| def controllers_root | ||
| Rails.root.join \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a little hard to read and still too long in my opinion, I believe the suggestion from @dhh should be good
def controllers_path
generator = StimulusGenerator.new(["stimulus"], Rails.application.config.generators.options.dig(:stimulus), {})
Rails.root.join generator.options.js_root, "controllers"
end
This PR aims to support paths other than
app/javascriptfor the root path in generator and manifest tasks. Similar attempts have been made/requested, but this PR usesconfig.generatorsinstead of an initializer to setcontrollers_path. A small drawback is the manifest tasks load:environmentto access configuration fromapplication.rb, but it plays nicely with generator help message and doesn't pollute theStimulusnamespace. Here's the usage:I like using the generator because it keeps the controller consistent with the
// Connects to data-controller=..comment and naming conventions which get tricky with camelCase, under_score and dash-erized in play. Because the path is hard coded in the generator, the only option is to monkey patch it. Monkey patching the generator in my project made it difficult to reference the template from inside the gem requiring me to copy template as well.If there's support for this option I'd be happy to proceed with updating docs and tests, although I had a pretty tough time getting the suite to run locally.
Thank you for considering this PR.