Initializing a hash variable when creating an instance - ruby-on-rails

I am trying to initialize a class variable as a hash when I create an instance of SomeClass but I keep getting an error. Somewhat new to ruby so any help would be appreciated. Thanks
class SomeClass < ActiveRecord::Base
attr_accessible :some_hash
serialize :some_hash, Hash
def initialize(args = {})
#some_hash != {}
end
end
NoMethodError: undefined method has_key?' for nil:NilClass
from /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.3.8/lib/active_support/whiny_nil.rb:52:inmethod_missing'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:2827:in has_attribute?'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:2888:ininspect'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:2887:in collect'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:2887:ininspect'
from /opt/local/lib/ruby/1.8/irb.rb:310:in output_value'
from /opt/local/lib/ruby/1.8/irb.rb:159:ineval_input'
from /opt/local/lib/ruby/1.8/irb.rb:271:in signal_status'
from /opt/local/lib/ruby/1.8/irb.rb:155:ineval_input'
from /opt/local/lib/ruby/1.8/irb.rb:154:in eval_input'
from /opt/local/lib/ruby/1.8/irb.rb:71:instart'
from /opt/local/lib/ruby/1.8/irb.rb:70:in catch'
from /opt/local/lib/ruby/1.8/irb.rb:70:instart'
from /opt/local/bin/irb:13

This article should help you.
In Ruby, you can easily overwrite existing code from gems by simply redefining the method ("monkey patching")
This is the #initialize method you over wrote:
# active_record/base.rb
def initialize(attributes = nil)
#attributes = attributes_from_column_definition
#attributes_cache = {}
#new_record = true
#readonly = false
#destroyed = false
#marked_for_destruction = false
#previously_changed = {}
#changed_attributes = {}
ensure_proper_type
populate_with_current_scope_attributes
self.attributes = attributes unless attributes.nil?
result = yield self if block_given?
_run_initialize_callbacks
result
end

Related

NoMethodError undefined method `[]=' for nil:NilClass

I created multiple classes with one test method to test wither the ruby objects get serialized correctly.
The error returned:
undefined method `[]=' for nil:NilClass
from /Users/horse/workspace/queryapi/app/models/query_model.rb:193:in `serialize'
I run the below test_query method through the rails console by initializing QueryModelTester and then invoking test_query() method on that object.
My code:
class QueryModelTester
def test_query
must = Must.new
range_criteria = RangeCriteria.new
range_criteria.gte = 20140712
range_criteria.lte = 1405134711
range = RangeBuilder.new
range.search_field = "created_time"
range.range_criteria = range_criteria
must.range = range
bool = Bool.new
bool.must = must
main_query = bool.serialize
puts main_query
end
end
Here are the model classes the above class is testing:
class RangeCriteria
#query_hash = Hash.new
attr_accessor :gte, :lte
def serialize
if(#gte.present?)
#query_hash[:gte] = #gte
end
if(#lte.present?)
#query_hash[:lte] = #lte
end
if(#gte.present? || #lte.present?)
return #query_hash
end
end
end
class RangeBuilder
#query_hash = Hash.new
attr_accessor :search_field, :range_criteria
def serialize
if(#search_field.present?)
#query_hash[#search_field] = #range_criteria.serialize
return #query_hash[:range] = #query_hash
end
end
end
class Bool
#query_hash = {}
attr_accessor :must
def serialize
if( #must.present? )
#query_hash[:must] = #must.serialize
return #query_hash[:bool] = #query_hash
end
end
end
The problem is when you initialize your #query_hash. In all your classes they are initialized in wrong scope. To fix it, you should move #query_hash = Hash.new to initialize method, like:
class RangeCriteria
def initialize
#query_hash = Hash.new
end
# ...
end
class RangeBuilder
def initialize
#query_hash = Hash.new
end
# ...
end
class Bool
def initialize
#query_hash = Hash.new
end
# ...
end
Hope that helps.
Good luck!

Access varible in ruby after initialize

I am trying to access variable in ruby after initialize, but i didn't get that variable , anything wrong in that?
class Test
def initialize(params)
#has_test = params[:has_test]
#limit_test = params[:limit_test]
end
def self.method1(params)
Test.new(params)
#can i get that two instance variable
end
end
You should probably set up attribute accessors, then use them this way:
class Test
attr_accessor :has_test
attr_accessor :limit_test
def initialize(params)
#has_test = params[:has_test]
#limit_test = params[:limit_test]
end
def self.method1(params)
t = Test.new(params)
// can i get that two instance variable
// Yes:
// use t.has_test and t.limit_test
end
end
You are mixing an instance and a class method in your example.
If this is really what you want, then you have to define an accessor with attr_reader:
class Test
def initialize(params)
#has_test = params[:has_test]
#limit_test = params[:limit_test]
end
attr_reader :has_test
attr_reader :limit_test
def self.method1(params)
obj = Test.new(params)
p obj.has_test
p obj.limit_test
end
end
Test.method1(has_test: 1, limit_test: 3)
It the instance/class-method is a mistake, then this example may help you:
class Test
def initialize(params)
#has_test = params[:has_test]
#limit_test = params[:limit_test]
end
def method1()
p #has_test
p #limit_test
end
end
obj = Test.new(has_test: 1, limit_test: 3)
obj.method1
If you define also the accessors like in the first code, then you have again access from outside the class.
Just in case you don't want a reader, see also Access instance variable from outside the class

How can I work with this Module/Class setup?

I have the following module/class:
module Pigeons
class FedEx
attr_accessor :signature_name
def initialize(account)
self.account = account
end
def response(number)
body = "...some xml..."
return HTTParty.post('http://example.com', :body => body)
end
def track(number)
details = response(number)
self.signature_name = details[:delivery_signature_name]
end
end
end
What I'd like to be able to do is this:
#fedex ||= Pigeons::FedEx.new('123abc')
tracker = fedex.track('1234567890')
tracker.signature_name
Everything is working up until the tracker.signature_name part, which throws an undefined method 'signature_name' for nil:NilClass error.
The problem is in this line:
self.signature_name = details[:delivery_signature_name]
details[:delivery_signature_name] turns out to be nil, which is then assigned to self.signature_name and then becomes return value of track method. And here
tracker = fedex.track('1234567890')
tracker.signature_name
tracker will be nil and you try to call a method on it.
You probably meant to write this instead:
def track(number)
details = response(number)
self.signature_name = details[:delivery_signature_name]
self # <== here
end
You need two methods called signature_name= and response that do whatever they are supposed to do in your class.

Creating a class method with Ruby problems

Why does the following code result in the error 'undefined local variable or method `foo_client' for Foo::People:Class'
class Foo::People
class << self
def get_account_balance(account_num)
foo_client.request :get_account_balance, :body => {"AccountNum" => account_num}
end
end
def foo_client
##client ||= Savon::Client.new do|wsdl, http|
wsdl.document = PEOPLE_SERVICE_ENDPOINT[:uri] + "?WSDL"
wsdl.endpoint = PEOPLE_SERVICE_ENDPOINT[:uri]
end
end
end
def get_account_balance is inside the class << self block, so it's a class method. def foo_client is not, so it's an instance method. So you can't call foo_client from get_account_balance because you're not calling it on an instance of People.

Rails Active Record Instance Variables

My questions is in regards to this AR and its instance variable #saved
class PhoneNumber < ActiveRecord::Base
has_one :user
validates_presence_of :number
def self.create_phone_number( user, phone_hash )
#new_phone = PhoneNumber.new(phone_hash)
#user = user
PhoneNumber.transaction do
#user.phone_numbers << #new_phone
#new_phone.save!
#user.save!
end
#saved = true
return #new_phone
rescue ActiveRecord::RecordInvalid => invalid
#saved = false
return #new_phone
end
def saved?
#saved ||= false
end
end
It is my understanding that the instance variables will keep their values through the existence of the instance.
When using this AR in my controller, saved? always returns false..
#phone_number = PhoneNumber.create_phone_number(#active_user, params[:phone_number])
puts "add_phone_number"
if #phone_number.saved? => always false
What am I missing in regards to these instance variables? Thank you
you're using the instance variable #saved inside a class method, the #saved var then belongs to the class, not to its instances, so you cannot call it from an instance method like #saved?.
what you can do, is, at the top of the class add:
attr_accessor :saved
and inside the create_phone_number method, replace:
#saved = true
with:
#new_phone.saved = true
then it should work

Resources