为什么我的对象被序列化为字符串而不是我的Rails ActiveRecord DB中的文本?

时间:2018-03-23 15:45:30

标签: ruby-on-rails ruby

我目前正在尝试将从Soundcloud API访问的用户对象存储到我的本地rails ActiveRecord数据库中。该对象就像一个哈希。

这就是对象/哈希的样子:

#<SoundCloud::HashResponseWrapper avatar_url="https://i1.sndcdn.com/avatars-000296065573-ewlbh2-large.jpg" city="Brooklyn" country="United States" description="Raising The Bar Since 2007" discogs_name=nil first_name="Fool's" followers_count=7993682 followings_count=84 full_name="Fool's Gold" id=5636679 kind="user" last_modified="2018/03/09 19:40:55 +0000" last_name="Gold" myspace_name=nil online=false permalink="foolsgoldrecs" permalink_url="http://soundcloud.com/foolsgoldrecs" plan="Pro Plus" playlist_count=250 public_favorites_count=808 reposts_count=449 subscriptions=#<Hashie::Array [#<SoundCloud::HashResponseWrapper product=#<SoundCloud::HashResponseWrapper id="creator-pro-unlimited" name="Pro Unlimited">>]> track_count=1037 uri="https://api.soundcloud.com/users/5636679" username="Fool's Gold Records" website="http://smarturl.it/FoolsGoldSpotify" website_title="Spotify">

我的ActiveRecord Schema.rb

ActiveRecord::Schema.define(version: 20180323143520) do

  create_table "soundcloud_users", force: :cascade do |t|
    t.string "user_name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.text "user_hash"
  end

end

我尝试了什么: 研究如何在Ruby中序列化对象我发现我应该对“text”类型进行字段序列化。我对序列化进行了两次不同的尝试,然后对数据进行反序列化,所有这些都失败了。这是我做的:

1)序列化为哈希。

我试过的代码:

class SoundcloudUser < ApplicationRecord
  serialize :user_hash, Hash
end

然后我得到这个错误:

TypeError in SoundcloudQueriesController#create
allocator undefined for Proc

2)使用YAML序列化: 我试过的代码:

class SoundcloudUser < ApplicationRecord
  YAML::dump(:user_hash)
end

这次我没有收到错误。当我尝试访问哈希时,我在索引def中编写了这段代码,以便快速显示:

 def index
    @user = SoundcloudUser.find(2)
    @user_hash = YAML::load(@user.user_hash)
  end

但是,由于某些原因,我无法按照预期的方式访问参数,即@user_hash.followers_count

所以我决定进入rails console,看看发生了什么:

> @user = SoundcloudUser.find(6)
> @user_hash = @user.user_hash
> @user_hash.class
 => String 

因此,出于某种原因,即使活动记录中的字段是文本,它也会被存储为字符串?或者回读可能会将其转换为字符串?我真的不知道发生了什么,但有点迷失。这是我第一次序列化数据,而Soundcloud API总是返回奇怪的对象,这些对象永远不会像我期望的那样工作。 SUPER感谢任何帮助或建议!

编辑#2:

根据建议尝试使用JSON 当我按照你的规定改变我的代码时,我仍然会遇到同样的问题:

SoundCloudQueriesController.rb

  def index

  end

  def create
    @user_url = params[:soundcloud_url]
    @soundcloud_user = SoundcloudUser.new
    @query = Query.new
    @user = @query.query_user(@user_url)
    @soundcloud_user.user_name = @user.username
    @soundcloud_user.user_hash = JSON.parse(@user.to_json).symbolize_keys
    @soundcloud_user.save
  end

SoundcloudUser.rb(型号)

class SoundcloudUser < ApplicationRecord
end

输出(在rails console中查询数据库):

在rails控制台中输入以下命令: @user = SoundcloudUser.find(7) @user_hash = @ user.user_hash

这给出了哈希的以下输出(它似乎仍然用以前没有的“\”进行了奇怪的格式化):

=&GT; "{:id=>8, :kind=>\"user\", :permalink=>\"alex\", :username=>\" \", :last_modified=>\"2018/03/15 18:15:56 +0000\", :uri=>\"https://api.soundcloud.com/users/8\", :permalink_url=>\"http://soundcloud.com/alex\", :avatar_url=>\"https://i1.sndcdn.com/avatars-000208970259-vngd3i-large.jpg\", :country=>\"Germany\", :first_name=>\"Alexander\", :last_name=>\"Ljung\", :full_name=>\"Alexander Ljung\", :description=>\"Hi, my name is Alex. I like Sound. Founder & Chairman, SoundCloud.\", :city=>\"Berlin/NYC\", :discogs_name=>nil, :myspace_name=>nil, :website=>nil, :website_title=>nil, :track_count=>268, :playlist_count=>34, :online=>false, :plan=>\"Pro Plus\", :public_favorites_count=>1601, :followers_count=>185322, :followings_count=>1697, :subscriptions=>[{\"product\"=>{\"id\"=>\"creator-pro-unlimited\", \"name\"=>\"Pro Unlimited\"}}], :reposts_count=>132}"

当我尝试按照您的规定访问哈希时:

> @user_hash[:followers_count]

我收到以下消息:

TypeError: no implicit conversion of Symbol into Integer
    from (irb):6:in `[]'
    from (irb):6

奇怪的是,即使对于不是整数值的字段,它也会产生相同的错误,例如:followers_count(:username)。

我认为你是对的,这不是哈希。所以现在我对如何在我的数据库中存储它感到非常失望哈哈。我试着在没有序列化的情况下存储它,但是我得到了它看似转换为字符串的相同问题。

1 个答案:

答案 0 :(得分:1)

我在源代码中看到:

"autoload-dev": {
    "psr-4": {
      "App\\Tests\\": "tests/"
    },
    "files": [
      "vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php"
    ]
  },

此时class Query def initialize @client = Soundcloud.new(:client_id => API_KEY) end def query_user(user_url) @user_url = user_url @user = @client.get('/resolve', :url => @user_url) end end 仍然是@user个对象。 如果您想将数据存储为字符串文本,则需要先执行以下操作:

SoundCloud::HashResponseWrapper

使用db:中的符号键保存它:

@user.to_json

但你仍然无法在哈希上调用data = JSON.parse(@user.to_json).symbolize_keys sc_user = SoundcloudUser.new(user_hash: data) 。如果您想调用您需要执行的密钥值:

.key

有一些方法可以扩展您的模型,但这超出了这个问题的范围。

更新:这是您更新的控制器:

sc_user.user_hash[:username] #for example

您还需要修改您的Query类,以便能够从souncloud用户名构建用户。它看起来像这样:

class SoundcloudQueriesController < ApplicationController
  def new

  end

  def index
    @user = SoundcloudUser.find(3)
    @user_hash = @user.user_hash # but do you even need this?
  end

  def create
    sc_user_data = Query.new.get_user params[:username]
    @soundcloud_user = SoundcloudUser.create({
        user_name: sc_user_data[:username],
        user_hash: JSON.parse(sc_user_data.to_json).symbolize_keys
    })
  end

  def show

  end
end

我不确定您要使用class Query BASE_RESOLVE_URL="http://soundcloud.com/" def initialize @client = Soundcloud.new :client_id => ENV['SC_CLIENT_ID'] end def query_user(user_url) @user_url = user_url @user = @client.get('/resolve', :url => @user_url) end def get_user(username) @client.get('/resolve', url: BASE_RESOLVE_URL+username) end end 方法,或者只是删除它并使用query_user代替。在任何情况下,我分叉你的回购,让控制器创建测试传递。将发送PR。