How to generate Rails models from database schemas

The *only* thing you have to do now is to add the new field to the view. Everything else is handled automatically. All you are achieving by running the generator is adding that field to the view. Rails does know about the new field, it is just that the view has not asked for it to be displayed.

Colin

Scott & Colin ~

Perhaps this conversation has reached the end of its useful life. But in case there still is anything left to be learned, let me respond to a couple of your comments.

“Why on earth would you keep re-generating scaffolds over and over???” [Scott]

Because generators, when they work, are easier and more reliable than manually updating code. Rails obviously has a powerful set of generators for jump-starting development. That’s one big reason why I’m spending all this time evaluating it (vs other platforms like Django). This whole thread is trying to understand the powers and limits of the Rails generators, specifically in the somewhat-Rails-nonstandard scenario where the DB schema exists independently of the Rails app, so the requirement is to tailor (and re-tailor) the Rails objects to fit the DB schema, with as much automagic support as possible. Of course, the job of generators rapidly becomes harder when you ask them to update objects that have been modified manually since they were originally generated. But some generators can go farther into update-land than others, and I’m trying to understand where Rails is on this dimension.

"The only thing you have to do now is to add the new field to the

view. Everything else is handled automatically. All you are

achieving by running the generator is adding that field to the view."

Not so, from my experiments. Running “rake db:schema:dump” added the field to schema.rb, and the output from scaffold indicates that it edited a total of 8 different files for me, namely:

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

``

Not only did the generator update all these files for me, but it actually knew which files had to be updated so that my app could handle the new database column - another huge advantage for a newbie like me, who would otherwise have to spend hours figuring that out.

Were not all of these 9 edits necessary to weave the new database column into my app?

So, what’s the best approach: Run 3 simple console commands, or manually locate and edit 9 files (and debug the edits)?

I guess I see a lot more value in the Rails generators than you guys do. And I’m still looking to see if they have still further powers (especially in update-land) that I haven’t discovered yet.

Were not all of these 9 edits necessary to weave the new database column into my app?

Actually, no, not at all.

So, what's the best approach: Run 3 simple console commands, or manually locate and edit 9 files (and debug the edits)?

The generators are not going to put them into your views located where you need them and styled the way your app needs them. The generators are not going to be able to write the actual tests for them. The generators are not going to have a clue how they fit with your application's logic and what might need to be done with them in your models or controllers.

Diff the files and see what the changes were.

Colin

All of the changes were to files that specifically mentioned the model’s attributes (aka the table’s columns), and all the changes consisted of adding a mention of the new column. For example, the auto-edit of show.json.jbuilder when I added the size attribute changed

json.extract! @toy, :id, :name, :color, :price, :created_at, :updated_at

``

to

json.extract! @toy, :id, :name, :color, :price, :size, :created_at, :updated_at

``

All of the changes were to files that specifically mentioned the model’s attributes (aka the table’s columns), and all the changes consisted of adding a mention of the new column. For example, the auto-edit of show.json.jbuilder when I added the size attribute changed

json.extract! @toy, :id, :name, :color, :price, :created_at, :updated_at

``

to

json.extract! @toy, :id, :name, :color, :price, :size, :created_at, :updated_at

``

Did the generator add the validations for that attribute?

Did it add the code in the toy.rb that implements the business logic involving that attribute?

Did it add the attribute to the views that do not just consist of the simplistic tables and so on generated by the controller?

Did it add the required tests to make sure that all the uses of the attribute are correct?

So is it worth the hassle of messing about with the generator just for the few minor changes that it did make?

Colin

Comments inserted below.

Did the generator add the validations for that attribute?

Did it add the code in the toy.rb that implements the business logic

involving that attribute?

Did it add the attribute to the views that do not just consist of the

simplistic tables and so on generated by the controller?

Did it add the required tests to make sure that all the uses of the

attribute are correct?

For the Rails generators and their options that I have discovered so far, the answer to all these questions is, obviously, No. Could there be generators that do some of these things? Yes. Are there generators (or other tools) in the Rails World that do some of these things? That’s what I’m trying to find out in this thread.

So is it worth the hassle of messing about with the generator just for

the few minor changes that it did make?

As you develop an app starting with from a generated set of objects, the answer at first is clearly Yes. As you manually modify the objects produced by prior runs of the generator, at some point the answer crosses over into No. How soon you reach that point depends on the amount and kind of manual modifications you have made, vs the power of your generators to synthesize (or to help you synthesize) their new outputs with the manual refinements. The synthetic abilities of the Rails generator that I’ve tried so far (basically scaffold and whatever it invokes) seem to be limited to:

  1. Detecting whether an object that it is about to generate already exists.
  2. If so, detecting whether the existing and new versions of the object are identical.
  3. If the versions are not identical, showing you a diff between them.
  4. Giving you a choice between keeping the old version or replacing it entirely with the new version. I haven’t yet found any help from Rails tools with synthesizing the old (manually modified) and the new (generated) versions of a particular object. I’ll mention just two possibilities:
  5. Even a tool that compares two files textually and helps you merge them by picking line-by-line between the two versions would be a significant help.
  6. Better yet would be a “smart generator” - perhaps better called a synthesizer rather than a generator - that knows the structure of Rails objects and uses that knowledge to make (or at least suggest) syntheses of old and new object versions that preserve the functionality of both. For example, to address one of Colin’s questions, suppose a “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.

~ Thanks yet again ~ Ken

Comments inserted below.

Did the generator add the validations for that attribute?

Did it add the code in the toy.rb that implements the business logic involving that attribute?

Did it add the attribute to the views that do not just consist of the simplistic tables and so on generated by the controller?

Did it add the required tests to make sure that all the uses of the attribute are correct?

For the Rails generators and their options that I have discovered so far, the answer to all these questions is, obviously, No.

Could there be generators that do some of these things? Yes.

Are there generators (or other tools) in the Rails World that do some of these things? That's what I'm trying to find out in this thread.

So is it worth the hassle of messing about with the generator just for the few minor changes that it did make?

As you develop an app starting with from a generated set of objects, the answer at first is clearly Yes. As you manually modify the objects produced by prior runs of the generator, at some point the answer crosses over into No. How soon you reach that point depends on the amount and kind of manual modifications you have made, vs the power of your generators to synthesize (or to help you synthesize) their new outputs with the manual refinements.

The synthetic abilities of the Rails generator that I've tried so far (basically scaffold and whatever it invokes) seem to be limited to:

1. Detecting whether an object that it is about to generate already exists. 2. If so, detecting whether the existing and new versions of the object are identical. 3. If the versions are not identical, showing you a diff between them. 4. Giving you a choice between keeping the old version or replacing it entirely with the new version.

I haven't yet found any help from Rails tools with synthesizing the old (manually modified) and the new (generated) versions of a particular object. I'll mention just two possibilities:   • Even a tool that compares two files textually and helps you merge them by picking line-by-line between the two versions would be a significant help.
  • Better yet would be a "smart generator" - perhaps better called a synthesizer rather than a generator - that knows the structure of Rails objects and uses that knowledge to make (or at least suggest) syntheses of old and new object versions that preserve the functionality of both. For example, to address one of Colin's questions, suppose a "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.

Rails took a different path after that first foray into scaffolding-by-introspection, and decided that they would make it really cheap and easy to get a static file, and then let you modify it later as you go. I believe the thinking was that there was no way a professional would not exert themselves to make a truly custom application if that was what they were being paid to do.

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.

Walter

Thanks Walter ~

Comments interspersed below.

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.

I have some experience with Django, and it fits with what you’re saying. I’m pretty sure that Rails is ahead of Django in its ability to to the kind of generation/synchronization I’m looking for. For example, as far as I know, Django’s schema-to-model generator (inspectdb) generates only models (not controllers or views); and it can only “introspect” the whole DB and generate models for all of its tables (as opposed to Rails where you can run the generators table-by-table). BTW if any Django experts are listening in and I have sold Django short, please steer me straight.

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.

Good idea. Could use a “file compare and merge” tool to do the synthesis.

Another thing that’s emerging from this discussion is the interaction between a platform’s generator abilities and the optimal design of the apps that you build with it. There’s a lot to be gained if the objects it generates are “good enough” for your purposes, even if they aren’t exactly what you would create if starting from a blank slate, because you can the time and effort saved to writing custom code where it really matters or simply to getting done earlier. (For example, I hear that the generated Django “admin interface” was inspired by the fact that Django’s original purpose was to build online newspapers. The data-entry people were basically the paper’s reporters, who could do fine with plain-vanilla entry forms; the designer/developer creativity could be devoted to the read-only pages, to attract and serve the readers/customers.) So, it’s valuable to understand what kinds of automagic your platform can and can’t do, and proceed accordingly.

~ Ken