如何编写将一张数据转换为记录的方法?

时间:2017-01-26 19:46:00

标签: ruby-on-rails ruby

我想收集数据然后编写一个方法来根据所述数据生成记录。运行该方法后,我希望有一系列的电影和电影关系(将相似的电影相互关联)。每部电影都将通过MovieRelation制作titlerelease_date和几部相似的电影。每个MovieRelation都有movie_a_idmovie_b_id

我提出的最简单的方法是编写一个文本文档,其中包含电影及其各自的数据,由两个不同的特殊符号分隔,以标记文本应分解为单独的电影的位置,以及电影应该分解成各自的数据,如下所示:

Title@Release Date@Similar Movie A@Similar Movie B%Title2@Release Date2@Similar Movie 2A@Similar Movie 2B@Similar Movie 2C

然后我可以将原始文本复制并粘贴到类似于此的方法中:

"X Men@11-02-2010@Hulk@Logan%Sing@12-04-2017@Zootopia@Pitch Perfect@Monster U"
.split('%').map.each do |movie_data|
  @movie = Movie.create()
  movie_data.split('@').map.each_with_index do |individual_data, index|
    if index == 1
      @movie.name = individual_data
    elsif index == 2
      @movie.release_date = individual_data
    elsif index > 2
      MovieRelation.create(movie_a_id: @movie.id, movie_b_id: Movie.find_by(name: individual_data))
    end
  end
  @movie.save
end

所以最后,我应该有2部电影和5部电影关系。

我认为这样可行,但看起来很糟糕。有没有更好的方法来实现这一目标?

2 个答案:

答案 0 :(得分:1)

在您开始尝试创建自己的格式之前,我建议您查看YAML或JSON,它们已经很好地建立,得到很好的支持,是具有已建立语法的互联网标准,并且具有针对主要语言的解析器/序列化程序,因此您的数据不会仅限于您的应用程序。

这是一个起点:

require 'yaml'

data = {
  'title' => 'Raiders of the Lost Ark',
  'release_date' => '12 June 1981',
  'similar_movies' => [
    {
      'title' => 'Indiana Jones and the Last Crusade',
      'release_date' => '24 May 1989',
      'similar_movies' => nil
    },
    {
      'title' => 'Indiana Jones and the Temple of Doom',
      'release_date' => '23 May 1984',
      'similar_movies' => nil
    }
  ]
}

puts data.to_yaml

输出:

---
title: Raiders of the Lost Ark
release_date: 12 June 1981
similar_movies:
- title: Indiana Jones and the Last Crusade
  release_date: 24 May 1989
  similar_movies: 
- title: Indiana Jones and the Temple of Doom
  release_date: 23 May 1984
  similar_movies: 

使用Psych类解析YAML,请参阅Psych文档的loadload_fileload_stream方法,以了解如何阅读该数据和将其转换回Ruby对象。

同样,您可以使用JSON:

require 'json'

puts data.to_json

哪个输出:

{"title":"Raiders of the Lost Ark","release_date":"12 June 1981","similar_movies":[{"title":"Indiana Jones and the Last Crusade","release_date":"24 May 1989","similar_movies":null},{"title":"Indiana Jones and the Temple of Doom","release_date":"23 May 1984","similar_movies":null}]}

或者,如果您需要"漂亮":

puts JSON.pretty_generate(data)

{
  "title": "Raiders of the Lost Ark",
  "release_date": "12 June 1981",
  "similar_movies": [
    {
      "title": "Indiana Jones and the Last Crusade",
      "release_date": "24 May 1989",
      "similar_movies": null
    },
    {
      "title": "Indiana Jones and the Temple of Doom",
      "release_date": "23 May 1984",
      "similar_movies": null
    }
  ]
}

JSON允许我们使用JSON['some JSON as a string']JSON[a_ruby_hash_or_array]作为分别解析或序列化的快捷方式:

foo = JSON[{'a' => 1}]
foo # => "{\"a\":1}"
JSON[foo] # => {"a"=>1}

在任何一种情况下,尝试使用Ruby构建起始哈希并让它发出序列化版本,然后将该输出传递给文件并开始填充。

如果您想使用相关电影的ID代替名称,您必须在文件中订购您的记录,以便首先发生相关电影,记住插入后的ID是什么,然后插入它们进入你的数据。这真的很痛苦。相反,我会遍历解析数据所得的对象,提取所有相关电影,插入它们,然后插入主记录。如何做到这一点留给你去弄清楚,但它并不太难。

答案 1 :(得分:0)

解析字符串

对于您的代码,您不需要索引,ifcase,只需拆分和展示:

input = 'X Men@11-02-2010@Hulk@Logan%Sing@12-04-2017@Zootopia@Pitch Perfect@Monster U'

input.split('%').each do |movie_data|
  title, date, *related_movies = movie_data.split('@')
  puts format('%-10s (%s) Related : %s', title, date, related_movies)
end

输出:

X Men      (11-02-2010) Related : ["Hulk", "Logan"]
Sing       (12-04-2017) Related : ["Zootopia", "Pitch Perfect", "Monster U"]

保存数据

您正在尝试解决已经解决的问题。 MovieRelations属于关系数据库!

您可以使用数据库(例如使用Rails或Sequel)执行所有导入,排序和过滤。一旦完成并希望以纯文本形式导出信息,您可以将数据转储到YAML / SQL / JSON中。

使用您当前的格式,当您想要更新关系,删除电影或在title中插入%@的电影时,您只会遇到问题。 / p>