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.
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'm trying to generate a scaffold named "slave". When I run the command rails generate scaffold slave rails changes some parts of the scaffold from slave to slafe. Affected, for instance, are the resource routes.
Why does this happen and how can I fix this problem?
I am using Rails 5.0.2 with JRuby on RubyMine.
This is happening because of an incorrect inflection. Rails inflections take a one-size-fits-all approach that works in most cases but can often catch you out because of how weird English pluralization is. In your case, the plural 'slaves' is being correctly generated from your input 'slave', but during the route helper generation rails evidently needs a singular version of 'slaves' and settles on 'slafe' because of this inflection rule:
inflect.singular(/([^f])ves$/i, '\1fe')
To fix this simply add a rule of your own:
# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections do |inflect|
inflect.singular('slaves', 'slave')
end
...run the generator again and it works:
$ rake routes | grep slave
slaves GET /slaves(.:format) slaves#index
POST /slaves(.:format) slaves#create
new_slave GET /slaves/new(.:format) slaves#new
edit_slave GET /slaves/:id/edit(.:format) slaves#edit
slave GET /slaves/:id(.:format) slaves#show
PATCH /slaves/:id(.:format) slaves#update
PUT /slaves/:id(.:format) slaves#update
DELETE /slaves/:id(.:format) slaves#destroy
Incidentally, the exact opposite problem can be caused by this rule:
inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
...which causes problems with e.g rails generate scaffold cafe - everything that should be 'cafes' becomes 'caves'. Argh!
As already said by #omnikron, you can try to force an "irregular" inflection at the file config/initializers/inflections.rb:
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.irregular 'slave', 'slaves'
end
I'm wondering if i can generate a scaffold without getting that annyoing s after all scaffolds.
For example, when I run rails generate scaffold product, rails
generates a scaffold called products.
You can modify config/initializers/inflections.rb and provide custom Inflections for words that you want to pluralize/singularize differently. Something like:
ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable "product"
end
would make it so rails g scaffold Product ... wouldn't pluralize the table name and controller name.
However, I would advise against doing this en masse, or just because you don't like pluralization. One of Rails strengths is "Convention over Configuration", and like in several cases, if you're not following the convention, it will be more trouble than it's worth in the long run.
May be you should think about changing your config/initializers/inflections.rb file. Learn more by links below:
Pluralizations and Singularizations (Inflections) in Rails 3
ActiveSupport::Inflector
I've obtained a project that have controllers (minimal code only) and models, but the views are missing. Is there a way to generate the views only using scaffold or another tool?
rails g scaffold User --migration=false --skip
The --skip means to skip files that already exist. (The opposite is --force.)
If you don't want helpers, --helpers=false.
Sample output after deleting my User views:
invoke active_record
identical app/models/user.rb
invoke test_unit
identical test/unit/user_test.rb
skip test/fixtures/users.yml
route resources :users
invoke scaffold_controller
identical app/controllers/users_controller.rb
invoke erb
exist app/views/users
create app/views/users/index.html.erb
create app/views/users/edit.html.erb
create app/views/users/show.html.erb
create app/views/users/new.html.erb
create app/views/users/_form.html.erb
invoke test_unit
identical test/functional/users_controller_test.rb
invoke helper
identical app/helpers/users_helper.rb
invoke test_unit
identical test/unit/helpers/users_helper_test.rb
invoke assets
invoke coffee
identical app/assets/javascripts/users.js.coffee
invoke scss
identical app/assets/stylesheets/users.css.scss
invoke scss
identical app/assets/stylesheets/scaffolds.css.scss
This is what the scaffold generator calls internally:
rails g erb:scaffold User
erb is the templating engine used, so you can also use haml:scaffold.
You must explicitly specify the fields you would like the scaffolding to use--rails does not automatically deduce them from the created model. For example:
rails g erb:scaffold User firstname lastname reputation
See rails g --help for options like skipping, forcing overwriting, and dry runs or generate scaffold --help for information specific to generating scaffolding.
I just encounter the same your problem. I did it. More detail is below:
- First I rename views/your_model folder to views/your_model_bak. In order to revert if fail later
- Then, execute command
rails g scaffold YourModel [field[:type][:index]] --skip
Don't forget --skip option, it will not create exist files (controller and model in this case and few other files)
Make sure list [field[:type][:index]] is up to date
-- Finally, you should update your permit in your_model controller.
Hope it can help you.
"Another tool"...
How about being able to do "script/generate view_for model_name"? :)
There is a gem for that - View Mapper. It has Ruby on Rails 2 and 3 versions.
One small tip is to add "--no-test-framework" if using Rspec and don't want test files generated for each view in spec/views
To generate views after controller and models are already created, you may use the command line. You switch to the folder in which you want to create the new view. For example:
$ cd name_app/app/views/controller_name
$ touch name_file
To go back of one directory use:
$ cd ..
Here are the steps I did. In command line:
rails new lcdemo
rails generate scaffold Cove title:string
(created an entry in seeds.rb)
rake db:migrate
rake db:seed
In the controller and view files, instance variables are named cofe instead of cove.
The reason
"cove".pluralize
=> "coves"
"coves".singularize
=> "cofe"
The solution
You can edit your config/initializers/inflections.rb file to create a custom inflection to teach Rails that the singular of "coves" is "cove".
inflect.irregular 'cove', 'coves'
That'll be the Inflector working its magic. It looks like it's pluralizing "Cove" to "coves" in order to make the table name, and then singularizing "coves" (by analogy with "wolves", "knives" etc) to "cofe".
I don't know if it'll work, but you could try adding the following to config/initializers/inflections.rb before you run the scaffold generator?
inflect.plural "cove", "coves"
inflect.singular "coves", "cove"