[sunward@web324 rails_eval]$ rails new x
[sunward@web324 x]$ rails dbconsole
SQLite version 3.6.20
sqlite> CREATE TABLE toys ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" TEXT);
sqlite> INSERT INTO toys (name) VALUES ("Tinker");
sqlite> SELECT * FROM toys;
1|Tinker|58
Rails.application.routes.draw do
resources :toys
root 'toys#index'
end
[sunward@web324 x]$ rake routes
Prefix Verb URI Pattern Controller#Action
toys GET /toys(.:format) toys#index
POST /toys(.:format) toys#create
new_toy GET /toys/new(.:format) toys#new
edit_toy GET /toys/:id/edit(.:format) toys#edit
toy GET /toys/:id(.:format) toys#show
PATCH /toys/:id(.:format) toys#update
PUT /toys/:id(.:format) toys#update
DELETE /toys/:id(.:format) toys#destroy
[sunward@web324 x]$ rails generate controller toys
create app/controllers/toys_controller.rb
invoke erb
create app/views/toys
invoke test_unit
create test/controllers/toys_controller_test.rb
invoke helper
create app/helpers/toys_helper.rb
invoke test_unit
invoke assets
invoke coffee
create app/assets/javascripts/toys.coffee
invoke scss
create app/assets/stylesheets/toys.scss
class ToysController < ApplicationController
def index
@toys = Toy.all
end
def show
@toy = Toy.find(params[:id])
end
def new
@toy = Toy.new
end
def create
@toy = Toy.new(toy_params)
if @toy.save
redirect_to @toy
else
render 'new'
end
end
def edit
@toy = Toy.find(params[:id])
end
def update
@toy = Toy.find(params[:id])
if @toy.update(toy_params)
redirect_to @toy
else
render 'edit'
end
end
def destroy
@toy = Toy.find(params[:id])
@toy.destroy
redirect_to toys_path
end
private
def toy_params
params.require(:toy).permit(:name)
end
end
class Toy < ActiveRecord::Base
end
My next question is whether it is possible to sue the amazing Rails generators - in particular, scaffold - to more quickly create an app that works with an existing database - so it would not be necessary to go thru all those manual steps shown above. I tried it once, and it tried to run the migrator and croaked when it found that the DB table was already there. But that may have been pilot error on my part. Comments and advice would be welcome.
~ Ken
--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/4a506cc5-5bf7-4f46-9628-b4dc6e7555b2%40googlegroups.com.
The aim is to get all the components generated automatically, but based on the database schema. I did it my using the gem schema_to_scaffold, which simply generates a script (one command in this case) that runs the scaffold generator in a way that drives off of the database schema for the new table (users).
1. Created a new database table, users:
sqlite> CREATE TABLE "users" ("id" INTEGER PRIMARY KEY
AUTOINCREMENT NOT NULL, "name" text, "email" textuser);
sqlite> INSERT INTO users (name) VALUES (‘Jo’);
sqlite> SELECT * FROM users;
1|Jo|
2. Installed schema_to_scaffold gem:
sqlite> gem install schema_to_scaffold
3. Ran schema_to_scaffold for users:
[sunward@web324 x]$ scaffold -p db
Looking for schema.rb in db
0. db/schema.rb
Select a path to the target schema:
Loaded tables:
0. toys
1. users
Options are:
4 for table 4; (4..6) for table 4 to 6; [4,6] for tables 4 and 6; * for all Tables
Select a table: 1
Script for scaffold:
rails generate scaffold User name:text email:text --no-migration
4. Ran the script produced by schema_to_scaffold:
[sunward@web324 x]$ rails generate scaffold User name:text email:text --no-migration
invoke active_record
create app/models/user.rb
invoke test_unit
create test/models/user_test.rb
create test/fixtures/users.yml
invoke resource_route
route resources :users
invoke scaffold_controller
create app/controllers/users_controller.rb
invoke erb
create 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
create test/controllers/users_controller_test.rb
invoke helper
create app/helpers/users_helper.rb
invoke test_unit
invoke jbuilder
create app/views/users/index.json.jbuilder
create app/views/users/show.json.jbuilder
invoke assets
invoke coffee
create app/assets/javascripts/users.coffee
invoke scss
create app/assets/stylesheets/users.scss
invoke scss
create app/assets/stylesheets/scaffolds.scss
5. It works! See
http://x.sunward.webfactional.com/users/.
1. Add attribute toys.color (text):
sqlite> ALTER TABLE toys ADD COLUMN color TEXT;
sqlite> INSERT INTO toys (name, color) VALUES ('Tinker', 'Green');
sqlite> select * from toys;
1|Tinker|Green
2. Ran rake db:schema:dump to update schema.rb:
ActiveRecord::Schema.define(version: 0) do
create_table "toys", force: :cascade do |t|
t.text "name"
t.text "color"
end
3. Ran schema_to_scaffold for toys:
[sunward@web324 x]$ scaffold -p db
...
Loaded tables:
0. toys
1. users
...
Select a table: 0
Script for scaffold:
rails generate scaffold Toy name:text color:text --no-migration
4. Ran scaffold using that script:
[sunward@web324 x]$ rails generate scaffold Toy name:text color:text --no-migration
invoke active_record
conflict app/models/toy.rb
Overwrite /home/sunward/webapps/rails_eval/x/app/models/toy.rb? (enter "h" for help) [Ynaqdh] Y
force app/models/toy.rb
invoke test_unit
create test/models/toy_test.rb
create test/fixtures/toys.yml
invoke resource_route
route resources :toys
invoke scaffold_controller
conflict app/controllers/toys_controller.rb
Overwrite /home/sunward/webapps/rails_eval/x/app/controllers/toys_controller.rb? (enter "h" for help) [Ynaqdh] Y
force app/controllers/toys_controller.rb
invoke erb
exist app/views/toys
conflict app/views/toys/index.html.erb
Overwrite /home/sunward/webapps/rails_eval/x/app/views/toys/index.html.erb? (enter "h" for help) [Ynaqdh] Y
force app/views/toys/index.html.erb
conflict app/views/toys/edit.html.erb
Overwrite /home/sunward/webapps/rails_eval/x/app/views/toys/edit.html.erb? (enter "h" for help) [Ynaqdh] Y
force app/views/toys/edit.html.erb
conflict app/views/toys/show.html.erb
Overwrite /home/sunward/webapps/rails_eval/x/app/views/toys/show.html.erb? (enter "h" for help) [Ynaqdh] Y
force app/views/toys/show.html.erb
conflict app/views/toys/new.html.erb
Overwrite /home/sunward/webapps/rails_eval/x/app/views/toys/new.html.erb? (enter "h" for help) [Ynaqdh] Y
force app/views/toys/new.html.erb
conflict app/views/toys/_form.html.erb
Overwrite /home/sunward/webapps/rails_eval/x/app/views/toys/_form.html.erb? (enter "h" for help) [Ynaqdh] Y
force app/views/toys/_form.html.erb
invoke test_unit
conflict test/controllers/toys_controller_test.rb
Overwrite /home/sunward/webapps/rails_eval/x/test/controllers/toys_controller_test.rb? (enter "h" for help) [Ynaqdh] Y
force test/controllers/toys_controller_test.rb
invoke helper
identical app/helpers/toys_helper.rb
invoke test_unit
invoke jbuilder
conflict app/views/toys/index.json.jbuilder
Overwrite /home/sunward/webapps/rails_eval/x/app/views/toys/index.json.jbuilder? (enter "h" for help) [Ynaqdh] Y
force app/views/toys/index.json.jbuilder
conflict app/views/toys/show.json.jbuilder
Overwrite /home/sunward/webapps/rails_eval/x/app/views/toys/show.json.jbuilder? (enter "h" for help) [Ynaqdh] Y
force app/views/toys/show.json.jbuilder
invoke assets
invoke coffee
identical app/assets/javascripts/toys.coffee
invoke scss
conflict app/assets/stylesheets/toys.scss
Overwrite /home/sunward/webapps/rails_eval/x/app/assets/stylesheets/toys.scss? (enter "h" for help) [Ynaqdh] Y
force app/assets/stylesheets/toys.scss
invoke scss
identical5. It works! See http://x.sunward.webfactional.com/toys/.
[sunward@web324 x]$ rails dbconsole
...
psql (9.1.15)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
sunward_x=> \d toys
Table "public.toys"
Column | Type | Modifiers
--------+-------------------+-----------------------------------------------
id | bigint | not null default nextval('toy_seq'::regclass)
name | character varying |
color | character varying |
price | money |
sunward_x=> ALTER TABLE toys ADD size INTEGER;
ALTER TABLE
sunward_x=> \d toys
Table "public.toys"
Column | Type | Modifiers
--------+-------------------+-----------------------------------------------
id | bigint | not null default nextval('toy_seq'::regclass)
name | character varying |
color | character varying |
price | money |
size | integer |
[sunward@web324 x]$ rails generate scaffold Toy --no-migration
[sunward@web324 x]$ rake db:schema:dump
[sunward@web324 x]$ rails generate scaffold Toy --no-migration
conflict test/fixtures/toys.yml
force test/fixtures/toys.yml
conflict app/controllers/toys_controller.rb
force app/controllers/toys_controller.rb
conflict app/views/toys/index.html.erb
force app/views/toys/index.html.erb
conflict app/views/toys/show.html.erb
force app/views/toys/show.html.erb
conflict app/views/toys/_form.html.erb
force app/views/toys/_form.html.erb
conflict test/controllers/toys_controller_test.rb
force test/controllers/toys_controller_test.rb
conflict app/views/toys/index.json.jbuilder
force app/views/toys/index.json.jbuilder
conflict app/views/toys/show.json.jbuilder
force app/views/toys/show.json.jbuilder
json.extract! @toy, :id, :name, :color, :price, :created_at, :updated_at
json.extract! @toy, :id, :name, :color, :price, :size, :created_at, :updated_at
validates
:name
,
presence:
true
" validation had been added to the Toy model before the new "size" column was added to the database. A synthesizer would recognize a validation declaration, and it would know that a validation declaration on one attribute is independent of the existence of another attribute, so it would leave the validation in place and add the new attribute to all the Rails objects where it is relevant. Or, more cautiously, the synthesizer would suggest this synthesis to the developer and let the developer decide. A suite of synthesizers that worked like this would extend the value of running generators/synthesizers waaay deep into the Rails development process. And such synthesizers are especially doable in Rails because they can exploit the fact - which even us newbies can see and appreciate - that Rails is a highly structured, and well-structured, system.
Sorry to get into sermonizing. All I really want from this thread is to learn if any tools or facilities that provide additional generating/synthesizing functionality currently exist in the Rails World.
I don't know of any within the true meaning of "generator" that do all that you have outlined here. But there are systems that ape the Django admin view (RailsAdmin etc) that introspect your database and build an interface to modify it on the fly. This is similar to how the Scaffold system in Rails worked in versions less than 1 (and maybe a few minors after 1). The problem with these systems that I have encountered is that they have a well-formed opinion of how any type of field should be represented, and in what order, and they build you an 80% solution in no time at all. If you're happy with what they give you, then you're completely set. But if you want something even a little bit off the tracks they've laid, then you have a whole world of work to fake them into giving it to you.
One thing you might try is after you've made significant changes, try making a new stunt-double app with the generator, with the new version of your schema. Then copy the relevant files over to your actual working app. You'll be able to cherry-pick which parts of the new code make sense, so you don't have the generator overwrite something you spent time customizing.