简体   繁体   中英

how can I iterate hash data object and store in SQLite database in rails?

I am working on JSON data. Fetching JSON data from URL using httparty gem works perfectly. Now I want iterate hash data object and store in SQLite database.

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

I want to store this JSON data in the database like this:

+-----------------+---------------+
| 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

It store but in the format of array not hash.

In the database,

t.string :meta_data
t.string :meta_value

In migration, add

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

Or in case of creating new table,

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

In setting.rb model,

serialize: :meta_data, JSON

And in your code, change as,

  @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)

Little changes regarding associated object to be saved in above can be done as per your situation

There are a couple of things going wrong in your code example.

  1. When you are looping through the hash you use Hash#each_key . Which only loops through the keys, not the values.

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

    To correctly loop through key/value pairs use Hash#each .

  2. You are calling save in void context. What happens when a record cannot be saved? Currently it sets an error on the setting record and returns false , but both the return value and errors are ignored. This means that if a record for some reason cannot be saved, it's simply ignored. You might want to use save! instead to raise an exception in case of failure. Alternatively you can handle the save return value.

  3. How do you know which records belong together? You're currently simply saving meta_data and meta_value . What happens when you save settings from more than one request?

    This issue could be solved by adding an association to an other model. Resulting in the code:

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

    Alternatively you could use manage this column by yourself like so:

     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 

If the above issues are resoved you can convert a set of records to a hash by doing the following.

# 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", ... }

References:

I already provided most links in the answer itself. However here are some of the methods used in the code-blocks that aren't mentioned in the text.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM