How to get serialized column list on RoR - ruby-on-rails

I'm user of Ruby on Rails.
I made active model like this.
class User < ActiveRecord::Base
attr_protected :id
serialize :user_info, Hash
serialize :user_auth, Array
serialize :user_addr
end
I want to get the column names which contains a serialized object and type.
I'm looking forward to the method like this.
ex )
User.serialized_columns #=> {:user_info => Hash, :user_auth => Array, :user_addr => nil}
Would you help me?

Yes, you can get it using the method serialized_attributes which returns a Hash where key is the column name and value is the class of the column
So, you can get the serialized columns as
User.serialized_attributes
But you have modify the value of each key according to your requirement.

Related

ActiveRecord serialize not working properly with Hash column

I'm trying to store a Hash in a table column, using ActiveRecord's serialize method but I can't make it work. I'm using Rails 4.2.0 and RailsApi 0.3.1
This is my model:
class Agreement < ActiveRecord::Base
serialize :phone_numbers, Hash
end
phone_numbers is a text column like it's required.
Then in the console:
a = Agreement.new(phone_numbers: {"dario" => "12345"})
a.phone_numbers
=> "{\"dario\"=>\"12345\"}" #(Note this is a string, not a Hash as I would expect)
a.phone_numbers["dario"]
=> "dario" #(Not "12345" as I would expect)
Am I missing soemthing?? Thank you!
The behavior you're showing is consistent with the serialize call being wrong, either misnamed column, or missing entirely. Eg. https://gist.github.com/smathy/2f4536d3e59b7a52c855
You're showing the right code in your question, so either you didn't copy-paste that correctly, or perhaps it you haven't restarted your rails console since adding/correcting that serialize call?

when to use attributes hash

In this SO answer undefined method `stringify_keys!' ruby on rails, the OP tried to create a new car object with a 'Honda' string to the
#car = Car.new(params[:car])
and got a stringify keys error. The person who answered said that he had to specify the column from the table (in this case the 'name' column) when creating the object ,
create expects to get an attributes hash and to stringify it's keys for the column names.
If you have a column named name in your cars table then try this:
#car = Car.new(:name => params[:car])
However, I'm watching a RailsCast where Rbates creates an entry table with 'name' string and a column 'winner' as a boolean. In his controller (which he's set to respond with json), he does not use an attributes hash. His create action
def create
respond_with Entry.create(params[:entry])
end
Why didn't Rbates have to use an attributes hash, and, if he could have, what would that attributes hash look like? Something like this? Do you have to name every column, in ryans case :name and :winner?
def create
respond_with Entry.create(:name => params[:entry][:name], :winner => params[:entry] [:winner]
end
It all depends on what params[:car] contains. In the Railscast example, params[:car] is a Hash containing two entries (name and winner). In the other SO question it looks like params[:car] was a String containing the name of a car.
Car.new will always expect a Hash. If you want to pass a single value you need to turn it into a Hash with a key that tells Car.new what value you're passing.
In the previous question, params[:car] was a string. Rails's new and create methods both expect hashes, which is why the code was altered to pass in :name => params[:car]
If you use Rails's form_for to construct your forms, params[:model_name] will have a hash which keys matching model attributes. In that case, no custom work is necessary, and simply initializing the model with params[:model_name] works fine.

Saving an hash as a string, reform it later

I want to be able to save a params[:object] hash in a text field of a drafts table, to keep this hash saved and pull it out later. I want to know if it's possible to do so that I get a hash out later, with functionality.
Right now, when I am saving a post in here, so I have the following line:
#draft = user.drafts.build(:content => params[:post])
This saves the params[:post] hash as:
"--- !map:ActiveSupport::HashWithIndifferentAccess \ntitle: asdfasdfasdf\ncontent: \"\"\ndiscussion_id: \"87\"\ndraft: \"false\"\n"
If I find the draft (ie d = Draft.find(1)) and then I try to pull this hash out, I just get the string value here.
Is there some way I can reform this into a hash? Or is there a better way to go about saving the params hash in the first place?
Thanks
Check out the class method serialize in ActiveRecord::Base:
class Draft < ActiveRecord::Base
serialize :content, Hash
end
It should save a fair amount of time over doing this yourself!

Rails data design for multiple date picker

I have an Appointment model, whose available_dates can include multiple dates (say, available in Jan 1, 5, 6 and 7).
My question is very basic: how should I store available dates for each event?
What I can think of is a table Avaiable_Dates with two columns: event_id and date. Each event would have multiple rows, one date per row. It seems to be cumbersome to query entire table to make sure we got all dates of an event. A Hash {event => {date1, date2, date3}} would be faster, but I don't know how to implement it using ActiveRecord.
Thank you.
It might not be a bad idea to just use the separate model for available times, but if you decide to go the hash route you can do so using the serialize keyword. You have to tell ActiveRecord to serialize the variable, and then it will do the serialization and deserialization automatically whenever you access the hash.
Saving arrays, hashes, and other non-mappable objects in text columns
Active Record can serialize any object in text columns using YAML. To do so, you must specify this with a call to the class method serialize. This makes it possible to store arrays, hashes, and other non-mappable objects without doing any additional work.
class User < ActiveRecord::Base
serialize :preferences
end
user = User.create(:preferences => { "background" => "black", "display" => large })
User.find(user.id).preferences # => { "background" => "black", "display" => large }
You can also specify a class option as the second parameter that’ll raise an exception if a serialized object is retrieved as a descendant of a class not in the hierarchy.
class User < ActiveRecord::Base
serialize :preferences, Hash
end
user = User.create(:preferences => %w( one two three ))
User.find(user.id).preferences # raises SerializationTypeMismatch
When you specify a class option, the default value for that attribute will be a new instance of that class.
class User < ActiveRecord::Base
serialize :preferences, OpenStruct
end
user = User.new
user.preferences.theme_color = "red"
From rubyonrails.org
From a design perspective, if you think you will ever add any more data to the available time object then you should make it its own model. Otherwise a serialized hash seems fine.
I don't see a problem with the separate table that you mentioned, I would go with that. It will also be easier to extend later which you will appreciate when the time comes.

Suggestion needed for keeping hash value in the table in rails

As an extension of the question
How to retrieve the hash values in the views in rails
I have some doubts of keeping hash values in the table..
I have a user detail table where i am maintaining the additional details of the user in a column named additional_info in a hash format .. Will it be good in keeping like so...
As if the user scenario changes if the user wants to find all the users under a particular project where i kept the project to which the user belongs in the hash format..
Give some suggestions..
Simple solution is to serialiaze it:
class FooBar < ActiveRecord::Base
# ...
serialize :additional_info
#...
end
This internally uses the YAML serializer. You can assign any object that can be serialized using YAML.
foo = FooBar.first
foo.additional_info = {:foo => 'Lorem', :bar => 'ipsum'}
foo.save
foo.additional_info[:foo] # Gives 'Lorem'

Resources