Coder Social home page Coder Social logo

packs-rails's People

Contributors

ashleywillard avatar euglena1215 avatar exterm avatar geesu avatar imactia avatar jarredhawkins avatar julianpasquale avatar kpumuk avatar marcreynolds avatar matiaseche avatar morissetcl avatar ngan avatar oleg-vinted avatar olleolleolle avatar perryqh avatar professor avatar schoblaska avatar sgringwe avatar shageman avatar timfsw avatar yesthesoup avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

packs-rails's Issues

Add translations to packs

Hi! I am having an issue with my translations inside my pack.

I have a pack with some attribute translations inside packs/my_pack/config/locales/models/entity.rb.
The only way I have managed to make it work is adding the following line inside config/application.rb:

config.i18n.load_path += Dir[Rails.root.join('packs', '**', 'config', 'locales', '**', '*.yml').to_s]

This looks like something that should be done inside the gem, doesn't it?
I managed to make it work adding the following to the gem:

# lib/packs/rails/integrations/rails.rb
...
def inject_paths
  Packs.all.reject(&:is_gem?).each do |pack|
    Packs::Rails.config.paths.each do |path|
      @app.paths[path] << pack.relative_path.join(path).to_s
    end
  end
  i18n_translations
end

private

def i18n_translations
  if @app.config.respond_to?(:i18n)
    @app.config.i18n.load_path += Dir[::Rails.root.join('packs', '**', 'config', 'locales', '**', '*.yml').to_s]
  end
end

Is this something that should be added or not? If it is I can create a PR 😄

Trouble with spring after moving / renaming packages?

We're running into situations where packwerk check or packs check returns incorrect results in some situations, like after changing branches. I believe that this is due to an interaction (or lack thereof) between packs-rails and spring.

Is anyone else seeing this problem?

I just (seemingly) fixed this on a project I am working on.

It looks like the explanation is the following:

packs-rails sets up autoload paths by detecting package.ymls. So moving packs around, renaming them, deleting packs or creating new ones leads to the autoload paths being changed. The application has to be restarted for that. Which means spring needs to watch all the package.ymls. I just did a Dir["packs/**/package.yml"],each { |f| Spring.watch(f) } to fix it for us.

But if this is the actual explanation, everybody setting up packs-rails naively should have this problem, and I haven't been hearing much about it. Does this ring a bell for anyone?

If this is actually a common problem, maybe we can have packs-rails set up the spring watches implicitly?

RSpec integration behaves differently than stimpack

I would like to propose changing packs-rails' RSpec integration to operate a little more deterministically, and I think the way to do that with the smallest change is to add a #sort to the collection of package paths returned by Packs.all.map in

def initialize
# This is the list of directories RSpec was told to run.
to_run = ::RSpec.configuration.instance_variable_get(:@files_or_directories_to_run)
default_path = ::RSpec.configuration.default_path
if to_run == [default_path]
# This is the default case when you run `rspec`. We want to add all the pack's spec paths
# to the collection of directories to run.
pack_paths = Packs.all.map do |pack|
next if pack.is_gem?
spec_path = pack.relative_path.join(default_path)
spec_path.to_s if spec_path.exist?
end
to_run.concat(pack_paths)
else

And I wanted to get the maintainers' thoughts before opening a PR.

Background

I help maintain a codebase that has been modularized with stimpack. That configuration has been live for about three months. My team saw that stimpack had been renamed to packs-rails, and we hit a blocker when attempting the migration: an RSpec CI job began to fail consistently. This particular CI job ran flaky specs, which we would identify with a metadata tag. For this to operate correctly, we want to look across all tests (e.g. rspec --tag retry:true), including all packages, and find those specs matching the metadata we specified. Under packs-rails, this CI job would fail with some specs, but not all, throwing an exception

Failure/Error: visit size_breaks_path                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                            
     NameError:                                                                                                                                                                                                                                                                                                                                                             
       undefined local variable or method `controller' for #<RSpec::ExampleGroups::SizeBreaks::MensGeneral::SearchingMensSizeBreaksWithDimensionsLength "should show one Size Break" (./packages/assortments/spec/features/size_breaks_spec.rb:135)>                                                                                                                        
       Did you mean?  content_for 

Digging into this problem a little more, I saw that we hit the NameError exception when my application code attempted to execute size_breaks_path, which is one of Rails' provided methods for generating paths to routes defined in config/routes.rb.

However, when executing this spec file by itself, e.g. rspec ./packages/assortments/spec/features/size_breaks_spec.rb:135, it would work fine, as would running all specs in the file. This led me to conclude the problem wasn't the specs, but rather the way in which we were invoking RSpec.

I saw minimal differences between stimpack's RSpec integration and packs-rails'. Both manipulated RSpec.configuration.files_or_directories_to_run. However I did notice one difference. The list of directories stimpack added to RSpec's configuration was alphabetized, but packs-rails' was not.

Referring to the linked code above, if I inspected to_run with stimpack loaded, the collection of directories in my app was

["spec", "packages/a-pkg/spec", "packages/c-pkg/spec", "packages/i-pkg/spec", "packages/pr-pkg/spec", "packages/p_d-pkg/spec", "packages/p_o-pkg/spec", "packages/s-pkg/spec", "packages/s_b-pkg/spec"]"

whereas packs-rails would look like

["spec", "packages/p_o-pkg/spec", "packages/s_b-pkg/spec", "packages/p_d-pkg/spec", "packages/a-pkg/spec", "packages/I-pkg/spec", "packages/c-pkg/spec", "packages/pr-pkg/spec", "packages/s-pkg/spec"]" 

With this configuration active, any feature specs in the first package, packages/p_o-pkg/spec/features, would work. Any feature specs tagged as flaky that were located in any other package would fail with the NameError exception mentioned above.

Adding a #sort to packs-rails RSpec integration gave me the same behavior as I came to expect with stimpack, which is great, but it also feels like a bit of a workaround. I can only justify it to myself on the grounds that it adds some determinism to the behavior of this integration. I actually think we have identified a problem with RSpec, but until I understand the problem better in the RSpec side, this feels like the lest I can do to unblock my app's migration from stimpack to packs-rails. Thoughts?

Classes from pack are not recognized in tests

Description
I'm attempting to modularize a Rails app. I am starting with one section. I moved the files into a single folder. I installed packwerk and packs-rails. I placed the folder with the files inside of a packs folder at the root of the app. I moved the test files into an rspec folder inside of the section folder. My test fail with the error NameError: uninitialized constant for every single class. All of these classes are in the folder. I don't know why the tests are not treating them like classes.

To Reproduce

  1. move class files into a folder within the packs folder
  2. Add a package.yml turn on engine setting
  3. Add test files and tell rspec to include packs-rails
  4. Run tests and watch them fail

Expected Behaviour
I expected the tests to still recognize the class names though they are moved into a pack.

Screenshots
This is the package.yml in the pack folder
Screenshot 2023-06-06 at 6 41 00 PM

And here is the one at the root
Screenshot 2023-06-06 at 6 41 12 PM

Here is the file system
Screenshot 2023-06-06 at 6 34 17 PM

Here is the .rspec
Screenshot 2023-06-06 at 6 42 35 PM

Here is one of the failing tests
Screenshot 2023-06-06 at 6 35 43 PM

Version Information

  • Packwerk: 3.0.1
  • Ruby 3.2.2

Additional Context
I've tried directly requiring packwerk in the files, having the test files specify they are model tests, moving files around, and changing the names of classes. I've also started over from scratch, following the guidance in the instructions and using different tutorials.

Namespaced engines: what should the namespace be?

Problem

Since #23, Stimpack supports one-level-deep nested packs.

In case of a pack with engine: true, the dynamically defined Engine constant is namespaced by the nested directory, for example:

packs
└── foo
    └── bar
        ├── app
        │   ├── controllers
        │   └── models
        └── package.yml

This would define Foo::Bar::Engine. It would also do isolate_namespace Foo::Bar, meaning that controllers and models that belong to the engine should be namespaced by foo/bar, yielding paths like

packs/foo/bar/app/controllers/foo/bar/example_controller.rb

I had the expectation that the first level of nesting (foo) is only for logical grouping without any impact on namespaces.

Proposed solution

Use only the last directory for nesting for Engine constants, i.e. make it Bar::Engine in the example above.

The fix seems to be pretty simple: oleg-vinted@ff0ac5e, I'd be happy to make a PR if you're interested.

RSpec integration not working as expected

I've currently setup packwerk and stimpack in my application and my expectation around RSpec was that when running rspec or bundle exec rspec then all tests contained in the standard spec/ folder and all tests in packs/**/spec/ folders would be executed.

However it seems like at the moment only tests in the global folder are being picked up and executed, the packs tests are being ignored. I'm using the new Stimpack.config.root setting but I don't think that has anything to do with this.

While debugging, I've managed to print out the value of RSpec.configuration.pattern after the Stimpack integration was loaded, and I got the following:

"**{,/*/**}/*_spec.rb,components/comp1/spec/**/*_spec.rb,components/comp2/spec/**/*_spec.rb,components/comp3/spec/**/*_spec.rb"

so I can see my components there, but the tests are still not included in the run.
Is my expectation incorrect, or is this a bug with Stimpack?

For what is worth, I was previously able to make this work in my app before adding Stimpack, and the trick had to do with setting the --default-path option for RSpec.
This is because, as far as I understand, RSpec assumes your path starts from spec/ and so all patterns are relative to that path, hence components/... will translate into spec/components... which is not what we want.

Question: should db/migrate be part of the default paths?

When using engines we had to manually add db/migrate to the list of paths.

Stimpack.config.paths.concat(%w(db/migrate))

Should that path be part of the default paths? Alternatively, would it be possible to add that path for engines?

Adding `lib` directories to autoload paths

First of all, thanks for putting this gem together. I'm sure a lot of engineering teams have been relying on their own (potentially janky) setup for adopting Packwerk.

I'm trying to switch a project over right now, but it seems like the lib directory of each package isn't automatically autoloaded. Is there an easy way to configure this via Stimpack, or should we just be configuring that elsewhere?

I also realize that autoloading lib is a bit of bad practice but it seems fairly pervasive (especially in older Rails projects).

Moving fixtures inside a pack

Hello! I've been experimenting with this gem for a while now, and for the past few days I've been trying to add the test fixtures inside my pack, but with no success 😞

I currently have something like the following:

- app/
- bin/
- config/
- db/
- lib/
- logs/
- packs/
  - test_pack/
    - app/
    - config/
    - test/
      - controllers/
      - factories/
      - fixtures/
        - users.yml # Does not work
      - helpers/
      - jobs/
      - mailers/
      - models/
- public/
- test/
    - controllers/
    - factories/
    - fixtures/
    - helpers/
    - jobs/
    - mailers/
    - models/

If I move the users.yml file to the test/fixtures in the root then it loads correctly, but if I try it inside the pack I get an error where it says undefined method 'users' for #<UserTest ... > after running the test.

Is this something that can't be done with the current state of the gem?
I am trying to make several packs since I am working on a very big project, and having the fixtures inside the pack would make it easier to write and check the state of the fixtures that are needed for each pack.

[Feature Request] Recursive root or multiple roots

At my current company, we have a bunch of existing code that is laid out in nested folders, which makes it difficult to start using stimpack as it only looks up packages in the first level of the root.

We see two alternatives that would work for us:

  1. Change the behavior to search packs recursively
    We would need to change the resolve method to something like:

       def resolve
         # Gather all the packs under the root directory and create packs.
         Dir.glob(Rails.root.join(Stimpack.config.root).join("**").join("package.yml")).sort!.each do |path|
           next unless pack = Pack.create(File.dirname(path))
           @packs[pack.name] = pack
         end
         @packs.freeze
       end   
  2. Allow having multiple config roots, in that way we could manually list all the folder containing our code.

Would you be willing to accept a change to support this?

Add Rubocop

  • Grab a .rubocop.yml file from an existing @rubyatscale repo
  • Fix violations
  • Add a step to the CI workflow that runs Rubocop

This repo embeds two Rails apps for testing. The Rubocop rules can ignore those directories.

packwerk CVE issue

We noticed that packwerk is being flagged as having a CVE. My initial steps to resolve this was to move pack-rails and packs to the development block, but that of course didn't work because we lost the autoloading capability provided by packs-rails. Do you have any suggestions for how to maintain packs-rails within the app without pulling in these CVEs from packwerk? Our short term solution unfortunately was to stub in some customized autoloading and remove packs-rails as a depedency. It seems like there is maybe an ideal solution where packs-rails no longer has packs as dependency, so that packs can become a dev only gem and packs-rails can live in production without the other dependencies.

undefined method `configuration' for RSpec:Module (NoMethodError)

I've added packwerk and stimpack to our rails monolith but unfortunately if I start bin/rails c it fails with this exception:

bin/rails c
/Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/stimpack-0.4.0/lib/stimpack/integrations/rspec.rb:8:in `block in install': undefined method `configuration' for RSpec:Module (NoMethodError)
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/stimpack-0.4.0/lib/stimpack/packs.rb:36:in `each_value'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/stimpack-0.4.0/lib/stimpack/packs.rb:36:in `each'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/stimpack-0.4.0/lib/stimpack/integrations/rspec.rb:7:in `install'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/stimpack-0.4.0/lib/stimpack.rb:22:in `load'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/stimpack-0.4.0/lib/stimpack/railtie.rb:6:in `block in <class:Railtie>'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/activesupport-6.1.6.1/lib/active_support/lazy_load_hooks.rb:68:in `block in execute_hook'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/activesupport-6.1.6.1/lib/active_support/lazy_load_hooks.rb:61:in `with_execution_control'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/activesupport-6.1.6.1/lib/active_support/lazy_load_hooks.rb:66:in `execute_hook'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/activesupport-6.1.6.1/lib/active_support/lazy_load_hooks.rb:52:in `block in run_load_hooks'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/activesupport-6.1.6.1/lib/active_support/lazy_load_hooks.rb:51:in `each'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/activesupport-6.1.6.1/lib/active_support/lazy_load_hooks.rb:51:in `run_load_hooks'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/railties-6.1.6.1/lib/rails/application.rb:96:in `inherited'
	from /Users/user/Projects/app/app/config/application.rb:19:in `<module:Flowspace>'
	from /Users/user/Projects/app/app/config/application.rb:17:in `<top (required)>'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/application.rb:92:in `require'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/application.rb:92:in `preload'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/application.rb:157:in `serve'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/application.rb:145:in `block in run'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/application.rb:139:in `loop'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/application.rb:139:in `run'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/spring-2.1.1/lib/spring/application/boot.rb:19:in `<top (required)>'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:83:in `require'
	from /Users/user/.rbenv/versions/2.7.5/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:83:in `require'

I added a binding.pry right before this line to look at what is available for the ::RSpec module and it's not much. I'm not sure why it is defined here:

[3] pry(Stimpack::Integrations::RSpec)> cd ::RSpec
[4] pry(RSpec):1> ls
constants: Rails
locals: _  __  _dir_  _ex_  _file_  _in_  _out_  pry_instance

When executing $ it shows the module is defined here:

From: /Users/user/.rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/rspec-rails-5.1.2/lib/rspec/rails/feature_check.rb:1
Module name: RSpec
Number of monkeypatches: 2. Use the `-a` option to display all available monkeypatches
Number of lines: 47

Any ideas why this is occurring?

Dependency on full Rails is too broad

Bit of a nit, but blanket dependency of Rails via spec.add_dependency "rails" is throwing up security warnings like this one.

Any way to change that to something much smaller?
Looking at Rails' dependencies is's not immediately clear which are used by stimpack, most likely zeitwerk, but I'm not sure which of Rails' deps include it.

Maybe try:

s.add_dependency "activesupport"
s.add_dependency "railties"

New RSpec integration doesn't work unless `rails_helper` is required or Rails environment is loaded first

Adding --require stimpack/rspec to my .rspec raises the following error:

Failure/Error: require File.expand_path('../config/environment', __dir__)

FrozenError:
  can't modify frozen Array: [...]

# /Users/mattiagiuffrida/.rvm/gems/ruby-3.1.2/gems/railties-6.1.6.1/lib/rails/engine.rb:588:in `unshift'
# /Users/mattiagiuffrida/.rvm/gems/ruby-3.1.2/gems/railties-6.1.6.1/lib/rails/engine.rb:588:in `block in <class:Engine>'
# /Users/mattiagiuffrida/.rvm/gems/ruby-3.1.2/gems/railties-6.1.6.1/lib/rails/initializable.rb:32:in `instance_exec'
# /Users/mattiagiuffrida/.rvm/gems/ruby-3.1.2/gems/railties-6.1.6.1/lib/rails/initializable.rb:32:in `run'
# /Users/mattiagiuffrida/.rvm/gems/ruby-3.1.2/gems/railties-6.1.6.1/lib/rails/initializable.rb:61:in `block in run_initializers'
# /Users/mattiagiuffrida/.rvm/gems/ruby-3.1.2/gems/railties-6.1.6.1/lib/rails/initializable.rb:50:in `each'
# /Users/mattiagiuffrida/.rvm/gems/ruby-3.1.2/gems/railties-6.1.6.1/lib/rails/initializable.rb:50:in `tsort_each_child'
# /Users/mattiagiuffrida/.rvm/gems/ruby-3.1.2/gems/railties-6.1.6.1/lib/rails/initializable.rb:60:in `run_initializers'
# /Users/mattiagiuffrida/.rvm/gems/ruby-3.1.2/gems/railties-6.1.6.1/lib/rails/application.rb:391:in `initialize!'
# ./config/environment.rb:7:in `<main>'

If I require File.expand_path('../config/environment', __dir__) before stimpack (i.e. add --require rails_helper to my .rspec BEFORE stimpack/rspec), then everything works fine.
Although this solution is relatively easy, we have so far preferred only to require spec_helper by default as this significantly speeds up individual tests execution for non-rails specs (e.g. lib classes).

`spec/support/shared_examples/` doesn't work

If you try to put any spec shared example file to the spec/support/shared_examples/ pack-related folder, it will be unavailable for package-related specs.
The resulting error looks like this:

ArgumentError:
  Could not find shared examples "shared example name"

Auto-release new versions

Steps to publish currently are:

- https://github.com/rubyatscale/stimpack/releases
- “Draft a new release” button
- Release title => stimpack M.m.p
- “Choose a tag => vM.m.p => create new tag on publish with target main (other dropdown)
- “Generate release notes”
- Click big green publish release
- A github action should automatically be kicked off

This is a bit toilsome. Instead, it would be great to do all of this automatically each time a new (green) commit lands on main that changes the version. With a lot of gems, this would make it simpler to percolate changes throughout the ecosystem.

This applies to all gems in the rubyatscale org.

https://github.com/duderman/gh-gem-tag-action
This GitHub action automatically tags commits based on the gem spec. We'd likely want to fork this since this appears to be largely unmaintained. It also appears to not exit gracefully if a tag already exists, which we would want to add.

With this, we could simply bump the version and merge and viola, we would tag the commit, the release notes should be automatically generated, and we should run the publish job (I hope).

Question regarding namespacing

We've recently started using Packwerk and Stimpack in our organisation and we had a bit of a hard time coming to terms with the expected directory structure needed for everything to work and wondered if you can offer any guidance or input on how you consider the following:

We're running a big Rails monolith that has the classic rails file structure with /app, /spec /lib etc.

When developing new features, we generally take care to namespace these under a unique and descriptive name.
For instance a feature for profile pages could be namespaced as ProfilePages resulting in the following directory structure:

packs/
  profile_pages/
    app/
      models/
        profile_pages/
          profile_page.rb
      public/
        profile_pages/
          list_profile_pages.rb
    spec/
      models/
        profile_pages/
          profile_page_spec.rb
          list_profile_pages_spec.rb

This redundant directory structure is necessary for the autoloading to work since profile_page.rb defines ProfilePages::ProfilePage and list_profile_pages defines ProfilePages::ListProfilePages.
However, working with the codebase, this structure feels extremely verbose and redundant since all the code is already nested under the packs/profile_pages folder.

Optimally this directory structure would have been more clean and easier to navigate and reason about:

packs/
  profile_pages/
    app/
      models/
        profile_page.rb
      public/
        list_profile_pages.rb
    spec/
      models/
        profile_page_spec.rb
        list_profile_pages_spec.rb

Is this a problem you have dealt with in your daily use of Packwerk and if so what are your thoughts and opinions about it?
Do you know if support for something like this structure would be possible to add to Stimpack perhaps by using some of Zeitwerks existing functionality like loader.collapse?

Exclude packs directory from rubocop-rails Cops targeting by default

Hello,

I've noticed that files within the packs directory are not being targeted by some of the rubocop-rails Cops. This issue arises because the default configurations for these Cops specifically include paths like app/models/**/*.rb and potentially app/controllers/**/*.rb, but do not consider the packs directory.

ref. https://github.com/rubocop/rubocop-rails/blob/891de2254af9f4d4120b0fc5b5e127209851189f/config/default.yml#L139

For instance, if similar rules are applied to the controllers, this might cause oversight in code standards for files within packs. It may be beneficial to either adjust the default Include paths or provide guidance on how to ensure that packs directory files are also checked, as they are crucial parts of Rails applications.

Could you consider updating the configuration or documentation to address this coverage gap?

Thank you for looking into this issue.

FactoryBot + Minitest

I found that the FactoryBot integration is not working as expected: I added a debug before calling app.config.respond_to?(:factory_bot) and it always returns false somehow 😢

This is in test environment: I executed RAILS_ENV=test bin/rails console
image

I was trying to add minitest support and include the "test/factories" path, but found this instead

How to add custom paths to `Packs::Rails.config.paths`?

I'm trying to add a custom paths to Packs::Rails.config.paths, but I can't figure out the right place to do it.

Here's the relevant part of my application.rb:

Bundler.require(*Rails.groups)

Packs::Rails.config.paths << "app/once"

module MyCompany
  class Application < Rails::Application
    config.load_defaults 7.0

    config.paths.add("app/once", autoload_once: true)
  end
end

I'm trying to set up an app/once directory as a kind of app/lib directory but with autoload_once: true. This fails with the following message:

~/.local/share/rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/packs-rails-0.0.3/lib/packs/rails/integrations/rails.rb:31:in `block (2 levels) in inject_paths': undefined method `<<' for nil:NilClass (NoMethodError)

              @app.paths[path] << pack.relative_path.join(path)
                               ^^

This is caused by packs-rails using a config.before_configuration block to set up config.paths, which is run when inheriting from Rails::Application (i.e. before my config.paths.add(...) call). Is there an intended way to add custom paths? Or should I give up on using a custom path for this and find another way to set autoload_once: true?

Eager load paths

Hey there. Thanks so much for creating this gem! It's lowered the bar for getting started with packwerk. One question that I had though is around eager_loading. In all rails application everything in app/* gets eager loaded by default. But I don't think stimpack follows this convention... at least I couldn't figure out if it does or not by reading through the code.

Could be looking in the wrong place but when I query Rails.application.config.eager_load_paths in our application none of the packs/*/app/ folders show up in there.

parallel_tests gem support

parallel_tests gem allows running tests using multiple processes to speed up the process. The problem is that parallel_tests has its own spec discovery mechanism, so Stimpack's RSpec integration doesn't do anything.

One workaround we found is passing the name of the package directory through the fourth argument to parallel:spec works:

RAILS_ENV=test bundle exec rake 'parallel:spec[2,,,packs]'

It would be nice to find a better way to integrate into parallel_tests.

Moving routes inside a Pack

The documentation states that routes can be split.

I've set up a dummy app to explore how packs-rails behaves, and found that I was not able to get this working.

test app

# config/routes.rb
Rails.application.routes.draw do
  get 'work_orders/index'
  get 'articles/index'
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
  # root "articles#index"
  draw(:accounting)
end
# packs/accounting/config/routes/accounting
Rails.application.routes.draw do
  get 'bills/index'
end

This config works as expected when running the server locally. However, it fails when running bin/packwerk check:

Traceback (most recent call last):
	54: from bin/packwerk:29:in `<main>'
	53: from bin/packwerk:29:in `load'
	52: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/packwerk-3.0.1/exe/packwerk:16:in `<top (required)>'
	51: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
	50: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `bind_call'
	49: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/packwerk-3.0.1/lib/packwerk/cli.rb:43:in `run'
	48: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
	47: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `bind_call'
	46: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/packwerk-3.0.1/lib/packwerk/cli.rb:54:in `execute_command'
	45: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
	44: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `bind_call'
	43: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/packwerk-3.0.1/lib/packwerk/parse_run.rb:62:in `check'
	42: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
	41: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `bind_call'
	40: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/packwerk-3.0.1/lib/packwerk/run_context.rb:22:in `from_configuration'
	39: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
	38: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `bind_call'
	37: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/packwerk-3.0.1/lib/packwerk/configuration.rb:95:in `load_paths'
	36: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
	35: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `bind_call'
	34: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/packwerk-3.0.1/lib/packwerk/rails_load_paths.rb:16:in `for'
	33: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added'
	32: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/sorbet-runtime-0.5.10712/lib/types/private/methods/_methods.rb:277:in `bind_call'
	31: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/packwerk-3.0.1/lib/packwerk/rails_load_paths.rb:58:in `require_application'
	30: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/packwerk-3.0.1/lib/packwerk/rails_load_paths.rb:58:in `require'
	29: from /Users/sarah.sehr/src/packwerk_test_app/config/environment.rb:5:in `<top (required)>'
	28: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/application.rb:372:in `initialize!'
	27: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/initializable.rb:60:in `run_initializers'
	26: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/2.7.0/tsort.rb:205:in `tsort_each'
	25: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/2.7.0/tsort.rb:226:in `tsort_each'
	24: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/2.7.0/tsort.rb:347:in `each_strongly_connected_component'
	23: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/2.7.0/tsort.rb:347:in `call'
	22: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/2.7.0/tsort.rb:347:in `each'
	21: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/2.7.0/tsort.rb:349:in `block in each_strongly_connected_component'
	20: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/2.7.0/tsort.rb:431:in `each_strongly_connected_component_from'
	19: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/2.7.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
	18: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/2.7.0/tsort.rb:228:in `block in tsort_each'
	17: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/initializable.rb:61:in `block in run_initializers'
	16: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/initializable.rb:32:in `run'
	15: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/initializable.rb:32:in `instance_exec'
	14: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/application/finisher.rb:158:in `block in <module:Finisher>'
	13: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/application/routes_reloader.rb:13:in `execute'
	12: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/activesupport-7.0.4.3/lib/active_support/file_update_checker.rb:83:in `execute'
	11: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/application/routes_reloader.rb:38:in `block in updater'
	10: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/application/routes_reloader.rb:24:in `reload!'
	 9: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/application/routes_reloader.rb:50:in `load_paths'
	 8: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/application/routes_reloader.rb:50:in `each'
	 7: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/application/routes_reloader.rb:50:in `block in load_paths'
	 6: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/railties-7.0.4.3/lib/rails/application/routes_reloader.rb:50:in `load'
	 5: from /Users/sarah.sehr/src/packwerk_test_app/config/routes.rb:1:in `<main>'
	 4: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/actionpack-7.0.4.3/lib/action_dispatch/routing/route_set.rb:410:in `draw'
	 3: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/actionpack-7.0.4.3/lib/action_dispatch/routing/route_set.rb:428:in `eval_block'
	 2: from /Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/actionpack-7.0.4.3/lib/action_dispatch/routing/route_set.rb:428:in `instance_exec'
	 1: from /Users/sarah.sehr/src/packwerk_test_app/config/routes.rb:12:in `block in <main>'
/Users/sarah.sehr/.asdf/installs/ruby/2.7.5/lib/ruby/gems/2.7.0/gems/actionpack-7.0.4.3/lib/action_dispatch/routing/mapper.rb:1596:in `draw': Your router tried to #draw the external file accounting.rb, (ArgumentError)
but the file was not found in:

 * /Users/sarah.sehr/src/packwerk_test_app/config/routes

Debugging has indicated that @draw_paths does NOT contain the accounting pack routes.rb file when running bin/packwerk check. However, debugging shows that @draw_paths DOES contain the accounting pack routes.rb file when running the rails server.

It's very possible that I've messed something up, but my app is pretty simple, so I'm wondering if there is some config that isn't documented?

Modulize packs

This might be more of a question is it possible to have everything in a pack modulized. Without creating the nested folders for example:

- Packages
  └ Sales
     |- App
     │  ├─ models
     │  │        └ Lead.rb
     │  └─ Controllers

And lead is modulized as shown below.

module Sales
 class Lead
 end
end

I know its possible to change the file structure however i don't like have even deeper nesting of folders for autoloading to pick this up.

adding migrations to a pack with engine: true

is it possible to add (namespaced) migrations to a pack when engine: true is set?

i read through #25 and rails/rails#47882 but neither really clarified this.

ideally i'd like to add migrations to the pack just like i would add them to an engine (eg rails engine_name:install:migrations) but this doesn't seem to work.

if i add this to my root application.rb:

    Packs.all.map do |pack|
      config.paths["db/migrate"] << pack.path.join("db/migrate")
    end

then i can run migrations that i manually moved into my engine but they don't end up with the isolated package namespace prepended to them.

Running bundle exec rspec packs/my_domain fails with cryptic error

Assuming I have a file structure like described in the readme:

packs/
  my_domain/
    spec/ # With stimpack, specs for a pack live next to the pack
      public/
        my_domain_spec.rb
        my_domain/
          my_subdomain_spec.rb
      services/
        my_domain/
          some_private_class_spec.rb
      models/
        some_other_non_namespaced_private_model_spec.rb
        my_domain/
          my_private_namespaced_model_spec.rb
      factories/ # Stimpack will automatically load pack factories into FactoryBot
        my_domain/
          my_private_namespaced_model_factory.rb

How do I run the specs at packs/my_domain/spec/services/my_domain/some_private_class_spec.rb?

I've tried both:

> bundle exec rspec packs/my_domain/spec/services/my_domain/some_private_class_spec.rb
> bundle exec rspec spec/services/my_domain/some_private_class_spec.rb

And both result in a very strange error (in fact, with stimpack bundled, no specs work any more)

An error occurred while loading rails_helper.
Failure/Error: require File.expand_path("../config/environment", __dir__)

NoMethodError:
  undefined method `<<' for nil:NilClass
# ./vendor/bundle/ruby/2.7.0/gems/stimpack-0.4.0/lib/stimpack/integrations/rails.rb:11:in `block (2 levels) in install'
# ./vendor/bundle/ruby/2.7.0/gems/stimpack-0.4.0/lib/stimpack/integrations/rails.rb:10:in `each'
# ./vendor/bundle/ruby/2.7.0/gems/stimpack-0.4.0/lib/stimpack/integrations/rails.rb:10:in `block in install'
# ./vendor/bundle/ruby/2.7.0/gems/stimpack-0.4.0/lib/stimpack/packs.rb:36:in `each_value'
# ./vendor/bundle/ruby/2.7.0/gems/stimpack-0.4.0/lib/stimpack/packs.rb:36:in `each'
# ./vendor/bundle/ruby/2.7.0/gems/stimpack-0.4.0/lib/stimpack/integrations/rails.rb:9:in `install'
# ./vendor/bundle/ruby/2.7.0/gems/stimpack-0.4.0/lib/stimpack.rb:20:in `load'
# ./vendor/bundle/ruby/2.7.0/gems/stimpack-0.4.0/lib/stimpack/railtie.rb:6:in `block in <class:Railtie>'
# ./vendor/bundle/ruby/2.7.0/gems/activesupport-6.0.4.8/lib/active_support/lazy_load_hooks.rb:68:in `block in execute_hook'
# ./vendor/bundle/ruby/2.7.0/gems/activesupport-6.0.4.8/lib/active_support/lazy_load_hooks.rb:61:in `with_execution_control'
# ./vendor/bundle/ruby/2.7.0/gems/activesupport-6.0.4.8/lib/active_support/lazy_load_hooks.rb:66:in `execute_hook'
# ./vendor/bundle/ruby/2.7.0/gems/activesupport-6.0.4.8/lib/active_support/lazy_load_hooks.rb:52:in `block in run_load_hooks'
# ./vendor/bundle/ruby/2.7.0/gems/activesupport-6.0.4.8/lib/active_support/lazy_load_hooks.rb:51:in `each'
# ./vendor/bundle/ruby/2.7.0/gems/activesupport-6.0.4.8/lib/active_support/lazy_load_hooks.rb:51:in `run_load_hooks'
# ./vendor/bundle/ruby/2.7.0/gems/railties-6.0.4.8/lib/rails/application.rb:96:in `inherited'
# ./config/application.rb:47:in `<module:ScoutRFP>'
# ./config/application.rb:40:in `<top (required)>'
# ./config/environment.rb:4:in `require'
# ./config/environment.rb:4:in `<top (required)>'
# ./spec/rails_helper.rb:13:in `require'
# ./spec/rails_helper.rb:13:in `<top (required)>'
No examples found.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.