Script/generate became very annoying since I started using rspec etc. I dont need unit test files and fixtures anymore, but script/generate makes them anyway.
Is it possible to set --skip-fixtures and --skip-test to be default system-wide (or at least project-wide)?
You can edit your applications script/generate file to auto append options
#!/usr/bin/env ruby
ARGV << "--skip-fixture" if ["model"].include?(ARGV[0])
require File.dirname(__FILE__) + '/../config/boot'
require 'commands/generate'
Well, for starters,
ruby script/generate rspec_model
ruby script/generate rspec_controller
At least that doesn't generate unit tests and it gets the specs there for me :)
But --skip-fixtures still has to get passed. I've just made my own aliases in .bash_profile
alias model='ruby script/generate rspec_model $1 --skip-fixture'
Then I can just do
model bar name:string active:boolean
and it all works :)
I use minitest_rails as my testing framework, and you can set some defaults via the config/application.rb file.
config.generators do |g|
g.test_framework :mini_test, :spec => true, :fixture => false
end
When you generate a model (and controller), it will now automatically skip the fixture. This example will also create the Unit Test using the minitest_spec format.
Related
Edit: Originally this was a Rails 5.2 question but it still seems relevant with Rails 6 and 6.1
I am trying to customise which tests are generated by default in a vanilla Rails 5.2.x app. I don't seem to be able to configure the Minitest generators though. The following code in my config/application.rb causes a error minitest [not found] error when I try and generate a model.
config.generators do |generate|
generate.test_framework :minitest, model: false
end
My Assumptions/Understanding
In Rails 5.2 the default test frameworks are Minitest and Capybara
Minitest gem is included automatically with rails new
You can customise generator behaviour with a config.generators do block in config/application.rb
test_framework "defines which test framework to use. Defaults to false and will use Minitest by default"
Clearly there's a gap in my understanding or one of my assumptions is wrong.
Steps to Reproduce
rails -v
# Rails 5.2.1.1
rails new testing-test-frameworks
# Bundle install outputs: 'Using minitest 5.11.3'
cd testing-test-frameworks
rails g model --help
# Default [test framework]: test_unit [why???]
rails g model person
# invoke test_unit [why???]
# create test/models/person_test.rb
# create test/fixtures/people.yml
Strangely enough, the official Rails testing guide also has lots of references to invoke test_unit for both unit tests and system tests.
Other Things I Tried
I tried other settings in the config.generators block just to make sure it's working
Given that the test_unit generators seem to be non-negotiable I tried changing the generations through test_unit; config.generators.test_framework :test_unit, model: false
I tried to disable various other tests; fixture:false, integration: false, model: false, spec: false, system: false, view: false
I tried to confirm I don't have any other gems or settings that might be messing with things (several similar sounding problems related to an old version of FactoryBot/Girl)
I tried variations such as generate.test_framework :mini_test mentioned in other answers
Questions
How do I control these generators?
Where (on the Internet or on my filesystem) do I go to learn about the valid options that can be passed to the generators for each test framework?
Why does the help system in my vanilla app say the default test generator is TestUnit when the official documentation says it's Minitest?
I'm attempting to partially answer some of my own questions (2+ years later) based on recent learnings (and based on Rails 6). If I'm wrong, hopefully Cunningham's Law holds true.
1. :test_unit == :minitest (more or less)
The first big point of confusion for me was that Minitest is indeed the default test framework under the hood but just about everything within Rails (still?) seems to refer to TestUnit/test_unit.
Examples include:
rails g model --help output (snippets below)
-t, [--test-framework=NAME] # Test framework to be invoked
# Default: test_unit
^^^^^^^^^
TestUnit options:
^^^^^^^^
rails g scaffold Example output (snippets below):
create app/models/example.rb
invoke test_unit
^^^^^^^^^
create test/models/example_test.rb
invoke scaffold_controller
create app/controllers/examples_controller.rb
invoke test_unit
^^^^^^^^^
create test/controllers/examples_controller_test.rb
create app/helpers/examples_helper.rb
invoke test_unit
^^^^^^^^^
The way we generate tests:
bin/rails generate test_unit:model article title:string body:text
^^^^^^^^^
2. Digging into Test Unit
Sure enough, if we look in all.rb we see that "Test Unit" is being included via the test_unit Railtie. If (like me) you don't really know what a Railtie is, check out this blog post, I found it quite helpful.
In terms of what options we can provide in our config/application.rb config.generators block, I think the only options we can pass with config.generators.test_framework :test_unit are fixture: true/false (and maybe specifying a fixture_replacement path(?), based on the apparent defaults in the test_unit railtie).
3. What else can "TestUnit" generate?
If you run rails g to get a list of available generators, only four TestUnit ones are mentioned in the output:
TestUnit:
test_unit:channel
test_unit:generator
test_unit:mailbox
test_unit:plugin
But the Rails Testing Guide mentions test_unit:model and test_unit:scaffold as well. And when I tried rails g test_unit:foo Rails suggested perhaps I meant rails g test_unit:job so that's three "undocumented" generators.
From what I can tell, those three extras come from this generators folder, along with a few others. If so, I think the complete list is:
test_unit:channel *not in that folder, seems to be added by
ActionCable
test_unit:controller
test_unit:generator
test_unit:helper
test_unit:integration
test_unit:job
test_unit:mailbox *not in that folder, seems to be added by ActionMailbox
test_unit:mailer
test_unit:model
test_unit:plugin
test_unit:scaffold
test_unit:system
I am using graph database using rails. I don't want to generate migration while generating models. I know there is a options like rails g model user --skip-migration.
But I am searching for permanent solutions what I do not need to specify --skip-migration every time while generating model.
Yes. You can customize default rails generators (http://guides.rubyonrails.org/generators.html#customizing-your-workflow). It's actually quite easy. Just add following snippet into your config/application.rb:
config.generators do |g|
g.orm :active_record, migration: false
end
This tells Rails to use ActiveRecord as an ORM but to skip generation of migrations.
Using rspec, I would like the app to stop generating request specs and start generating feature specs instead. spec/features are used by capybara. The request spec generator could be omitted with
config.generators do |g|
g.test_framework :rspec, :request_specs => false
end
Is there a setting to enable feature specs when generating scaffolds?
You should make sure you have upgraded to the newest rspec-rails, just in case this is available there. If that doesn't help, you can always add your own generator.
I'm having a problem with generating scaffold for a Regatta. When I run
rails g scaffold Regatta name:string start_date:datetime
I get a model named regattum and a controller called regatta_controller (instead of regattas_controller)
invoke active_record
create db/migrate/20110609221608_create_regatta.rb
create app/models/regattum.rb
invoke test_unit
create test/unit/regattum_test.rb
create test/fixtures/regatta.yml
route resources :regatta
invoke scaffold_controller
create app/controllers/regatta_controller.rb
invoke erb
create app/views/regatta
create app/views/regatta/index.html.erb
create app/views/regatta/edit.html.erb
create app/views/regatta/show.html.erb
create app/views/regatta/new.html.erb
create app/views/regatta/_form.html.erb
invoke test_unit
create test/functional/regatta_controller_test.rb
invoke helper
create app/helpers/regatta_helper.rb
invoke test_unit
create test/unit/helpers/regatta_helper_test.rb
invoke stylesheets
identical public/stylesheets/scaffold.css
Obviously this is an inflection problem, but whenever I modify /config/initializers/inflections.rb I get an error saying:
The name 'Regatta' is either already used in your application or reserved by Ruby on Rails. Please choose an alternative and run this generator again.
I have tried everything I can think of to make it work, but I keep getting an error. Any advice on a solution or a workaround would be greatly appreciated!
Update
Here are some of the things I have tried:
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'regatta', 'regattas'
end
That didn't change anything so I tried a few of the options below, among others,in varying combinations to no avail:
inflect.plural 'regatta', 'regattas'
inflect.singular 'regattas', 'regatta'
inflect.singular 'regatta', 'regatta'
Update 2
Here is the code I used in inflections.rb once I figured out what I was doing wrong:
ActiveSupport::Inflector.inflections do |inflect|
inflect.plural 'regatta', 'regattas'
inflect.singular 'regatta', 'regatta'
inflect.singular 'regattas', 'regatta'
end
Hopefully this will help someone out in the future!
I recognize this post is old, but I thought I would contribute my findings as well.
I have been integrating rpsec and cucumber into my application after much development (yes; naughty, naughty). I wanted to generate the rspec stubs for my models and get my application unit tested. I am usually able to move an associated migration out of db/migrate/ and run 'bundle exec rails g ' to regenerate the scaffolds and in this case, the rspec stubs. Not this time.
<terminal>
bundle exec rails g scaffold User email:string ...
updated_at:datetime roles_mask:integer --trace
invoke active_record
The name 'User' is either already used in your application
or reserved by Ruby on Rails. Please choose an alternative
and run this generator again.
My problem was resolved by temporarily commenting out the 'devise_for' line in my 'config/routes.rb' file
config/routes.rb
#devise_for :users
Bingo. And this isn't the only time that Devise has surprised me with 'black magic' that is not readily apparent. I un-commented the line once my rspec stubs were generated, of course. Now it's off to writing my unit tests!
Given the error message saying that Regatta is already in use in your application (it's obviously not reserved by Rails), I'm guessing the Regattum model is still in place.
I'd recommend destroying the scaffold and trying again. It sounds like, once a word is already defined in the application, Rails has a built-in protection against changing the inflection. So, this error being thrown is to protect against unexpected behavior in this very situation.
Where and how do I run a simple script that uses my rails environment. Specifically I have one column that holds multiple pieces of information, I've added columns now for each piece of information and need to run a ruby script that can run to call a method on each row of the database to extrapolate data and save it to the new column.
Using a migration sounds like the right way to go if I am understanding your use case.
However, if you really do want to write a standalone script that needs access to your Rails application's models, you can require the environment.rb file from inside your standalone script.
Example:
#!/bin/env ruby
ENV['RAILS_ENV'] = "production" # Set to your desired Rails environment name
require '/path/to/railsapp/config/environment.rb'
# After this point you have access to your models and other classes from your Rails application
model_instance = MyModel.find(7)
model_instance.some_attribute = "new value"
model_instance.save
I have to agree with David here. Use a migration for this. I'm not sure what you want to do, but running it from inside your environment is much, much more efficient then loading up the app environment manually. And since your initial post suggests you're only doing this once, a migration is the way to go:
rails g migration MigrateData
.. generates:
class MigrateData < ActiveRecord::Migration
def self.up
# Your migration code here
end
def self.down
# Rollback scenario
end
end
Of course, you will always want to perform this locally first, using some test data.
Agree with everyone, for this specific case it sounds like migration will be way to go, however, to do this regularly, or write some other task/script that interacts rails app environment make rails generate a rake task for you! This gets saved with your rails app, and can be run again and again :)
Easiest way to generate a rake task that interact with rails app/models is to make Rails generate Rake tasks for you!! :)
Here's an example
run rails g task my_namespace my_task
This will generate a file called lib/tasks/my_namespace.rake which looks like:
namespace :my_namespace do
desc "TODO: Describe your task here"
task :my_task1 => :environment do
#write any ruby code here and also work with your models
puts User.find(1).name
end
end
Run this task with rake my_namespace:my_task
Watch your ruby code task that interacts with rails modal run!
Seeding data:
http://railscasts.com/episodes/179-seed-data
Adding data with migrations
http://railscasts.com/episodes/23-counter-cache-column
Working with Rake Tasks
http://railscasts.com/episodes/66-custom-rake-tasks
I prefer to use migrations for adding some data in your case.
If it's a one-time thing, use a migration.
If this is something that needs to be done multiple times, use a rake task for it.