Как я могу перебрать объект хеш-данных и хранить в базе данных SQLite в рельсах? - PullRequest
0 голосов
/ 24 января 2019

Я работаю с данными JSON. Извлечение данных JSON из URL с использованием httparty gem работает отлично. Теперь я хочу перебрать объект хеш-данных и сохранить его в базе данных SQLite.

# HTTParty response
@sett = {
  "restaurant_name": "Restaurant 3",
  "address": "xyz address",
  "country": "United States",
  "currency": "USD",
  "client_key": "12345",
  "client_name": "Client 3"
}

Я хочу сохранить эти данные JSON в базе данных следующим образом:

+-----------------+---------------+
| meta_key        | meta_value    |
+-----------------+---------------+
| restaurant_name | abc restatant |
| country         | USA           |
| ...             | ...           |
+-----------------+---------------+

def index
  require 'httparty'

  @setting = HTTParty.get(
    'http://codekyt.in/froodle-wp/wp-json/data/v2/projects?client_key=12345',
    headers: { 'Content-Type' => 'application/json' }
  )
  @sett = @setting.parsed_response

  @sett.each_key do |key, value|
    m = Setting.new
    m.meta_data = key
    m.meta_value = value
    m.save
  end
end

Хранится, но в формате массива, а не хеш.

В базе данных,

t.string :meta_data
t.string :meta_value

Ответы [ 2 ]

0 голосов
/ 24 января 2019

В вашем примере кода есть пара ошибок.

  1. Когда вы перебираете хеш, вы используете Hash#each_key. Который только циклически перебирает ключи, а не значения.

    @sett.each_key do |key, value|
    #                         ^- will always be nil
    

    Чтобы правильно пройти по парам ключ / значение, используйте Hash#each.

  2. Вы звоните save в пустом контексте. Что происходит, когда запись не может быть сохранена? В настоящее время он устанавливает ошибку в записи настроек и возвращает false, но и возвращаемое значение, и ошибки игнорируются. Это означает, что если запись по какой-либо причине не может быть сохранена, она просто игнорируется. Возможно, вы захотите использовать save! вместо этого, чтобы вызвать исключение в случае сбоя. В качестве альтернативы вы можете обработать возвращаемое значение save.

  3. Откуда вы знаете, какие записи принадлежат друг другу? Вы просто сохраняете meta_data и meta_value. Что происходит, когда вы сохраняете настройки из более чем одного запроса?

    Эту проблему можно решить, добавив связь с другой моделью. В результате чего код:

    request = Request.create!(url: url)
    
    @sett.each do |key, value|
      request.settings.create!(
        meta_data: key,
        meta_value: value
      )
    end
    

    В качестве альтернативы вы можете использовать управление этим столбцом самостоятельно, например:

    request_nr = Setting.maximum(:request_nr) || 0
    request_nr += 1
    
    @sett.each do |key, value|
      Setting.create!(
        request_nr: request_nr,
        meta_data: key,
        meta_value: value
      )
    end
    

Если указанные выше проблемы устранены, вы можете преобразовать набор записей в хеш, выполнив следующие действия.

# First you need to fetch the records that belong together.
Setting.where(request_nr: 1)
#=> #<ActiveRecord::Relation [#<Setting id: 1, meta_data: ...>, ...]>

# The above will result in an collection of records, however we only care 
# about the key/value. We can use `pluck` to get those values.
Setting.where(request_nr: 1).pluck(:meta_data, :meta_key)
#=> [["restaurant_name", "Restaurant 3"], ["address", "xyz address"], ...]

# The above array can be converted to a hash by simply calling `to_h` on it.
Setting.where(request_nr: 1).pluck(:meta_data, :meta_key).to_h
#=> { "restaurant_name" => "Restaurant 3", "address" => "xyz address", ... }

Ссылка:

Я уже предоставил большинство ссылок в самом ответе. Однако вот некоторые методы, используемые в кодовых блоках, которые не упомянуты в тексте.

0 голосов
/ 24 января 2019

В миграции добавьте

def change
  add_column :settings, :meta_data, :json
end

Или, в случае создания новой таблицы,

t.json :meta_data # storing meta_data & meta_value in your code

В setting.rb модели,

serialize: :meta_data, JSON

И вваш код, измените как,

  @setting = HTTParty.get(
    'http://codekyt.in/froodle-wp/wp-json/data/v2/projects?client_key=12345',
    :headers =>{'Content-Type' => 'application/json'}
  )
  Setting.create(meta_data: @setting.parsed_response)

Небольшие изменения относительно связанного объекта, который будет сохранен выше, могут быть сделаны согласно вашей ситуации

...