Ruby Convert Object to Hash

Ruby convert Object to Hash


class Gift
def initialize
@name = "book"
@price = 15.95
end
end

gift = Gift.new
hash = {}
gift.instance_variables.each {|var| hash[var.to_s.delete("@")] = gift.instance_variable_get(var) }
p hash # => {"name"=>"book", "price"=>15.95}

Alternatively with each_with_object:

gift = Gift.new
hash = gift.instance_variables.each_with_object({}) { |var, hash| hash[var.to_s.delete("@")] = gift.instance_variable_get(var) }
p hash # => {"name"=>"book", "price"=>15.95}

Converting an object to a hash of values in Ruby

Assuming all data you want to be included in the hash is stored in instance variables:

class Foo
attr_writer :a, :b, :c

def to_hash
Hash[*instance_variables.map { |v|
[v.to_sym, instance_variable_get(v)]
}.flatten]
end
end

foo = Foo.new
foo.a = 1
foo.b = "Test"
foo.c = Time.now
foo.to_hash
=> {:b=>"Test", :a=>1, :c=>Fri Jul 09 14:51:47 0200 2010}

Rails Object to hash

If you are looking for only attributes, then you can get them by:

@post.attributes

Note that this calls ActiveModel::AttributeSet.to_hash every time you invoke it, so if you need to access the hash multiple times you should cache it in a local variable:

attribs = @post.attributes

Converting an object to a hash in Ruby

If you can't update GameTeam to add a to_h method, then you can get the needed instance variables and make your own:

class GameTeam
def initialize(game_id, hoa, result, team_id)
@game_id = game_id
@hoa = hoa
@result = result
@team_id = team_id
end
end

obj = GameTeam.new('2012030154', 'home', 'LOSS', '30')
%i[game_id hoa result team_id].map { |ivar| [ivar, obj.instance_variable_get("@#{ivar}")] }.to_h
# {:game_id=>"2012030154", :hoa=>"home", :result=>"LOSS", :team_id=>"30"}

Convert Active Record Object into Hash

You can get it from below query,

Hash[Person.all.collect { |user| [user.email, user.attributes.except(:email).values] }]

If you want to omit other attributes like created_at & updated_at, run

Hash[Person.all.collect { |user| [user.email, user.attributes.except(:email, :created_at, :updated_at).values] }]

How do I convert a String object into a Hash object?

The string created by calling Hash#inspect can be turned back into a hash by calling eval on it. However, this requires the same to be true of all of the objects in the hash.

If I start with the hash {:a => Object.new}, then its string representation is "{:a=>#<Object:0x7f66b65cf4d0>}", and I can't use eval to turn it back into a hash because #<Object:0x7f66b65cf4d0> isn't valid Ruby syntax.

However, if all that's in the hash is strings, symbols, numbers, and arrays, it should work, because those have string representations that are valid Ruby syntax.

Convert Array of objects to Hash with a field as the key


users_by_id = User.all.map { |user| [user.id, user] }.to_h

If you are using Rails, ActiveSupport provides Enumerable#index_by:

users_by_id = User.all.index_by(&:id)

Convert an Object to hash then save it to user's column


HStore

I remembered there's a PGSQL datatype called hStore:

This module implements the hstore data type for storing sets of
key/value pairs within a single PostgreSQL value. This can be useful
in various scenarios, such as rows with many attributes that are
rarely examined, or semi-structured data. Keys and values are simply
text strings.

Heroku supports it and I've seen it used on another live application I was observing.

It won't store your object in the same way as Stripe's data attribute (for that, you'll just need to use text and save the object itself), but you can store a series of key:value pairs (JSON).

I've never used it before, but I'd imagine you can send a JSON object to the column, and it will allow you to to use the attributes you need. There's a good tutorial here, and Rails documentation here:

# app/models/profile.rb
class Profile < ActiveRecord::Base
end

Profile.create(settings: { "color" => "blue", "resolution" => "800x600" })

profile = Profile.first
profile.settings # => {"color"=>"blue", "resolution"=>"800x600"}

profile.settings = {"color" => "yellow", "resolution" => "1280x1024"}
profile.save!

--

This means you should be able to just pass JSON objects to your hstore column:

#app/controllers/profiles_controller.rb
class ProfilesController < ApplicationController
def update
@profile = current_user.profile
@profile.update profile_params
end

private

def profile_params
params.require(:profile).permit(:x, :y, :z) #-> z = {"color": "blue", "weight": "heavy"}
end
end

As per your comments, it seems to me that you're trying to store "interest" in a User from another model.

My first interpretation was that you wanted to store a hash of information in your @user.interests column. Maybe you'd have {name: "interest", type: "sport"} or something.

From your comments, it seems like you're wanting to store associated objects/data in this column. If this is the case, the way you're doing it should be to use an ActiveRecord association.

If you don't know what this is, it's essentially a way to connect two or more models together through foreign keys in your DB. The way you set it up will determine what you can store & how...

#app/models/user.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :interests,
class_name: "Support",
join_table: :users_supports,
foreign_key: :user_id,
association_foreign_key: :support_id
end

#app/models/support.rb
class Support < ActiveRecord::Base
has_and_belongs_to_many :users,
class_name: "Support",
join_table: :users_supports,
foreign_key: :support_id,
association_foreign_key: :user_id
end

#join table = users_supports (user_id, support_id)

by using this, you can populate the .interests or .users methods respectively:

#config/routes.rb
resources :supports do
post :interest #-> url.com/supports/:support_id/interest
end

#app/controllers/supports_controller.rb
class SupportsController < ApplicationController
def interest
@support = Support.find params[:support_id] # I need the post's id they are on
current_user.interests << @support
end
end

This will allow you to call @user.interests and bring back a collection of Support objects.


Okay, look.

What I suggested was an alternative to using interest column.

You seem to want to store a series of hashes for an associated model. This is exactly what many-to-many relationships are for.

The reason your data is being populated twice is because you're invoking it twice (u= is creating a record directly on the join model, and then you're inserting more data with <<).

I must add that in both instances, the correct behaviour is occurring; the join model is being populated, allowing you to call the associated objects.

What you're going for is something like this:

Sample Image

def interest_already_sent
support = Support.find params[:id]
current_user.interests << support
end

When using the method I recommended, get rid of the interest column.

You can call .interests through your join table.

When using the code above, it's telling Rails to insert the support object (IE support_id into the current_user (IE user_id) interests association (populated with the UserInterestSelf table).

This will basically then add a new record to this table with the user_id of current_user and the support_id of support.

how to covert array object to hash in rails


hash.each {|k,v| hash[k] = v.map{|e| {id: e[:id], name: e[:name]}}}

and if you can use select_all method get the array of hash, not array of object, so you doesn't need to covert object to hash.

ModelName.connection.select_all("select id, name from <table_name>;")
=> [{id:xxx, name: xxx}.......]

convert hash to object

You need to add recursivity:

class Hashit
def initialize(hash)
hash.each do |k,v|
self.instance_variable_set("@#{k}", v.is_a?(Hash) ? Hashit.new(v) : v)
self.class.send(:define_method, k, proc{self.instance_variable_get("@#{k}")})
self.class.send(:define_method, "#{k}=", proc{|v| self.instance_variable_set("@#{k}", v)})
end
end
end

h = Hashit.new({a: '123r', b: {c: 'sdvs'}})
# => #<Hashit:0x007fa6029f4f70 @a="123r", @b=#<Hashit:0x007fa6029f4d18 @c="sdvs">>


Related Topics



Leave a reply



Submit