我目前正在尝试将从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)。
我认为你是对的,这不是哈希。所以现在我对如何在我的数据库中存储它感到非常失望哈哈。我试着在没有序列化的情况下存储它,但是我得到了它看似转换为字符串的相同问题。
答案 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。