undefined method `unserialize_attribute' in ruby on rails - ruby-on-rails

I am working on upgrading rails application, I have a method unserialize_attribue in rails 3 but I am not able to see this method in rails 5.
What is the alternative for unserialize_attribute in rails 5 or any suggestion on what can I do, Thanks

unserialize_attribute is removed from rails-5 but you can unserialized value in different way,
Method:1
> #user.accessible_attribute
# => {"attr1"=>["Email id"], "attr2"=>["First Name"], "attr3"=>["Last Name"]}
> #user.attributes_before_type_cast['accessible_attribute']
# => "--- !ruby/hash:ActionController::Parameters\nattr1:\n- Email id\nattr2:\n- First Name\nattr3:\n- Last Name\n"
Method:2
#user.instance_variable_get(:#attributes)['accessible_attribute'].value_before_type_cast
# => "--- !ruby/hash:ActionController::Parameters\nattr1:\n- Email id\nattr2:\n- First Name\nattr3:\n- Last Name\n"
Method:3
> #accessible_attribute = ActiveRecord::Base.connection.execute("SELECT accessible_attribute FROM users WHERE id = #{#user.id}")
(0.4ms) SELECT accessible_attribute FROM users WHERE id = 3
# => #<Mysql2::Result:0xe0fc374 #query_options={:as=>:array, :async=>false, :cast_booleans=>false, :symbolize_keys=>false, :database_timezone=>:utc, :application_timezone=>nil, :cache_rows=>true, :connect_flags=>-2147442171, :cast=>true, :default_file=>nil, :default_group=>nil, :adapter=>"mysql2", :encoding=>"utf8mb4", :collation=>"utf8mb4_unicode_ci", :database=>"example_development", :pool=>5, :username=>"root", :password=>"password", :socket=>"/var/run/mysqld/mysqld.sock", :flags=>2}>
> #accessible_attribute.first[0]
# => "--- !ruby/hash:ActionController::Parameters\nattr1:\n- Email id\nattr2:\n- First Name\nattr3:\n- Last Name\n"
Note: Precisely, Some prefer to take attribute value unserialized by #user.accessible_attribute.to_yaml also.

I got it working using serializable_hash and it is available in rails 3 as well as in rails 5
I have this code written in rails 3
unserialized_value = unserialize_attribute(options[:serialized_column]) || { }
which I changed to
unserialized_value = self.serializable_hash[options[:serialized_column]] || { }
both method returns the same hash object.

Related

NoMethodError - undefined method `where_values' | Upgraded from rails 4.2 to 5.0.1

I have recently upgraded my rails app from 4.2.8 to 5.0.1 with ruby 2.4.5
Facing this error
NoMethodError - undefined method `where_values' for
Query:
PlacementActivityStep.where(query_values_hash[:query_string], query_values_hash[:values])
.where_values.select{|x| x.present?}
How do I achieve the same query in rails 5.0.1 using where_clause as where_values has been removed from the new rails version??
Reference: Ruby on Rails where_values method
Following is tested in Rails 5.2.2
First, where_values was not intended for public use, see https://bugs.ruby-lang.org/issues/12962
And to get the same behavior you must do some hacks.
I don't know what you will use the generated arel code for, I prefer to make the condition directly with arel if it's a complicated condition. And you will lose some automatic type detection.
Consider this (bad example but only to show the difference):
# model Foo have column 'bar' that is sql type string
Foo.where('bar = :one OR bar = :two', one: 55, two: nil ).to_sql
=> "SELECT `foos`.* FROM `foos` WHERE (firstname = 55 OR firstname = NULL)"
# bad, the last should be "firstname IS NULL"
# use Rails "magic"
Foo.where(bar: [ 55, nil ]).to_sql
=> "SELECT `foos`.* FROM `foos` WHERE (`foos`.`firstname` = '55' OR `foos`.`firstname` IS NULL)"
# "`firstname` IS NULL" as it should be (and '55' is a string)
# if it is the arel you want, you can use it directly
fo_a = Foo.arel_table
fo_a[:bar].eq_any([ 55, nil ]).to_sql
=> "(`foos`.`firstname` = '55' OR `foos`.`firstname` IS NULL)"
# that is the same as if you where using this in Rails 4:
Foo.where(bar: [ 55, nil ]).where_values.first.to_sql
# even if you use a hackish way you will not get the same result
Foo.where(bar: [ 55, nil ]).where_clause.send(:predicates).first.to_sql
=> "(`foos`.`firstname` = ? OR `foos`.`firstname` IS NULL)"
# '55' is gone (it's a "bind value")

Rails Digest::UUID v5 (vs) Postgresql uuid-ossp v5

I'm getting different V5 UUIDs when generating with Rails Digest::UUID and Postgresql uuid-ossp.
Rails:
[58] pry(main)> Digest::UUID.uuid_v5('e90bf6ab-f698-4faa-9d0f-810917dea53a', 'e90bf6ab-f698-4faa-9d0f-810917dea53a')
=> "db68e7ad-332a-57a7-9638-a507f76ded93"
Postgresql uuid-ossp:
select uuid_generate_v5('e90bf6ab-f698-4faa-9d0f-810917dea53a', 'e90bf6ab-f698-4faa-9d0f-810917dea53a');
uuid_generate_v5
--------------------------------------
6c569b95-a6fe-5553-a6f5-cd871ab30178
What would be the reason? I thought both should generate the same UUID when the input is the same, but it is different!
It's not an answer to the question about why Rails produces a different result, but if you want to produce v5 UUID in your Ruby code, you could use uuidtools. It returns the same result as PSQL:
~ pry
[1] pry(main)> require 'uuidtools'
=> true
[2] pry(main)> UUIDTools::UUID.sha1_create(UUIDTools::UUID.parse('e90bf6ab-f698-4faa-9d0f-810917dea53a'), 'e90bf6ab-f698-4faa-9d0f-810917dea53a')
=> #<UUID:0x3fe09ea60dd8 UUID:6c569b95-a6fe-5553-a6f5-cd871ab30178>
[3] pry(main)>
It seems that a patch is proposed so that working string-representation of namespaces can be enabled explicitly
The new behavior will be enabled by setting the config.active_support.use_rfc4122_namespaced_uuids option to
true.
but, the patch is very recent and it could be still under test. People can be afraid it breaks things. Check
https://github.com/rails/rails/issues/37681
https://github.com/rails/rails/pull/37682/files
Meanwhile, a workaround is to pack the namespace string
ns=n.scan(/(\h{8})-(\h{4})-(\h{4})-(\h{4})-(\h{4})(\h{8})/).flatten.map { |s| s.to_i(16) }.pack("NnnnnN")
In your example
irb(main):037:0> n='e90bf6ab-f698-4faa-9d0f-810917dea53a'
=> "e90bf6ab-f698-4faa-9d0f-810917dea53a"
irb(main):038:0> ns=n.scan(/(\h{8})-(\h{4})-(\h{4})-(\h{4})-(\h{4})(\h{8})/).flatten.map { |s| s.to_i(16) }.pack("NnnnnN")
=> "\xE9\v\xF6\xAB\xF6\x98O\xAA\x9D\x0F\x81\t\x17\xDE\xA5:"
irb(main):039:0> puts Digest::UUID.uuid_v5(ns, 'e90bf6ab-f698-4faa-9d0f-810917dea53a')
6c569b95-a6fe-5553-a6f5-cd871ab30178

NoMethodError Ruby 1.9.3

I am using Ruby 1.9.3 and getting the following error on the following line while trying to use the SendGrid API.
ERROR [on this line below "mailer.mail(mail_defaults)"]:
NoMethodError (undefined method `to_h' for #<Hash:0x00000005da0958>):
CODE:
assuming some users
recipients = []
recipient = SendGrid::Recipient.new('jn#geo.com')
recipient.add_substitution('name', 'Billy Bob')
recipient.add_substitution('number', 1234)
recipient.add_substitution('time', '10:30pm')
recipients << recipient
# then initialize a template
template = SendGrid::Template.new('blahblah7bef2-d25b00')
# create the client
# see client above
# set some defaults
mail_defaults = {
:from => 'no-reply#geo.com',
:html => '<h1>I like email tests</h1>',
:text => 'I like email tests',
:subject =>'Test Email is great',
}
mailer = SendGrid::TemplateMailer.new(client, template, recipients)
# then mail the whole thing at once
mailer.mail(mail_defaults)
I thought it might be my mail_defaults array so I tried this (see below) and received the same error on the same line.
mail_defaults = {
from: 'no-reply#geo.com',
html: '<h1>I like email tests</h1>',
text: 'I like email tests',
subject: 'Test Email is great',
}
Do I have an error in my code or is their an error in SendGrids mailer.mail method?
This problem is with mail.mailer. This uses the to_h method internally, which was implemented in Ruby 2.1. Effectively, the sendgrid sdk requires ruby 2.1 now. I had the same issue with Ruby 1.9.3 and solved it by upgrading to 2.1.
This is what I used to upgrade to Ruby 2.1 on CentOS 6 (not my gist):
https://gist.github.com/mustafaturan/8290150
Hope this helps.

Upgrading Rails 3.2 app to Rails 4, Strong Params behaving strange

I'm in the middle of the process of upgrading a Rails 3.2 app to Rails 4.
I'm working on replacing the attr_accessible from the models with Strong Params in controller.
I noticed that the #permit method behaves a bit different on the 3.2 I'm upgrading than it should behave in a Rails 4 app. In order to validate my suspicion I created a new Rails 4 app from scratch and tested the same code while getting a different outcome:
Rails 3.2 app that is currently being upgraded
[9] pry(main)> x = { attr1: { attr2: "val1", attr3: "val2"}, attr4: "val3", attr5: "val4", attr6: { attr7: "val5"}}
=> {:attr1=>{:attr2=>"val1", :attr3=>"val2"}, :attr4=>"val3", :attr5=>"val4", :attr6=>{:attr7=>"val5"}}
[10] pry(main)> params = ActionController::Parameters.new x
=> {"attr1"=>{"attr2"=>"val1", "attr3"=>"val2"}, "attr4"=>"val3", "attr5"=>"val4", "attr6"=>{"attr7"=>"val5"}}
[11] pry(main)> params.require(:attr1)
=> {"attr2"=>"val1", "attr3"=>"val2"}
[12] pry(main)> params.permit(:attr1)
ActionController::UnpermittedParameters: found unpermitted parameters: attr1, attr4, attr5, attr6
[19] pry(main)> params.permit(:attr4)
ActionController::UnpermittedParameters: found unpermitted parameters: attr1, attr5, attr6
Rails 4 app
2.2.3 :009 > x = { attr1: { attr2: "val1", attr3: "val2"}, attr4: "val3", attr5: "val4", attr6: { attr7: "val5"}}
=> {:attr1=>{:attr2=>"val1", :attr3=>"val2"}, :attr4=>"val3", :attr5=>"val4", :attr6=>{:attr7=>"val5"}}
2.2.3 :012 > params = ActionController::Parameters.new x
=> {"attr1"=>{"attr2"=>"val1", "attr3"=>"val2"}, "attr4"=>"val3", "attr5"=>"val4", "attr6"=>{"attr7"=>"val5"}}
2.2.3 :013 > params.require(:attr1)
=> {"attr2"=>"val1", "attr3"=>"val2"}
2.2.3 :014 > params.permit(:attr1)
=> {}
2.2.3 :032 > params.permit(:attr4)
=> {"attr4"=>"val3"}
I use the protected_attributes gem during the upgrade and I also placed this code in config/initializers/strong_parameters.rb:
ActiveRecord::Base.send(:include, ActiveModel::ForbiddenAttributesProtection)
# config.action_controller.always_permitted_parameters = %w( controller action format )
module ActionController
class Parameters
remove_const(:NEVER_UNPERMITTED_PARAMS) if (defined?(NEVER_UNPERMITTED_PARAMS))
NEVER_UNPERMITTED_PARAMS = %w( controller action format)
end
end
Do you have any idea what the problem might be?
You'll need to permit all nested parameters, see here: http://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit.
So in your case, for the first attribute you should do
params.permit(attr1: [:attr2, :attr2])
and likewise for the other parts of your hash.
Apparently the reason I was getting this error was because I had this setting in my config/application.rb
config.action_controller.action_on_unpermitted_parameters = :raise
Deleting it gave me the ability to permit only the params I wanted.

Rails to_json Why are timestamps breaking, and being set to 2000-01-01T01:31:35Z

I'm building a json object in rails as follows:
#list = Array.new
#list << {
:created_at => item.created_at
}
end
#list.to_json
Problem is this gets received by the browser like so:
"created_at\":\"2000-01-01T01:31:35Z\"
Which is clearly not right, in the DB it has:
2011-06-17 01:31:35.057551
Why is this happening? Any way to make sure this gets to the browser correctly?
Thanks
You need to do some testing / debugging to see how that date is coming through.
For me, in Rails console (Rails 3.0.9, Ruby 1.9.2)
ruby-1.9.2-p180 :014 > d = Date.parse("2011-06-17 01:31:35.057551")
=> Fri, 17 Jun 2011
ruby-1.9.2-p180 :015 > #list = {:created_at => d}
=> {:created_at=>Fri, 17 Jun 2011}
ruby-1.9.2-p180 :016 > #list.to_json
=> "{\"created_at\":\"2011-06-17\"}"
i.e. it's just fine. Can you see whether the date is really ok?
The trouble lies with the way to_json escapes characters. There is a very good post on the subject here:
Rails to_json or as_json
You may need to look into overriding as_json.

Resources