Search code examples
ruby-on-railsrspecguard

How to map guard-rspec to multiple different files?


Say I have a controller in app/controllers

I have a series of request specs, one for each action in controller. How do I tell guard when watching a controller, to not only run spec/controllers/controller_spec.rb file but also run:

  • spec/requests/controller/index_spec

  • spec/requests/controller/create_spec

  • spec/requests/controller/update_spec

  • spec/requests/controller/delete_spec

  • spec/requests/controller/show_spec

?

Update:

After @TheChamps help, I have this going. Is this the correct approach for this use case?

  # Controller could be under api/v1 or root level.
  watch(%r{^app\/controllers(\/api\/v1\/)?(.+)_(controller)\.rb}) do |m|
    "spec/requests#{m[1]}#{m[2]}/"
  end

Solution

  • The watch command is pretty straight forward. Via regex, you define where to watch and what to trigger.

    An example

    Take this standard command from their docs:

    watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
    

    The first part

    watch(%r{^app/(.+)\.rb$})
    

    It looks for any files in the app directory which ends with .rb and takes the path as an argument - via (). If a matching file gets saved, for example app/models/users.rb, model/users gets passed on to:

    The block

    { |m| "spec/#{m[1]}_spec.rb" }
    

    By inserting the passed argument it looks for a specific file in the spec directory to trigger - spec/models/user_spec.rb.

    Your usecase

    After saving your controller file, you want to trigger any files located under /requests and under a subfolder named after that controller. Now you should easily be able to understand this command, which achieves just that.

    watch('app/controllers/(.*)_controller.rb') { |m| "spec/requests/#{m}" }