Is there any command available for generating all missing spec files for existing models / controllers? I have a project that has several models that have been generated with out spec files.
In rspec-rails-2 which is intended for Rails 3 all of the rspec generators have been removed.
You can solve this problem by running the rails model generator. You can add -s to skip any existing files and --migration=false to skip creating the migration file.
Like so:
rails generate model example -s --migration=false
You could just run the generator and ignore the models/migrations/fixtures.
ruby script/generate rspec_model User --skip-migration --skip-fixture --skip
I've been looking into writing something to do this but there hasn't been any interest from others.
If the number of missing specs is rather small, you could simply run the rails generate commands for each components with missing specs.
When a conflict arises, simply opt not to overwrite the original file. The generator will ignore the existing files and generate the missing ones.
https://gist.github.com/omenking/7774140
require 'fileutils'
namespace :spec do
def progress name, x, y
print "\r #{name}: #{x}/#{y} %6.2f%%" % [x.to_f/y * 100]
end
def generate_files name
kind = name.to_s.singularize
collection = Dir.glob Rails.root.join('app',name.to_s,'**','*').to_s
root = Rails.root.join('app',name.to_s).to_s<<'/'
ext = case name
when :controllers then '_controller.rb'
when :models then '.rb'
end
count = collection.count
collection.each_with_index do |i,index|
`rails g #{kind} #{$1} -s` if i =~ /#{root}(.+)#{ext}/
progress name, index, count
end
end
task generate_missing: :environment do
generate_files :controllers
generate_files :models
end
end
# if you dont want certian things generated than
# configure your generators in your application.rb eg.
#
# config.generators do |g|
# g.orm :active_record
# g.template_engine :haml
# g.stylesheets false
# g.javascripts false
# g.test_framework :rspec,
# fixture: false,
# fixture_replacement: nil
# end
#
Related
In my rails 5 engine I want to include the installation of the engine's migrations with the custom install generator I have at:
myengine/lib/generators/myengine/install_generator.rb
This generator currently looks like this:
module Myengine
module Generators
class InstallGenerator < Rails::Generators::Base
source_root File.expand_path("../../templates", __FILE__)
desc "Creates a Myengine initializer and copys template files to your application."
def copy_initializer
template "myengine.rb", "config/initializers/myengine.rb"
end
end
end
end
When I add the engine to a rails app, instead of having to call:
rails g myengine:install
then
rails myengine:install:migrations
How can I add the creation of those migrations to the custom generator?
Fun question! And one that I hope I can answer. Let's say you have an engine named "Buttafly" and a generator living at:
#lib/generators/buttafly/install/install_generator.rb
At the top of your generator, require the 'date' library like so:
require 'date'
Then in the body of your generator, add a method definition like:
def copy_migrations
# get an array of the migrations in your engine's db/migrate/
# folder:
migrations = Dir[Buttafly::Engine.root.join("db/migrate/*.rb")]
migrations.each_with_index do |migration, i|
# The migrations will be created with the same timestamp if you
# create them all at once. So if you have more than one migration
# in your engine, add one second to the second migration's file
# timestamp and a third second to the third migration's timestamp
# and so on:
seconds = (DateTime.now.strftime("%S").to_i + i).to_s
seconds = seconds.to_s.length == 2 ? seconds : "0#{seconds}"
timestamp = (DateTime.now.strftime "%Y%m%d%H%M") + seconds
# get the filename from the engine migration minus the timestamp:
name = migration.split("/").split("_").last
# See if a the name of your engine migration is already in your
# host app's db/migrate folder:
if Rails.root.join("db/migrate/*#{name}").exist?
# do nothing:
puts "Migration #{name} has already been copied to your app"
else
# copy your engine migration over to the host app with a new
# timestamp:
copy_file m, "db/migrate/#{timestamp}_buttafly_#{name}"
end
end
end
When I generate a model using:
$ rails g model example
Rails generates a factory for the model. Currently it adds the factory to test/factories however I need it to add the factory to spec/factories.
I'm using RSpec and everything else is generated to spec/….
Normally, the place where these files end up, is determined by a directive in the file config/application.rb:
class Application < Rails::Application
config.generators do |g|
...
g.fixture_replacement :factory_girl, dir: 'spec/factories'
...
end
...
I have an admin engine with rspec inside my host application. Here is the my application structure:
Here is the my admin engine's config:
module Admin
class Engine < ::Rails::Engine
isolate_namespace Admin
engine_name 'admin'
config.generators do |g|
g.test_framework :rspec, fixture: false, view_specs: false
g.fixture_replacement :fabrication
g.fixture_replacement :factory_girl, dir: 'spec/factories'
g.integration_tool :rspec
g.assets false
g.helper false
end
end
end
When I create new controller inside the admin engine. I want to generate controller tests on host application's spec/admin/controllers/welcome_controller_spec.rb. I guess I need change admin engine's rspec's config. Any idea?
In your admin project, in config/initializers directory you can create a monkey patch to overwrite the path where the controller spec file is generated:
file /config/initializers/scaffold_generator.rb
require 'generators/rspec/scaffold/scaffold_generator'
module Rspec
module Generators
class ScaffoldGenerator
def generate_controller_spec
return unless options[:controller_specs]
template 'controller_spec.rb',
File.join('/path/to/host/project', 'spec/admin/controllers', controller_class_path, "#{controller_file_name}_controller_spec.rb")
end
end
end
end
It would be clever to replace the hard-coded path '/path/to/host/project' by something more dynamic, so it won't break when you move your workspace files in another location. I can't help you for that because it depends on your project file structure, and it should be easy to do.
To invoke:
bundle exec rails generate scaffold_controller my_controller
Will generate the controller, helper, views, rspec/helper, and rspec/views files in your admin project, and the rspec/controller file in your host project
Does anyone know of a rake task or RSpec call that will generate a bunch of empty files relative to the existing controllers, models, helper files and views that already exist within your application?
You can generate an empty scaffold set of rspec tests against an existing controller using something like this:
rails generate rspec:scaffold recipe
You can improve on this by passing the attributes of the model you want to generate against, like this:
rails generate rspec:scaffold recipe title: string slug: string description: text
You'll still need to do some manual editing, but this should get you most of the way there.
The best solution for this is to add hooks in place within environment.rb to create the spec.rb files within the rails application each time a model or controller is created.
Here's the code for that (using RSpec and FactoryGirl):
module RailsApp
class Application < Rails::Application
config.generators do |g|
g.test_framework :rspec, :fixture_replacement => :factory_girl, :views => true, :helper => false
g.fixture_replacement :factory_girl, :dir => 'spec/factories'
g.stylesheets false
g.javascripts false
g.helper false
end
end
end
This should work:
Install the rspec-rails gem by adding it to your development and test groups in your gemfile gem 'rspec-rails'
Run the rspec generator from inside your app rails generate rspec:install
Read over this doc quickly to see how it integrates with your rails app RSpec-rails doc
Hey Guys, I'm writing a custom Generator(named shcaffold) in Rails 3.0.3, and I'd like it to generate an active_record model(and migration) based on the first argument passed into it(the model's name).
However, I'm getting this error when I run the command:
$ rails g shcaffold someclass
error active_record [not found]
Here's my generator definition, stored in lib/generators/shcaffold/shcaffold_generator.rb:
class ShcaffoldGenerator < Rails::Generators::NamedBase
include Rails::Generators::ResourceHelpers
source_root File.expand_path('../templates', __FILE__)
# Run Other Generators
hook_for :model, :in => :rails, :required => true
end
I'm defining the orm in my app's application.rb:
config.generators do |g|
g.orm :active_record
g.template_engine :erb
g.test_framework :test_unit, :fixture => false
g.stylesheets false
end
But alas, I'm not having any luck.
No detailled answer, but you should take inspiration there: https://github.com/ryanb/nifty-generators
Another similar question regarding the the error active_record [not found] pain in the nether regions =)
Over here: Rails: hook_for :orm not finding active_record
How to resolve:
Stay within the Rails::Generators namespace
This already solves most of the not-found issues.
configure your generator as a default. (anywhere within the Generators model space)
module Rails
module Generators
class Railtie < ::Rails::Engine
if config.respond_to?(:app_generators)
config.app_generators.orm = :my_own_model
else
config.generators.orm = :my_own_model
end
end
end
end
And you wont have any further hassles from rails g anymore.
nJoy!