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
Related
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'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.
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"
Background: i'm using InstantRails 2.0
I wanted to add a new column to an existing table using the following syntax:
ruby script/generate migration add_fieldname_to_tablename fieldname:string
So I tried
ruby script/generate migration add_invites_to_user invites:integer
ruby script/generate migration add_invites_to_users invites:integer
And to test it further
ruby script/generate migration AddInvites
ruby script/generate migration AddInvites invites:integer
All of the above give me
builder.rb:175 in 'build': Illegal route: the :controller must be specified! (ArgumentError)
Got it,
I had specified a route without indicating the controller.
ie map.connect 'users/invite/:id'
I fixed it by adding :controller => 'users'
map.connect 'users/invite/:id', :controller => 'users'
I setup the first route while the server was running and it worked fine!
An explanation of why this happens helps:
When you run script/generate Rails will instantiate your application, which involves loading your routes amongst other things. This may seem excessive but it's "for the best", as the other things loaded in the Rails initialization process such as plugins, gems and initializers could affect how the migration operates.
So yes, if you have bad routing code it will break when you try to generate anything.
I have a model named Aggelia (it's greek for classified ad) and have set an inflection in RAILS_ROOT/config/initializers/inflections.rb like so:
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'aggelia', 'aggelies'
end
It works fine in the development environment but when I try to run the tests (only assert truths right now) every test errors with:
test_the_truth(UserTest):
ActiveRecord::StatementInvalid: Mysql::Error: Table 'market_redux_test.aggelias' doesn't exist: DELETE FROM `aggelias`
Seems like rails does not load the inflections when running the tests (or at least not in time).
I am using ruby 1.8.7 on rails 2.3.3
Any ideas why this might be happening?
Found the bug.
Actually, the test environment loads the inflections just fine, the problem was a forgotten aggelias.yml which was created by script/generate model (possibly before I wrote the inflection rule) and triggered the search for an aggelias table.
relevant lighthouse ticket