Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/53.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在Rails 5中,如何使Rails将所有属性保存在种子文件中定义的对象中?_Ruby On Rails_Find_Updates_Ruby On Rails 5_Seed - Fatal编程技术网

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”)),一切都会正常工作