4

更新:问题仍然存在,欢迎任何评论,评论

我有一个现有的 rails 项目,其中丢失了一些重要的文件和目录。

项目 rails 版本(2.3.8)我在 environment.rb 中找到了它

目前我所拥有的是

app
   controllers (already fully coded)
   helpers  (already fully coded)
   models (already fully coded) 
   reports (already fully coded)
   views  (already fully coded)

config ---> default configurations (already fully coded)
lib ---> contains nothing
public --> contains images and scripts (already fully coded)
script ---> contains server,runner,plugin,dbconsole....

app 目录完全包含代码的工作状态,app/model 包含 100 多个 .rb 文件,所以我假设它会超过 100 个表

主要缺少的东西是db 目录、.gem 文件、rake 文件、doc、test、vendor、database、schema.rb 和迁移

注意: 我没有该项目的表架构和数据库

我需要从模型和视图生成表或完整的数据库,我正在寻找逆向工程类的东西来从模型或视图生成数据库模式

我是rails的新手,我来自java背景,在java中通过使用hibernate有一个pojo(rails中的模型)到数据库选项可用,我正在为rails寻找类似的东西,我的主要目标是运行那个项目,所以请大家帮帮我。

4

3 回答 3

4

要重新创建数据库模式,需要相当长的时间。

您可以在 app/models、app/controllers app/views 目录中获得很多关于数据库的信息。

您应该知道 ActiveRecord不需要您显式列出模型的所有属性。这具有重要意义 - 您只能根据是否引用属性来推断您仍需要添加到数据库中的属性!这意味着这样做有点艺术。并且没有明确的步骤来完成这项工作。但以下是一些您可以用来帮助您的规则。

这是一个大项目,以下是帮助您的指南、规则和提示。但请注意,这可能需要很长时间,并且有时会令人沮丧才能完成这项工作。


您需要什么表:

每个表通常都有一个匹配的ActiveRecord::Base模型。所以在app/models目录下,检查每一个文件,如果类继承自ActiveRecord::Base,就是一个额外的表。

默认情况下,表名是类名的复数形式。

class UserGroup < ActiveRecord::Base # for this class

表的名称是 user_groups。注意它是复数,而不是驼峰式,它是小写,用下划线分隔单词。

所有这些表都将有一个“id”整数列。默认情况下,这些表还具有日期时间类型的“created_at”和“updated_at”列。

关联和外键:

您可以通过模型中的关联来推断存在哪些外键。所有关联都明确列出,所以这并不难。

例如:

class UserGroup < ActiveRecord::Base # for this class
  belongs_to :category

这意味着 user_groups 表有一个名为“category_id”的列,它是类别表的外键。

这意味着 Category 模型可能具有反比关系(但没有额外的列):

class Category < ActiveRecord::Base
  has_many :user_groups

主要的其他关联是 has_many_and_belongs_to 关联。例如。

class A < ActiveRecord::Base
  has_and_belongs_to_many :bs
end
class B < ActiveRecord::Base
  has_and_belongs_to_many :as
end

这意味着要添加一个名为“as_bs”的连接表(as 和 bs 按字母顺序排序),外键为“a_id”和“b_id”。

所有外键都是整数。


属性

好的,这就是表关联。现在对于普通属性...

您应该检查app/views/user_groups/或其他类似的app/views目录。

在里面你会找到视图模板。您应该查看 _form.html.erb 模板(假设它是 .erb 模板,否则它可能是 .haml 等模板)。

_form.html.erb 模板(如果存在)通常具有许多列为表单字段的属性。

form_for块中,检查它是否显示类似f.text_field :name的内容,这意味着有一个名为“名称”的属性/(表中的列)。您可以通过它是什么类型的字段来推断该列应该是什么类型。例如。在这种情况下,它是一个字符串,所以 VARCHAR(255) 可能是合适的(在 Rails 中称为字符串)。

您可能还需要根据属性的名称来推断哪种类型是合适的(例如,如果它提到类似 :time 的内容,那么它可能是 Time 或 DateTime 类型)。

这可能会为您提供表中的所有其他属性。但在某些情况下,您可能会错过这些属性。如果您在控制器中找到对其他属性的引用,例如。app/controllers/user_groups_controller.rb,那么您应该将其添加为表中的列。但是,您可以在测试时将其保留到最后,因为在测试时,如果缺少某个属性,那么它将为相关模型的对象抛出 NoMethodError 。例如。如果它说 UserGroup 类的 @user_group 变量缺少一个名为 title 的方法,那么它可能缺少一个名为“title”的字符串类型的列。


重新创建您的迁移/数据库

好的,现在您知道数据库表和列名和类型应该是什么了。

您应该为您的数据库生成/重新创建迁移。

为此,只需使用命令rails generate migration RecreateTables

然后你应该在db/migrate/???_recreate_tables.rb.

在里面,开始编写 ruby​​ 代码来创建表。可以在http://guides.rubyonrails.org/migrations.html找到这方面的参考。

但本质上,你会得到类似的东西:

class RecreateTables < ActiveRecord::Migration
  def up
    create_table :user_groups do |t|
      t.string :name # adds a string (VARCHAR) column called "name"
      t.text :description # adds a textarea type column called "description
      t.timestamps # adds both "created_at" and "updated_at" columns for you
    end
  end

  def down
    drop_table :products # this is the reverse commands to undo stuff in "up"
  end
end

要重新创建您的 Gemfile:

首先添加一个默认的 Gemfile。这可以通过在rails new testapplication某个地方创建一个空的 Rails 应用程序来完成。然后将 Gemfile 复制到您的实际应用程序中。它将通过包含 rails 和其他常见的 gem 来帮助您入门。

很难准确地确定需要什么宝石。您可以做的最好的事情是在查看代码时尝试将它们一一添加。

同样,在这里,MethodNotFound 错误是您的朋友。当您测试应用程序时,根据您添加的 gem,它可能会检测到一些缺失的方法,这些方法可能由 gem 提供。模型上的一些缺失方法可能表明缺少宝石(或者它们可能表明数据库中缺少字段/列)。但是,Controller 或 ActiveRelation 类上缺少方法很可能是因为缺少 gem。

您将不得不查看代码并尝试推断要添加哪些 gem。

如果它使用can, can?, 之类的方法并且有一个文件app/models/ability.rb,那么你需要gem 'cancan'. 如果它调用devise一个模型,它需要gem 'devise'. 在http://ruby-toolbox.com可以看到许多常见的 gem 。

将 gem 添加到 Gemfile 后,您应该bundle在命令行上运行以安装新的 gem,然后再次测试。当你再次测试它时,你应该重新启动你的测试服务器。重新运行bundle exec rails server以启动本地测试服务器localhost:3000或类似的东西。

您可以简单地从 复制 Rakefile rails new testapp,它可能会包含您需要的所有内容。

缺少测试

缺少的 test/ 目录与您的实际应用程序无关。不需要运行应用程序。但是,它确实包含自动脚本来测试您的应用程序。如果您想自动测试您的应用程序,您将不得不重新编写新的测试。但是,为了备份您的应用程序,您现在可以忽略它。

缺少供应商目录

一些额外的代码不是作为 gem 安装的,而是作为插件安装的。如果您没有供应商目录,则作为插件安装的任何内容都会丢失。与 gems 一样,您能做的最好的事情就是尝试推断可能丢失的内容,然后重新下载丢失的插件,或者重新安装插件,或者使用 gem 替换。


附加提示:

  • 尝试阅读一些评论,其中可能会列出一些使用的宝石。

  • 如果缺少一个或一组方法,您认为不是数据库字段/列,则可能是由于缺少 gem。最好的办法是在 google 上搜索这些方法名称。例如。如果缺少“paginate”,您可以搜索“rails paginate gem”,看看您可能需要哪些宝石。这个例子可能会出现“will_paginate”和“kaminari”。然后,您必须尝试推断需要哪些宝石。也许grep will_paginate app -r在命令行上做一个看看它是否正在使用将分页。grep 命令在名为“app”的目录中搜索字符串“will_paginate”,-r 使其递归地对所有文件执行此操作

于 2012-09-02T03:59:33.170 回答
2

尽管 rails 是一个全栈 Web 框架,但它也可以在没有某些部分的情况下工作,如果您愿意,

例如:在你的情况下

db - 目录用于保存迁移以创建数据库/表,但如果您使用的是旧数据库或数据库内容由数据库管理员处理,您可能不想要它。(您可以通过 database.yml 文件简单地连接到数据库)

Gem 文件帮助您将所有 gem(库)保存在一个地方,就像使用 Maven(在 java 中)一样

test,如果你写过测试用例(这绝对是个坏主意),你确实需要这个

vendor,用于 3rd 方插件, doc 用于文档,所以同样的规则适用,如果你确实需要它们,你可以跳过它们

在rails中休眠称为“Activerecord”,相同的概念,模型与数据库表绑定(技术上模型表示表中的原始数据)

因此,如果您真的想要他们添加它们,但如果不只是离开它们

但是,我认为拥有一个合适的 Gem 文件和测试用例是必须的

欢迎来到 Rails

高温高压

于 2012-07-31T14:34:28.847 回答
2

在下文中,我假设您已经知道如何:

  • 将您的数据库模式转储到 SQL 文件中
  • 启动 Rails 控制台 ( rails c)
  • 生成 Rails 迁移

这是我认为你应该做的。

  1. 确定您的哪些类对应于物理表(您在问题中提到了一些视图,这使我相信您的模型的一个子集绑定到数据库视图而不是实际表)。为此,您需要将模型的定义(扩展 ActiveRecord::Base 的类)与CREATE TABLE模式转储中的语句相匹配。例如,class Person在您的 Ruby 代码中匹配到CREATE TABLE people在您的 DB 模式转储中。

  2. 一旦您确定了这些模型(类名),您就启动了一个 Rails 控制台并输入这些模型名称,一次一个,然后按 Enter。一个名为 Person 的模型的控制台输出大概如下所示:

>> Person
=> Person(id: integer, first_name: string, last_name: string)

You then take what's inside the parentheses, strip the leading id: integer,, get rid of commas, get rid of those blanks after the colons, thus obtaining something like this:

first_name:string last_name:string

Having done this, the command to generate the migration would look like this:

rails g migration Person first_name:string last_name:string

You then start a new Rails project somewhere else, perform all of these migrations and inspect the contents of db/migrate. Your migrations are most likely 90% done, what you still need to do is replace some instances of t.integer with t.references, and other minor stuff that's completely domain-specific and impossible to capture in a generic answer.

HTH.

于 2012-09-02T09:09:48.390 回答