Ruby on rails 在Rails 5中,如何使Rails将所有属性保存在种子文件中定义的对象中?
编辑: 尝试替代解决方案,但使用此数据Ruby on rails 在Rails 5中,如何使Rails将所有属性保存在种子文件中定义的对象中?,ruby-on-rails,find,updates,ruby-on-rails-5,seed,Ruby On Rails,Find,Updates,Ruby On Rails 5,Seed,编辑: 尝试替代解决方案,但使用此数据 crawlers = [] crawler1 = WebCrawler.new({ class_name: "MyObjectService", start_url: "stuff?format=json&key=88b3284d4b892b430767b830d0c0eb51", begin_with_start_url: false, active: true }) crawlers.push(crawler1) 对ra
crawlers = []
crawler1 = WebCrawler.new({
class_name: "MyObjectService",
start_url: "stuff?format=json&key=88b3284d4b892b430767b830d0c0eb51",
begin_with_start_url: false,
active: true
})
crawlers.push(crawler1)
对rake db:seed的调用失败,出现以下消息。显然,即使该行已经存在,Rails也试图用空值更新其id列
rake aborted!
ActiveRecord::StatementInvalid: PG::NotNullViolation: ERROR: null value in column "id" violates not-null constraint
DETAIL: Failing row contains (null, MyObjectService, null, null, stuff/500?format=json&key=88b3284d4b892..., null, f, t, null, null, null, 1).
: UPDATE "web_crawlers" SET "id" = $1, "start_time" = $2, "end_time" = $3, "active" = $4, "created_at" = $5, "updated_at" = $6 WHERE "web_crawlers"."id" = $7
/Users/davea/.rvm/gems/ruby-2.4.0@global/gems/activerecord-5.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:598:in `async_exec'
/Users/davea/.rvm/gems/ruby-2.4.0@global/gems/activerecord-5.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:598:in `block in exec_no_cache'
/Users/davea/.rvm/gems/ruby-2.4.0@global/gems/activerecord-5.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:589:in `block in log'
编辑:
这种方法不需要在许多地方更新代码。我们使用.attributes
获取.new
调用中分配的一组属性。然后我们检查以找到一个WebCrawler
实例,该实例定义了每个爬虫实例的class\u name
。从那里我们更新或创建
crawlers = []
crawler7 = WebCrawler.new({
class_name: "MainService",
start_url: "...",
...
})
crawlers.push(crawler7)
crawlers.each do |c|
web_crawler = WebCrawler.find_by(class_name: c.attributes['class_name'])
if web_crawler
web_crawler.update(c.attributes)
else
c.save
end
end
请参阅标题下的第一句话:“查找具有给定属性的第一条记录,如果未找到,则创建具有该属性的记录。”由于给定属性只是名称,因此它违反了您的验证。请参阅文档了解:
查找具有给定属性的第一条记录,如果未找到,则创建具有这些属性的记录
由于您只将class\u name
属性传递给find\u或\u create\u by
,因此创建的记录没有设置其他属性。(请注意,new
或initialize
仅初始化内存中的Ruby对象,只有update
、save
或create
等方法才能将记录写入数据库。)
与其调用WebCrawler.new
,然后将这些对象的属性传递给单独的find\u或\u create\u by
调用,更简单的方法是从一开始调用finder方法,使用附加参数更新新创建或现有的记录:
...
crawler7 = WebCrawler.find_or_initialize_by(
class_name: "MainService"
).update!(
start_url: "...",
...
)
# Done- the record is created/updated in the database
注:
find_或
,因为update
之后将在下一步将记录保存到数据库中...
crawler7 = WebCrawler.new({
class_name: "MainService",
start_url: "...",
...
})
crawlers.push(crawler7)
#
# Create the crawlers
crawlers.each do |c|
crawler = WebCrawler.find_or_initialize_by(class_name: c.class_name)
crawler.update!(c.attributes)
end
这种方法不太简单(因为它迭代所有对象两次),效率也不高(因为它在每个记录中初始化2个Ruby对象),但它仍然可以完成任务。Model\35; new只实例化一个对象,但不会将其持久化到数据库中,您仍然需要在实例上调用Model\35; save
模型#create立即在数据库中创建它,假设它通过了验证。这将修复错误消息中的空问题。实际上,您正在尝试更新尚未持久化的对象。您可以通过“持久化”菜单检查此项?方法 find_或_create_by()帮助您查找具有给定属性的第一条记录,或者在未找到属性的情况下创建具有这些属性的记录。现在出现错误是因为它找不到指定的类名(c.class_name),并尝试通过仅传递类名来创建新的类名,而其他字段为非空列并导致错误…如果是我,我将尝试查找,如果是查找,则更新,否则创建它。“查找”或“创建”在本例中被误用。嗨,我不理解你的评论。该记录不存在于类名中,因此应该创建它,但它不是使用我提供的所有信息创建的。在我的替代解决方案中,您不需要立即将爬虫分配给对象,它们是散列。不确定你是否这样做了,但这并没有反映在你更新的问题中。请让我知道,如果你给了一个尝试!哦,我一定是误会了。但是,在您的替代解决方案中,这一行--“crawlers.each do | c |”意味着crawlers是一个数组(这是我最初使用它的方式)。你是说“爬虫”是一个散列?我的理解是你有很多爬虫对象的声明作为种子信息。我没有用
.new
初始化它们,而是将它们做成散列,然后它们都被推送到一个数组中,就像您最初使用的那样。然后,它们被循环,并根据需要更新或创建DB对象。我将编辑我的答案,使其更明确。所以我正确理解你的解决方案,你说的不是在一个地方更改代码,而是我必须更改我声明的所有“爬虫”对象?因此,如果我声明50个对象,我需要在50个位置更新代码,对吗?@Dave是的,要实现我描述的解决方案,您需要更改现有代码。如果更改代码的最小努力很重要,您可以使用另一种方法(请参见编辑)。遗憾的是,在我尝试运行此操作时,出现了错误,“id”列中的“PG::NotNullViolation:error:null值违反了not null约束”。我没有在我的对象定义中指定id,所以可能这就是它变得混乱的原因?Nvm,如果我将行更改为“web_crawler.update(c.attributes.except(“id”、“created_at”、“updated_at”)),一切都会正常工作