Having default Rails generators call a custom generator - ruby-on-rails

To be clear, here's NOT what I'm trying to:
Have my custom generator call a default Rails generator
Replace a default Rails generator with my own
What I want to do is have my generator be invoked automatically when I call:
rails generate scaffold User name age:integer
I'm not writing a test replacement or anything, it's completely custom. All information I find about generators out there involve one of those first two cases but not what I want to do. As soon as I found hook_for I immediately thought that was exactly what I needed, but it appears to do the opposite -- invokes another Rails generator from inside of my custom one (if I wanted a test file created for my custom generator I'd call hook_for :test_framework and then define a TestUnit::MyCustomGenerator class somewhere).
I suppose I could monkey patch the default scaffold generator to call mine but that feels dirty. I've looked into some gems that do something similar like https://github.com/Skalar/i18n-yaml-generator but trying to convert that to use an initializer and lib/generators isn't working for me. The scaffold_generator runs but mine never gets called.

for me it works from lib/generators/
$ rails g generator scaffold
create lib/generators/scaffold
create lib/generators/scaffold/scaffold_generator.rb
create lib/generators/scaffold/USAGE
create lib/generators/scaffold/templates
$ rails g scaffold
Usage:
rails generate scaffold NAME [options]
....
what/will/it/create
http://guides.rubyonrails.org/generators.html#generators-lookup
another way may be :)
fork railties gem
override Rails::Generators::ScaffoldGenerator class to your liking
install locally or specify source path in Gemfile
also if 'its completely custom', it is just fair to call it a different name, no?

Related

there are some way to create a custom scaffold or generator on ruby on rails

I wish to create my custom generator, some like run the command "rails generator myScaffold entity field1:String field2:String
and the generator behavior like a normal scaffold, except it will not create the stylesshets, views, and the class of the controller would be customized.
Is it posible with rails? And is it a good and correct thing to do?
thanks!!!
All you need is available here http://guides.rubyonrails.org/generators.html

Overriding default ActiveRecord migration used to create tables in Rails 4

In our existing Rails 3 applications we use an overridden migration.rb file to customise the table creation behaviour.
This was done in Rails 3 by placing our custom file in lib/templates/active_record/model/migration.rb, however it appears Rails 4 has changed the location used for these templates, and this override isn't picked up anymore (it uses the default ActiveRecord migration when creating tables).
I've had a look through the 4.1 ActiveRecord code but can't get the override to work again.
Does anyone know the correct location to place our custom migration.rb in a Rails 4 codebase?
EDIT FOR CLARIFICATION
When you create a new model in Rails, the migration that is generated for you is based off the template found in (> 4.1.x) activerecord/lib/rails/generators/active_record/migration/templates/create_table_migration.rb in the Rails gem.
This has changed since Rails 3.2. In Rails 3.2 the template that was used was called migration.rb and was in the activerecord/lib/rails/generators/active_record/model/templates directory of the Rails gem.
In order to customise the generated template (add a custom SQL block that would be executed in the change method), we override this file by placing a modified copy of it in in our local code base under the lib/templates/active_record/model directory.
We customise it to add some application specific SQL to the end of the migration. In rails 3 this meant that any time you generated a new model, the resulting migration would auto-magically include our custom SQL at the end of the migration.
In our Rails 4 upgrade this custom migration isn't being used anymore, so we're getting vanilla migration files generated by rails, and are having to manually add the SQL each time.
I have tried following the same convention and placing the file in lib/templates/active_record/migration/migration.rb (and a variety of other locations) but the custom template is not being used by Rails when generating a migration.
In Rails 4.2.6 those paths are like this:
lib/templates/active_record/migration/migration.rb
lib/templates/migration/templates/create_table_migration.rb
And the ultimate answer to this problem is to look into source code of Thor library, because all rails generators are based on it. This is how I found correct paths.
Go to lib/thor/actions.rb file and look for find_in_source_paths method and just add puts statement there. Whenever you run any generator you can see a list of all paths that are searched for templates. There are also other ways, but this should give you an idea.
In Rails 4.1.4 this should go here:
activerecord/lib/active_record/migration.rb
Source:
http://api.rubyonrails.org/files/activerecord/lib/active_record/migration_rb.html

Adding source paths to generator (thor, rails)

Trying to make my own app generator (i.e. rails new appName -m path/to/generator) and use my custom generator alongside the rails one.
All goes well except when I want to add a source_path. There are several posts about how this could work with generators for existing apps - see here and I get the same error.
When I add the following line to the top of my script:
source_root File.expand_path('../dependencies',FILE)
the console returns:
apply': undefined method 'source_root' for # Rails::Generators:: App Generator : 0x007f8b0a2a3798> (NoMethodError)
how should I restructure my generator given I am in a Rails project and not a pure ruby one?

How to get generators call other generators in rails 3

I am experimenting with gem development, right now specifically generators. So far I have successfully created two generators that do their job just perfectly. These two generators are in the same directory.
However, right now I have to call each of them separately.
What I'd like to do is just call one generator and have that generator call all the other ones. Just would type
rails g generator_name
and this would call x other generators.
Does anyone know how would I got about doing this?
Help is much appreciated, thanks!
In your generator, you can just call
generate "some:generator" # can be anything listed by 'rails g'
for example:
module MyGem
class InstallGenerator < Rails::Generators::Base
def run_other_generators
generate "jquery:install" # or whatever you want here
end
end
end
By the way, if you are working on Rails 3 gems, this question can also help out:
Rails 3 generators in gem
Another possibility is to use something like
invoke 'active_record:model', 'foo bar:string baz:float'
which is not as clean as generate, but has one advantage: When your generator gets called via rails destroy, this call -- like may other of Thors actions -- will try to revoke the action of the generator you invoke.
There's a catch however: Probably due to Thors dependency management, this only works once per generator you want to call, meaning that a second invoke of the same generator will do nothing. This can be circumvented by using a statement like
Rails::Generators.invoke 'active_record:model', '...', behavior: behavior
instead. In this case you have to explicitly pass through the behavior of your generator (which is a method returning values like :invoke, :revoke and possibly others, depending on which command -- rails generate, rails destroy, rails update, etc. -- called your generator) to achieve the same result as above. If you don't do this, the generator you call with Rails::Generators.invoke will also be executed when running your generator with rails destroy.
Alternatively you could stick to invoke and try to tamper with Thors invocation system. See also here for example.
Generators are based off of Thor, so you can use the apply method.
This is what the Rails Templater gem does. (Here's a walk through the Rails Templater gem.)
Take a look at the scaffold generator that comes with rails.
/Users/XYZ/sources/rails/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb
def manifest
record do |m|
#....rest of the source is removed for brevity....
m.dependency 'model', [name] + #args, :collision => :skip
end
end
Here the scaffold generator is using the model generator. So take a look at the dependency method. You can find the API docs for it over here.

Creating Rails Generator For Model/View/Controller/Mailer

I have an app that's heavily form-based. Many of the forms are constructed exactly alike so it seems like a natural fit for a generator. What I want to do is create one that works like this (fictitious example):
rails g request_form name:string phone:string date_of_birth:date
In any case, the standard, empty controllers, helpers, models, and so on won't quite do. I've read the Rails code but it's, frankly, not been a heck of a lot of help in puzzling this out. What I want to do specifically is:
Create a model and migration given the fields specified on the command line
Create a controller and helper, based on my template
Create views based on my templates
Create empty specs
Create a mailer based on my template
Create mailer views based on my templates
I'm getting stalled at square 1: How the heck do I get the ARGV part of the rails g command -- that is, the field names? Then there's square 2: How do I hook into the built-in generators, where appropriate and fill in my own stuff where not?
This is analogous to
rails g scaffold blah:type blah1:type
so I don't think this is biting off more than I can chew...
Any help mucho appreciated!
All inspiration needed in this great gem: https://github.com/ryanb/nifty-generators
The awesome Ryan Bates has a screencast on writing generators in Rails 3, have you watched that?

Resources