Are Rails engines supposed to come with an environment.rb? - ruby-on-rails

I recently created my first Rails engine. The only thing in /config is routes.rb - no environment.rb or application.rb or anything like that.
When I installed the rspec-rails gem and tried to run my specs, I got an error saying it couldn't find environment.rb, which is not surprising, since environment.rb doesn't exist.
The confusing thing to me is that the evidence I have tells me one of two things must be the case:
1) Rails engines don't come with an environment.rb and you're expected to create environment.rb, application.rb, etc. by hand. This seems unlikely.
2) Rails engines do come with an environment.rb, but my engine happens to be missing it for whatever reason. This also seems unlikely. I am confused, though, by this answer that refers to environment.rb in an engine: Testing Rails 3.1 mountable engine with Rspec
So my question is: Are Rails engines supposed to come with an environment.rb, and if not, how are you supposed to create one if you want/need one?

Use the dummy app's environment.rb file.
To setup RSpec:
Add the below to your spec_helper.rb file.
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../test/dummy/config/environment", __FILE__)
...
It's also helpful to add the engine root.
ENGINE_RAILS_ROOT = File.join(File.dirname(__FILE__), '../')
If you want access to the engine's routing helpers, add the below in the RSpec.configure block.
# This will include the routing helpers in the specs so that we can use
# <engine>_path, etc., to get to the routes.
config.include <RailsEngine>::Engine.routes.url_helpers
Hope that helps.

Rails engines may have environment files, but they don't need them. I would recommend against them, because your application is probably going to get mounted (as a gem) inside of another application, making it very difficult to configure your engine from within the main rails application.
It's more advisable that you use a yml file that can be configured from within the primary rails app, and allow that rails app to implement environment specific configurations. That doesn't mean you can't have some defaults that are based on environment environment files inside of your rails engine, but rather, that it usually makes life easier to allow external configuration.

Related

Loading Rails project's app paths in Rspec

I'm writing an application in Rails 5 and using Rspec for tests. I'm having a lot of trouble with require 'some_model' or require 'some_controller' in my spec files. Every time I run a spec, it acts lost and doesn't seem to understand that it's in a Rails app. The suggestions I've seen range from
config.autolad_paths += %W( #{config.root}/app )
to
$LOAD_PATH << '~/my_app/app/models' which sort of works, except that my tests throw an unitialized constant for ApplicationRecord
So for all the digging around I've done, I still haven't found a good way require my MVC files while keeping my specs and spec_helper clean. There doesn't seem to be any defacto way to do so, so how do you all suggest doing it?
can you not take on the entire stress of RSpec configuration. Use the rspec-rails gem and look through the documentation to use it within your app. I guess you can get a base config with rails generate rspec:install after including the gem in your project.

Get routes of Rails app without running rake routes

My understand of rake routes is that it bootstraps the Rails application and then pulls the routes from it. If I want to simply look at the text (no loading of a rails application) and be able to output something similar to what rake routes outputs, how would I do it? I know rake routes actually runs Ruby code and I am worried about doing so as I do not trust these applications.
I am weary to load the Rails application as I do not trust these Rails applications, but if there is a way to sandbox the running of rake routes or some related method, I would be open to that as well.
If you have a complex routes file with lots of engines you'd probably be better off using Vagrant to run the app in a sandbox. If it's simple though, this method might work for you.
Rails will generate routes from routes.rb without the underlying application. Create a new dummy app making sure you match the rails version to the version of the app you want to inspect.
> rails new dummy_app
…
> cd dummy_app
> cp /path/to/untrusted/app/config/routes.rb ./config/
Edit the app name at the top of the route file to match the name of the dummy app, in this case it would be DummyApp.Application.routes.draw do. Then run
> rake routes
Some caveats: If there are any engines or gem speficic routes in there you'll need to add those to the Gemfile or comment out those routes. For example, if the pap uses active_admin you'll need to add that to the gemfile as well as generate the AdminUser class. And then you'll want to recopy over the routes files as the generator adds lines to the routes file. If you run into issues with uninitialized contents you may need an initializer to require certain classes. For example, if you mount Resque::Server, you need an initializer with these two lines:
# config/initializers/dummy_init.rb
require 'resque'
require 'resque/server'

Ruby on Rails - using modules from a different directory

This is a very basic question, but I can't find exactly the answer I need.
I have the following code in trunk/app/models/parsers/my_file.rb in my dev environment:
def initialize
...
#logger = Utils::SingletonLogger.get_logger
#logger.debug("Instantiating my_file object")
end
It runs fine.
But when I deploy it to the test environment (all code should be identical, but I'm not sure where to start looking for differences if there are any), Rails complains that it can't find Parsers::MyFile::Utils. The Utils module I want to use is in app/lib/my_utils.rb. This makes me think that Rails is creating some sort of namespace for the code in the parsers sub-directory, and only looking there for the Utils module, but I haven't been able to figure out how to make it work for me. Is there some main, application level prefix I can use to specify to look outside of the current directory structure?
I've tried adding require 'my_utils' and require_relative '../../../lib/my_utils.rb'. The former can't find the file, the latter just throws the same error as when I don't have any require at all. I'm not sure if I should have to require this or not.
In any case, I clearly don't quite understand how to refer to code in modules in a different directory, I don't understand when/why rails needs an explicit path at some times/environments but not others, and I don't know how to make Rails look outside of the current file for code. Any help with any of these would be appreciated.
Oh, I'm using Ruby 1.9.3, and rails 3.2.1.
Edit: It just started working, without any changes to the application.rb or environment files. It doesn't even have a require in the current version. Is there any obvious reason for it not to work at first, then to work after another server restart? (I'm pretty sure I restarted it after the code went in - I don't think I just forgot to do that before.)
Anyway, thanks for your help - I really do appreciate it.
You can manually add directories you want to include in application.rb. Might want to make sure in your application.rb or test.rb config files you have this autoload_paths in there, yours might be specific to your development.rb file.
config.autoload_paths += %W(#{config.root}/lib/)

Are *all* specs for an engine expected to live in the dummy Rails app?

I'm using RSpec to test some engine models.
My preference would be to test the parts that are independent from the (dummy) app outside of the app. I'd prefer to have non-app tests live at the top level and not be hidden in spec/dummy/spec.
The problem is that by default (AFAICT) engine initializers aren't run if the engine isn't mounted.
Should I just go with what appears to be expected, i.e., put all my specs in the dummy app and run RSpec from the dummy app's directory, even when the tests aren't related to the app as a whole?
Or should I run initializers from a top-level spec helper for the non-app specs? Or some other way?
If I do, are there dummy app repercussions?
If you have a dummy app, you do not have to have your specs in the dummy app dir structure.
The following is a simplified version of what permitters v0.0.1 uses.
In spec/spec_helper.rb:
ENV['RAILS_ENV'] = 'test'
app_path = File.expand_path("../dummy", __FILE__)
$LOAD_PATH.unshift(app_path) unless $LOAD_PATH.include?(app_path)
# if require rails, get uninitialized constant ActionView::Template::Handlers::ERB::ENCODING_FLAG (NameError)
require 'rails/all'
require 'config/environment'
require 'db/schema'
require 'rails/test_help'
require 'rspec/rails'
# rspec config, etc.
Beyond that, I want to say that all of the modifications I made in the dummy app in spec/dummy were either to allow it to be run in different versions of Rails (3.1.x, 3.2.x, and 4.0.x) or because I was configuring things for the gem in the dummy app.
I also currently like using the appraisal gem and TravisCI for continuous integration. The setup I'm using allows me to test in various versions of Rails with various versions of gems and not a lot of maintenance overhead. It needs a little cleanup, but it works well.
If you wanted to not load the Rails environment for a certain set of specs (i.e. not load Rails for some specs_, you could definitely do that. You could just set an env var in the task definition in the Rakefile or at command-line and then look for that in spec_helper.rb to determine whether to load things or not. Then you could have various Rake tasks that spawn new processes that set the env var or not depending on whether a set of tests needs Rails. I wouldn't necessarily worry about that though if everything is meant to be run in Rails, unless you really need to isolate it.
For more info on different ways to test with dummy apps, you might see this question: Strategies for gem tests to ensure the gem works with Rails 3.x and 4.0.

How to get other Gem helpers into my Engine Gem's tests?

I'm trying to write tests for an engine gem I'm writing. I'm using Rspec and the tests seem to be running fine. But whenever a view uses a helper from another gem, such as "will_paginate" or "ransack", I get an "undefined method" error.
I've tried including the other gems in my gem's Gemfile (in addition to the engine.gemspec file) as well as the dummy app's Gemfile, but I get the same error. I've also tried including the gems in the spec/spec_helper.rb file.
So I've tried most of the things mentioned here:
Setup RSpec to test a gem (not Rails)
Usually, for Rspec tests for a regular Rails app, these helpers seem to be just included some how since I don't have this issue running tests for a regular Rails app.
I also have been needing to namespace my url helpers in the views with something like:
engine.resources_path
I'm not sure if that's a symptom of some configuration I've messed up on.
Everything in the engine runs fine when mounted to another app and viewed on the browser.
Any ideas?
Turns out a better approach is to stub out methods from gems since the gem should be testing their own methods anyways. Please let me know if I'm misunderstanding anything. Thanks!

Resources