Passing in a hash to a class without using an initialization method
I was under the, apparently incorrect, impression that when I pass a hash into a class the class requires an initialization method like this:
class Dog
attr_reader :sound
def initialize(params = {})
@sound = params[:sound]
end
end
dog = Dog.new({sound:"woof"})
puts dog.sound
But I've run into a bit of code (for creating a password digest) that works within a rails application that doesn't use an initialization method and seems to work just fine and it's kind of confuses me because when I try this anywhere else it doesn't seem to work. Here is the sample code that works (allows me to pass in a hash and initializes without an initialization method):
class User < ActiveRecord::Base
attr_reader :password
validates :email, :password_digest, presence: true
validates :password, length: { minimum: 6, allow_nil: true }
def password=(pwd)
@password = pwd
self.password_digest = BCrypt::Password.create(pwd)
end
end
NOTE: In the create action I pass in a hash via strong params from a form that, at the end of the day, looks something like this {"email"=>"joeblow@gmail.com", "password"=>"holymolycanoli”}
In this bit of code there is no initialization method. When I try something like this (passing in a hash without an initialization method) in pry or in a repl it doesn't seem to work (for instance the following code does not work):
class Dog
attr_reader :sound
def sound=(pwd)
@sound = pwd
end
end
dog = Dog.new({sound:"woof"})
puts dog.sound
The error I get is:
wrong number of arguments (1 for 0)
Is it rails that allows me to pass in hashes like this or ActiveRecord? I'm confused as to why it works within rails within this context but generates an error outside of rails. Why does this work in rails?
If you look at the top you have this:
class Dog < ActiveRecord::Base
This causes your class Dog
to inherit from ActiveRecord::Base
when it does so it gains a bunch of methods that allows you to set things up.
Now when you call for example:
Dog.create(password: 'some_password', username: 'some_username')
Your calling a method on the class object that then returns an instance of the class.
so taking your example
class Dog
attr_reader :sound
def sound=(pwd)
@sound = pwd
end
def self.create data_hash
new_dog = self.new #create new instance of dog class
new_dog.sound = data_hash[:sound] #set instance of dog classes sound
new_dog # return instance of dog class
end
end
It's essentially what we would term a factory method, a method that takes in data and returns an object based on that data.
Now I have no doubt that ActiveRecord::Base
is doing something more complicated than that but that is essentially what it's doing at the most basic of levels.
I'd also like to point out that when inheriting from ActiveRecord::Base
your also inheriting its 'initialize' method so you don't have to set one yourself. The class knows what attribute methods to create based on the schema you set when you did the DB migrations for a table that matches (through rail's conventions) the class.
A lot of things happen when you subclass ActiveRecord::Base. Before looking at other issues I'm guessing that Dog is a rails ActiveRecord model and you just forgot to add
class Dog < ActiveRecord::Base
链接地址: http://www.djcxy.com/p/60960.html
上一篇: 强制第一个散列和数组元素位于rubocop中的同一行上
下一篇: 在不使用初始化方法的情况下将哈希传递给类