Regarding attr_accessor and def initialize - ruby-on-rails

I want to add school names to array using attr_accessor.
My question is what 'def initialize()' is doing in this case
so that I can store data by using
v1.school_name[0] = "myschoolname"
If I omit the initialize() function I get the error
class StoreData
attr_accessor :school_name
def initialize
#school_name = []
end
end
v1 = Store_data.new
v1.school_name[0] = "myschoolname"
print v1.school_name[0]
v1.school_name[1] = "myschoolnamehighschool"
print v1.school_name

In this case you're initializing the #school_name with an empty array. If you don't do that it doesn't automatically create it, but it could. That pattern's called lazy initialization:
class StoreData
def school_name
#school_name ||= [ ]
end
end
s = StoreData.new
s.school_name << "Name 1"
s.school_name << "Name 2"
s.school_name
#=> [ "Name 1", "Name 2" ]
You can't assign something to a nil value which is what instance variables are by default.
This one creates an array if necessary using the ||= operator.

attr_accessor is just an attribute and by default it is nil. You cannot assign any value to it. If you need it to an array then initialize it as an array before using it.

Related

How to convert string to existing attribute in model when creation

I got a array of strings, I want to retrieve for each the attribute during the creation of the post.
My array = ["_646_maturity", "_660_maturity", "_651_maturity", "_652_maturity", "_641_maturity"]
class Audit < ApplicationRecord
belongs_to :user
before_save :calculate_scoring
def calculate_scoring
scoring = []
models = ActiveRecord::Base.connection.tables.collect{|t| t.underscore.singularize.camelize.constantize rescue nil}
columns = models.collect{|m| m.column_names rescue nil}
columns[2].each do |c|
if c.include? "maturity"
Rails.logger.debug 'COLUMN : '+c.inspect
scoring.push(c)
end
end
getMaturity = ""
scoring.each do |e|
getMaturity = e.to_sym.inspect
Rails.logger.debug 'MATURITY : '+getMaturity
end
end
end
The log print > 'MATURITY : :_651_maturity'
I'm looking to the value of :_651_maturity who is a attribute of my post.
I tried .to_sym but it's not working..
Thanks for the help!
Inside calculate_scoring you can use self to point to the record you are saving. So self._651_maturity = <some_value>, self[:_651_maturity] = <some_value> and self['_651_maturity'] are all valid methods to set _651_maturity.
Also, you can do something like:
my_attrib = '_651_maturity'
self[my_attrib] = 'foo'

Return members of a hashmap through a class get method

The following returns the default "client?":
class ClientMap
def initialize
##clients = {"DP000459": "BP"}
##clients.default = "client?"
end
def get(id)
return ##clients[:id]
end
end
clientMap = ClientMap.new
cKey = "DP000459"
puts clientMap.get(cKey)
Could anybody explain why I cannot retrieve anything but the 'default'?
You've got two problems. First, you are using the symbol syntax in your hash, which works only if your keys are symbols. If you want keys to be strings, you need to use hash-rocket syntax: ##clients = {'DP000459' => 'BP'}.
Second, your method returns clients[:id] regardless of what parameter is provided. The key is the symbol :id rather than the local variable id. You need to change this to ##clients[id].
Here's a cleaned-up version of what you want:
class ClientMap
def initialize
##clients = {'DP000459' => 'BP'}
##clients.default = 'client?'
end
def get(id)
##clients[id]
end
end
I've also taken the liberty of making the spacing more Ruby-idiomatic.
Finally, for variable names in Ruby, use snake_case:
>> client_map = ClientMap.new
>> c_key = 'DP000459'
>> client_map.get(c_key)
#> "BP"
Look at these code:
h = { foo: 'bar' } # => {:foo=>"bar"}
h.default = 'some default value' # => "some default value"
h[:foo] # => "bar"
h[:non_existing_key] # => "some default value"
You can read here about Hash#default method
Returns the default value, the value that would be returned by hsh if
key did not exist in hsh

Looping through object and blanking out fields

I have this constant to hold all dates fields:
DATE_FIELDS = [:a_effective_on, :a_expire_on,
:field_effective_on, :field_expire_on,
:line_manager_effective_on, :line_manager_expire_on,
:officer_effective_on, :officer_expire_on,
:regional_effective_on, :regional_expire_on]
I want to loop over an object and remove a date if it has a value.
Is this valid?:
#copy_to.DATE_FIELDS.each do |_date|
# remove dates here
end
I am getting a nil class for id error.
DATE_FIELDS.each do |field|
#copy_to.send("#{field}=".to_sym, nil) if #copy_to.send(field)
end
When you put a constant in your class like this, it exists at the class level. Access it with YourClassName::DATE_FIELDS if you're outside the class, or just DATE_FIELDS if you're inside the class.
This is how i would do it:
#instance method in your class
def clear_all_date_fields
atts = {}
DATE_FIELDS.each{|f| atts[f] = nil}
self.attributes = atts
end
Now you can do
#copy_to.clear_all_date_fields
note that this doesn't save #copy_to. You can save it afterwards, or put the save into the method (though i think it's better to have it not saving automatically).

ruby on rails accessing custom class attributes from its object

I have a custom class in my application controller. Like below:
class Defaults
def initialize
#value_1 = "1234"
#value_2 = nil
#data = Data.new
end
end
class Data
def initialize
#data_1 = nil
end
end
Now in my controller method i have created an object of type Defaults
def updateDefaultValues
defaults = Defaults.new
# i am unable to update the value, it says undefined method
defaults.value_2 = Table.maximum("price")
defaults.data.data_1 = defaults.value_2 * 0.3
end
How to access value_2 from defaults object?
defaults.value_2
Also, how to access data_1 attribute from data object within defaults object?
defaults.data.data_1
You should use attr_accessor:
class Defaults
attr_accessor :value_1, :value_2, :data
# ...
end
defaults = Defaults.new
defaults.value_1 = 1
# => 1
defaults.value_1
# => 1
As you are using def as a keyword to define the method, that means def is a reserved keyword. You can't use reserved keywords as a variable.
You just need to rename your variable name from def to something_else and it should work! Your code will look like this:
def updateDefaultValues
obj = Defaults.new
obj.value_2 = Table.maximum("price")
obj.data.data_1
end
EDIT:
As per OP's comment & updated question, he had used def just as an example, here is the updated answer:
You may need attr_accessor to make attrs accessible:
class Defaults
attr_accessor :value_1, :value_2, :data
...
...
end
class Data
attr_accessor :data_1
...
...
end
Add value_2 method in Defaults class
class Defaults
def initialize
#value_1 = "1234"
#value_2 = nil
#data = Data.new
end
def value_2
#value_2
end
end
class Data
def initialize
#data_1 = nil
end
end

ActiveRecord: How to set the "changed" property of an model?

For every model in ActiveRecord, there seems to be a private property called "changed", which is an array listing all the fields that have changed since you retrieved the record from the database.
Example:
a = Article.find(1)
a.shares = 10
a.url = "TEST"
a.changed ["shares", "url"]
Is there anyway to set this "changed" property yourself? I know it sounds hacky/klunky, but I am doing something rather unordinary, which is using Redis to cache/retrieve objects.
ActiveModel::Dirty#changed returns keys of the #changed_attributes hash, which itself returns attribute names and their original values:
a = Article.find(1)
a.shares = 10
a.url = "TEST"
a.changed #=> ["shares", "url"]
a.changed_attributes #=> {"shares" => 9, "url" => "BEFORE_TEST"}
Since there is no setter method changed_attributes=, you can set the instance variable by force:
a.instance_variable_set(:#changed_attributes, {"foo" => "bar"})
a.changed #=> ["foo"]
See this example from: Dirty Attributes
class Person
include ActiveModel::Dirty
define_attribute_methods :name
def name
#name
end
def name=(val)
name_will_change! unless val == #name
#name = val
end
def save
#previously_changed = changes
#changed_attributes.clear
end
end
So, if you have a attribute foo and want to "change" that just call foo_will_change!.

Resources