Can shared examples be defined after a feature in RSpec 2? - ruby-on-rails

I am using RSpec/Capybara.
I am writing shared examples in the same spec file. I want to place the shared examples after the feature as the shares examples are really long.
But if I place the shared examples below the feature, RSpec is complaining that it is not able to find the shared example. Is there any way to make it happen?

This question is a year old, but wanted to mention that rspecs shared examples are an alternative to using a normal module. Basically you define module ('concern') that can be included in any spec file using it_behaves_like "my_concern"
See this question for a good example of this in action.

a common practice is to define the code for your shared examples in a module and include it via the configuration. that way, you have a clear code separation and reuse.
in spec/support/xyz.rb
module SomeSharedExamples
[...]
end
in your spec_helper.rb
config.include SomeSharedExamples

Related

What would you need to do to Rails to make spec files live alongside the code they describe?

For years I've followed the rails convention of putting spec files in a spec folder and entirely separate from the code they describe:
- app
- controllers
- application_controller.rb
- models
- user.rb
- spec
- controllers
- application_controller_spec.rb
- models
- user_spec.rb
However there's a lot of unnecessary dislocation and confusion that can come with that approach and I really like Angular's approach of keeping components, their specs and code side by side. Having worked on large rails projects, the dislocation between spec and code can become incredibly confusing and disorientating.
What changes would be needed to make this happen?
I'd like to experiment doing the same thing in rails and moving the specs to sit next to the files they describe so that the directory structure is more similar to this:
- app
- controllers
- application_controller.rb
- application_controller_spec.rb
- models
- user.rb
- user_spec.rb
What things will I need to change to make this work?
A couple of things that spring to mind are:
making sure Zeitwerk doesn't load spec files into memory on app load
adjusting guard so that it watches the correct directories
What other things would I need though and is there anything in particular I should watch out for?
It may be possible, but probably not practical.
First off, assuming you're using rspec, you would have to configure/override the path where your test suite expects to find your spec files, which is probably not all that difficult to do, but if you're using any extensions to rspec, (or any other test suite), you would have to make adjustments to any references to spec paths in order to make your specs run correctly, which could add to future maintenance efforts.
You may also lose the ability to use generators, unless you patch the classes that create spec files when you run a generator, since they will, by default, put spec files in spec/models, spec/controllers, etc.
Overriding these kinds of things is possible, but will require maintenance, and would probably be considered 'not the Rails way' by most Rails developers. Rails is an opinionated framework, which is to say that any developers working on your app would almost certainly expect to see spec files in the spec directory by default, so you might get pushback from your future team members.
There may be other issues, but those are just the first things that come to mind.
Why use autoload? Since you're going so far away from the framework's convention, you could simply require files manually, and configure rspec to run only on _spec.rb files. rspec ./app and you're good to go.
-
A note about architecture:
Bob Martin points out in his book "Clean Architecture" that tests can be considered the outermost layer of your system. They're there to guarantee it works properly, but absolutely NOTHING depends on them. Changing the structure of your whole project, tied to one web-framework, to tie it to the convention of another web-framework, doesn't appeal too much to me.
Here's a quite old talk from him for the rails community, touching topics such as this: https://www.youtube.com/watch?v=WpkDN78P884
https://github.com/RailsEventStore/cqrs-es-sample-with-res
This sample application from the RailsEventStore organization provides an example of how to go about it, though it uses mini-test instead of rspec, in theory it should work for rspec.
It provides an example of using /ordering at the top level to group logic. Specific for this, it uses /ordering/test/ to store the tests. It includes a test helper which basically just loads the stuff you could include in the regular test helper. So for rspec I imagine it would be something like:
# rails_root/something/rspec/spec_helper.rb
require_relative '../../rspec/rspec_helper' # Load the standard rspec helper
This allows you to continue to use the standard /rspec pattern while also being able to have high level modules (ie: bounded contexts) include their own specs.
Though really, I think that is probably a bad practice as far as how you had it. It would likely make more sense to do something like below, though even that isn't really ideal as you add duplicate spec_helpers and there really isn't a practical benefit to grouping them that way other than it being slightly faster to find specs in some cases.
- app
- controllers
- application_controller.rb
- specs
- application_controller_spec.rb
- spec_helper.rb
- models
- user.rb
- specs
- user_spec.rb
- spec_helper.rb
You would run the model specs via rspec app/models/specs.

Where do I put my helpers and how do I test them?

This is my first on StackOverflow and I'm a new rails developer.
I'm using RoR to create an inventory application for Magic: The Gathering cards. I've found a Json API that I'd like to use to pull data on all of the cards, sets, etc into a local database.
My initial inclination is to create a helper class to manage all of this (which can also be called in seeds.rb during db:setup), but I have no idea where I should put this class in my project's directory structure. It's not really a model/controller/view, so I feel it should be kept separate from those parts of the app.
Further more, I'm having trouble testing any class I do make. I initially created a directory app/classes and put the class there. Then in my spec directory, I created spec/classes and created the spec file. Accessing my helper class from the spec did not work in the same way that accessing my models in their spec classes did.
I'm at a loss as to how to do this and quite a bit of googling and searching on here has just left me more confused. I'd love any help that can be offered. How would you do this?
You don't mention specifically what issues you're encountering, but for starters app/classes isn't in rails's autoload path - rails' require magic doesn't know to look in there to find these classes (as an aside, 'classes' sounds like a slightly meaningless name - models & controllers are classes too).
You can add to the paths rails searches (see config.autoload_paths in config/application.rb) but I would put this in lib (and the corresponding specs in spec/lib).
It would also work just fine with these classes in app/models, whether or not it does there is down to choice. There's nothing that says that files in there have to be active record subclasses - the decision of whether or not this functionality belongs in there boils down to whether it works/feels like a model to you.

How-to know what to require to get specific part of Rails framework functions?

When writing non-rails ruby project I often find myself in the position that I want to use certain parts of the Rails framework. This can be object extensions (like the String method camelize) or, as today, ActionDispatch::Assertions::SelectorAssertions, where I just want to add css_select to some of my tests.
I get pretty confused often over hyphenation/underscoring and often struggle to find out, what exactly I have to require. And I haven't found a system yet...
Is there a rule as to how to require a part of Rails if I know what module or class I want?
I suggest use active support library of rails. It has huge set of inbuilt methods which you can use in your ruby code. Just write in your ruby code.
require 'active_support'
http://as.rubyonrails.org/

Ruby on Rails: where should I store modules?

I am new to Ruby on Rails and my questions are about the application design, based on Rails 3. There are many data on the internet on the creation of standard websites (such as blogs) on Rails, but my application requires more than just "post and read" and I am not sure how to implement that.
The idea:
The model "Route" includes a number of airlines modules: "Ryanair", "easyJet", etc.
The "Route.Update" method calls the "UpdateRoutes" on each airline module (for example, "Ryanair.UpdateRoutes", "easyJet.UpdateRoutes")
It should work the same way with more models (such as "Flight.find") and more airlines ("Delta.FindFlights")
The questions:
Where should I store all the modules? I don't see any app/modules folder in Rails.
If my modules require gems, should I include them in the modules or in the models (where they are actually used)?
I want to make my application scalable. For example, I want to add a new working airline (module) without changing any code in "Route", "Flight" or any other model. I imagine something like the method "IncludeAirlines" which would go through modules/airlines/name.rb, include every module and call the needed method of it (such as name.UpdateRoutes). Is there any better way to implement that in Ruby on Rails?
As you might know, modules are generally used either as namespaces or as mixins.
Where you place a module depends on how tightly coupled a module is with the app directory . A few patterns in storing modules :
The /lib directory, if the module does not particularly 'interact' or concern the app/ and you treat the module as an internal plug-in.
The app/models directory, would be an appropriate place if your module is central to your business logic. A popular use case here, is where you use a module as a mixin to DRY your models/controllers.
37 Signals introduced a pattern of treating them as 'concerns' and storing them in app/concerns.
If your module uses a gem, you may need to require the gem in the module (sometimes a require is not at all necessary).
Your 3rd question is not clear. Sorry about that. Not quite sure what you're trying to do.

How to break rails models into modules? [duplicate]

I have a model that requires loading external data from an auxiliary source. A number of web services exist that my model can fetch the data from (swappable), but I don't want to create code that will make it difficult to change services (costs significantly differ based on variable and fixed usage and it is likely changing will be required).
I would like to create a driver to perform the interaction (and then create further custom drivers if the service requires switching). Unfortunately, due to the tight coupling of the driver and model, it does not makes sense to extract the code into a plugin or gem. I have extracted all the code into a module (see example), and currently have the code declared above my model.
module Synchronize
def refresh
self.attributes = ...
self.save
end
end
class Data < ActiveRecord::Base
include Synchronize
end
Does Rails (3.0.0) have a convention for storing modules tightly coupled with models? Should I be using a plugin to do this? Is this associated with the 'app/helpers' directory? If not, where is the most appropriate place to store the code? Thanks!
You are correct that if the module is tightly coupled to that specific model then it's not a good candidate for a gem/plugin.
app/helpers/ is for view helper methods and shouldn't contain modules that are solely for mixing into models.
One place you could put the module is within lib/. This is for code that doesn't really fit anywhere within app/ and is often the initial home of loosely coupled code before it is moved to a plugin (but that isn't a hard and fast rule). However, since your module is tightly coupled to your model, lib/ may not be the best place for it.
I know that 37signals (and others) use the concept of 'concerns' as a way of keeping related model code organised in modules. This is implemented by creating app/concerns/ and putting the modules in there. That directory is then added to the app's load path in config/application.rb (config/environment.rb for Rails 2) with:
config.load_paths += %W(#{Rails.root}/app/concerns)
The module can then be mixed into the model as normal.
Here's the original blog post about this by Jamis Buck - http://weblog.jamisbuck.org/2007/1/17/concerns-in-activerecord
Another variation of this which I personally prefer, although it doesn't involve modules, uses this plugin:
http://github.com/jakehow/concerned_with
Hope that helps.
This link has helped me out around this.
http://ander.heroku.com/2010/12/14/concerns-in-rails-3/
I have been sticking it in a model/extensions directory. The concerns directory makes sense but the word 'concerns' doesn't feel obvious to me. Maybe it will grow on me.
I also added the extensions path in the application.rb
config.autoload_paths += %W(#{config.root}/app/models/extensions)

Resources