【问题标题】:How to use Faker gem without a model in Ruby On Rails?如何在 Ruby On Rails 中使用没有模型的 Faker gem?
【发布时间】:2020-07-11 12:07:20
【问题描述】:

第一次在这里发帖。我目前有一个 Ruby on Rails 项目,其中有一个 PostgreSQL 数据库。我最近在 PostgreSQL 数据库中创建了一个表,我想生成假数据来填充它。问题是我通常这样做的方式是使用模型,而我的 PostgreSQL 数据库中的表没有该模型。我通常会这样做:

50.times do
  Model.create({ ...properties })
end

如果我没有模型,我该怎么做?可以用表名来做吗?如果我只使用表名(没有模型),我会收到此错误:NameError: uninitialized constant。

任何帮助表示赞赏:)

aburr 完美回答了我的问题!

【问题讨论】:

  • 为什么要测试超出应用业务逻辑范围的数据?

标签: ruby-on-rails ruby postgresql faker


【解决方案1】:

我的第一个想法是,如果您没有与 SQL 表关联的任何类型的模型或类,那么您可以执行 SQL insert 语句。

可能是这样的

require 'pg'
require 'faker'

db =  PG.connect({:dbname => 'my_db_name'})

50.times do
  db.exec("insert into Users (name) values(#{Faker::Name.name}")
end

这是 Faker 自述文件https://github.com/faker-ruby/faker/blob/master/README.md#usage

以及在 Ruby 中使用 SQL 的参考http://zetcode.com/db/postgresqlruby/

【讨论】:

  • 您缺少值周围的引号,以及将其评估为代码所必需的 #{}。为避免这种情况以及一堆安全漏洞,请使用exec_params。 db.exec_params('insert into users (name) values ($1)', [Faker::Name.name]).
  • 您仍然缺少名称值周围的引号。考虑insert into Users (name) values('Some name')。注意Some name 周围的引号。由于您要传入一个字符串,因此您需要添加这些引号。如果Sean O'Exploit 注册,您还需要转义该名称。 db.exec("insert into Users (name) values('#{db. escape_string(Faker::Name.name)}'")。同样,不要向带有字符串的查询添加值。使用参数。它避免了一大堆错误和one of these most common security holes。
  • 这样做很有效!只需在值内部按照 '#{Faker::Name.name}' 的行做一些事情!
【解决方案2】:

问题不在于 gem 'faker',实际上它是一个假数据生成器。所以问题是关于 ActiveRecord,你需要找到关于 ActiveRecord 的文档。
通常,Model.create(foo: 'bar') 表示insert into Model (foo) values('bar')。
所以 ActiveRecord 有原始的 sql 操作,以防你有一些更复杂的场景ActiveRecord::Base.connection.execute(sql)。
如果您有机会使用gem sequel,您将对幕后有更多的了解。

  • 数据库(MySQL、PG)
  • 数据库连接器(mysql2,pg)
  • ORM(ActiveRecord,续集)

这就是您处理数据库所需的全部内容。

【讨论】:

    【解决方案3】:

    我建议为桌子制作一个模型。这是微不足道的。如果您使用的是 Rails 6,则可以使用 insert_all 显着加快创建速度。

    class SomeThing < ApplicationRecord
    end
    

    如果您不想这样做,可以使用exec_insert 手动执行插入操作。

    ActiveRecord::Base.connection.exec_insert(
      'insert into some_thing (first_name, last_name) values ($1, $2)',
      nil,
      [[nil, Faker::Name.first_name], [nil, Faker::Name.last_name]]
    );
    

    最后,考虑使用FactoryBot,而不是手动编写50.times { SomeThing.create(...) }。

    factory :some_thing do
      name { Faker::Name.name }
    end
    
    FactoryBot.create_list(:some_thing, 50)
    

    【讨论】:

      猜你喜欢
      • 2016-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-30
      • 1970-01-01
      相关资源
      最近更新 更多