Forcing override of file with template() in Rails generator? - ruby-on-rails

I have myself a generator that, as part of a set of other operations, needs to set up a model class with a bunch of mixins, defaults, comments, etc.
I want to be using the same rails g model ... code (I'm calling invoke from my generator), but the problem is that there's a conflict because my template and the model generator's template are trying to splat each other:
$ be rails g entry_form karaoke events full_name:string group_name:string
create app/controllers/karaokes_controller.rb
create app/views/karaokes/show.html.erb
create app/views/karaokes/thanks.html.erb
route resource :karaoke
create app/models/karaoke_entry.rb
invoke active_record
create db/migrate/20111004004008_create_karaoke_entries.rb
conflict app/models/karaoke_entry.rb
Overwrite app/models/karaoke_entry.rb?
(enter "h" for help) [Ynaqdh]
Any recommendations how to get around this?
(The best I've come up with is to maybe move my model file creation to the bottom, and find some way to force template / copy_file to go ahead and overwrite the file without bothering the user, but I can't see any pre-existing way of doing this.)

Append force: true or skip: true to the template call:
template "model.rb", "app/models/#{model}.rb", force: true

Some group brainstorming turned up a way to work around this problem.
You can't override (in so far as I can tell), but you can tell the model generator to skip files that already exist. This works:
# Create the model definition from a template:
template "model.rb", "app/models/#{model}.rb"
# ... Later, get Rails to create everything else:
Rails::Generators.invoke("model", ["Example", "title:string", "--skip"])
(I would still welcome a way to allow template to override files.)

Related

Where is a logical place to put a file flag?

In a Ruby on Rails application, where would the most logical place be to put a "file flag."
I am attempting to externalize configuration and allow the presence of a file to be the deciding factor on whether or not something shows on the webapp.
Right now, I have a file here:
lib/
deployment_enabled
Model deployment.rb
class Deployment...
...
def deployment_enabled?
Dir["#{Rails.root}/lib/deployment_enabled"].any?
end
end
Now this works of course, but i'm not sure this follows the MVC paradigms, since the lib directory should consist of scripts. I could put it in config, but again - not sure it belongs there as rails uses this for rails specific configuration, not necessarily the webapp.
I could of course put this in our database, but that require a new table to be created, and that seems unnecessary.
Where's the most logical place to put this flag file? Does Rails have a directory that's created during the generation to put these sort of files?
I suggest using the Rails tmp directory for this purpose. Then:
File.exist?("#{Rails.root}/tmp/deployment_enabled")
Phusion Passenger use this kind of mechanism too.
https://www.phusionpassenger.com/library/walkthroughs/basics/ruby/reloading_code.html#tmp-always_restart-txt
I recommend that you follow the Twelve-Factor App guidelines and keep your code separate from your configuration. In this case you are really talking about a simple boolean value, and the presence of the file is just the mechanism you use to define the value. This should be done instead through an environment variable.
Something like:
DEPLOYMENT_ENABLED=1 RAILS_ENV=production rails server
You would then use an initializer in Rails to detect the value:
# config/initializers/deployment.rb
foo if ENV['DEPLOYMENT_ENABLED']
The value can still be modified at runtime, e.g., ENV['DEPLOYMENT_ENABLED'] = 0.

Ruby on Rails 4: Where i have to put Common code?

I am new to Ruby on rails. i am using rails 4.1.6 and what i want is to make log of all the process in one text file (like index page accessed, view page access etc..). for that i want to create common function, in which i can pass my text as agrs, i had do some R&D on that and i found this : In Rails, where to put useful functions for both controllers and models, but it seems that it is not working with active admin resources. so, for active admin controller and model, i have to create any other modules (i.e. on other location let say /admin/) or anything else i have to do ?
is there any global location that we can use in active admin like component in cakephp.
thanks
EDIT
app/admin/driver.rb
ActiveAdmin.register User, as: 'Driver' do
...
...
index :download_links => false do
...
...
#call function to maintain log something like,
take_note('action performed')
end
A global method feel like a code smell to me. Instead I would create a Note class or module. This doesn't pollute the global name space and is easier to test in isolation.
I would add code like this in a initializer:
# in config/initializers/note.rb
module Note
def self.take(message)
# log `message`
end
end
It could be used in your controller like this:
index :download_links => false do
# ...
Note.take('action performed')
end
Please note that you need to restart your server when changing files in the config folder.
Easiest way is to create a file in the config/initializers folder - these will be autoloaded.
You could also write it in application.rb, though I recommend only doing this for configuration.
A common pattern is to add lib/ to the autoload path so any custom files there can be used - see Auto-loading lib files in Rails 4
It's maybe worth mentioning that you can in fact access your models from anywhere as well.
for your comment
here's a generic class which you can write in lib/ if you add it to your autoload path
class MyClass
def self.my_class_method
puts "i was called"
end
end
Then calling it from anywhere else ...
MyClass.my_class_method

Rails is generating completely blank model files

I have been tinkering around with a Rails project (actually, trying to get it to pick up view templates from lib/templates, which was successful). Now, however, if I generate a scaffold, I get the view files, the migration, but NOT the model file - it creates a zero length file in app/models, but gives it no content.
What on earth have I done?
The way in which I got the thing to pick up the templates was to add a
config.generators do |g|
block, but even if I comment that out now, I can't get rails g model ... to create a model file.
Any clues? FWIW, if I go into an existing alternative rails project, I can create model files perfectly - it's something to do with this project. And I'd quite like to find out what it is rather than blowing the project away and starting again...

Override the default Rails model template

I want to override the default model file that's generated with rails generate model. I've created a template based on this file, but I can't figure out where to put it. Other answers seem to suggest /lib/templates/rails/model/model.rb or /lib/templates/rails/model/model_generator.rb, but neither of those do anything - I put the template in that location but when I run rails generate model ModelName it gets ignored.
Am I going about this the right way? Where should I put the template?
Solved: I wanted lib/templates/active_record/model/model.rb.
You probably need to put it in "lib/rails/generators/active_record/model/templates/model.rb". Here's the rails' default one: https://github.com/rails/rails/blob/master/activerecord/lib/rails/generators/active_record/model/templates/model.rb

Why is Scaffolding Not Working in Ruby on Rails?

I created a controller and a model. The controller is called "Admin" and the model is called "Album". I edited database.yml with proper info and did the rake db:migrate command which didn't return any errors and did migrate the db inside schema.rb. Inside the controller I wrote:
class AdminController < ApplicationController
scaffold :album
end
Next I started my server and went to http://localhost:3000/admin but instead of seeing the typical CRUD page I get the following error:
app/controllers/admin_controller.rb:3
Request
Parameters:
None
Show session dump
---
flash: !map:ActionController::Flash::FlashHash
{}
Response
Headers:
{"cookie"=>[],
"Cache-Control"=>"no-cache"}
Any idea why?
That syntax for scaffolding has been deprecated for quite some time. Nowadays, rails (versions 2.x) use the following method to scaffold a resource:
script/generate scaffold Album title:string date:date ...
That generates the scaffolding views (in app/views), the controller (app/controllers), standard tests (in test/) and, crucially, the required routes to make scaffolding work.
I believe the rails dev team took away the old syntax ("scaffold :resource") because no real application would ever leave a scaffold untouched, ie. you will always need some kind of customization. With the new syntax you can leave it untouched, but it is also much easier to customize.
If you really need your controller to be named admins, you can change the file config/routes.rb after generating the scaffolding. It makes no sense, though: Why should the URI to create a new album be called "/admins/new"?
If you are trying to create an admin area for an image album app, you are probably looking for namespaces (so you can have multiple different resources, controllers and views inside the "admin" namespace). To create an album resource within the admin namespace, write:
script/generate scaffold Admin/Album title:string date:date
In that case, your controller will be accessible as http://host/admin/albums.
Hm,
Normally you would have a controller and a model called Admin and the same thing would be about Album,
Take a look at this quick screen cast how a blog is done using scaffolding;
Creating a web-blog
the script/generate command seems not to work, someone has to provide ./script/generate , I think its a linux directory issue, you have to explicitly say you are starting from the current directory (./). hope this helps someone avoid scratching his head

Resources