self. vs. @

I'm working on an application that creates a confirmation e.mail whenever you create and account or change an e.mail address. I thought I'd just use the same key generation code used for the password hash login example from the Agile Rails book.

The function to create a salt value keeps failing complaining I have a nil object where I don't expect it.

The code where it breaks is:

def create_new_salt     self.salt = @user_id.to_s + rand.to_s end

I've also put a constant string assigned to self.salt, but the error still occurs, as if self.salt points to a nil object, but I don't see how that can happen. I also don't understand any reason for this function to call self.salt, instead of @salt. Any clues would be much appreciated.

Thanks, j

PS here is the table definition for this model.

:created_at, :timestamp :email, :string :type, :string #which of several e.mail columns in 'user' does this change apply to :user_id, integer :key, :string #randomly generated key :salt, :string

That code seems to be fine. Look at where create_new_salt is being called, it's probably being called on a nil Object instead of an AR model, possible a find condition returning nil instead of the model(s).

Vish

Thanks for your help. create_new_salt is only ever called from within the the model object. Here is the only function that calls it:

def initialize(id, address, type) @email = address @type = type @user_id = id create_new_salt self.key = self.encrypt_key(self.email, self.salt) end

Perhaps I can't call it until after initialize has run? Also I still don't understand why I should call self.salt in some of these cases and not @salt.

Thanks, j

Joshua Kolden wrote: > how that can happen. I also don't understand any reason for this > function to call self.salt, instead of @salt. Any clues would be much > appreciated.

I don't know much about the book example you refer to but you seem to have some confusion between "self.salt = foo" and "@salt = foo"

When you do "@salt = foo" it is simply making the instance variable "salt" point to whatever "foo" is pointing at. If you do "self.salt = foo" then you are calling the method "salt=" with the argument "foo". The method "salt=" could do anything. One might think it is typically defined as:

def salt=(val)    @salt = val end

but it could be defined as

def salt=(val)    @salt = rand end

Sounds like you need to see how "salt=" is defined. Until then you won't know why it is not working.

Eric

Thanks for the info. I do realize that one is a function and the other is the member.

What I'm still unclear on is why in an ActiveRecord derived object one would choose to use one over the other. If there is logic happening with the self.name assignment, then why would we not always call self.name in ActiveRecord objects as a rule, however that doesn't seem to be the case. In the book examples several members were assigned as @some_data = something, while this salt value was set with self.salt.

Thanks, j

Well, there you have it, you can't easily override initialize for AR objects. It shouldn't work alright with create_new_salt being removed from there too.

See this: has_many :through - Using faux accessors to initialize values

What you're trying to do can possibly be done like this:

Model.new(:email => address, :type => type, :user = user) and an after_initialize callback.

Also, usually, @salt = and self.salt = are the same thing inside a model. salt= is a function equivalent to this:

def salt=(var)   @salt = var end

(it's part of an attr_accessor definition.) If you didn't have the accessor tho, you wouldn't be able to call it from outside the model since instance variables are private.

Vish

Great thanks, that's my issue. I'm still not clear on why various examples (including the book) switch between @member, and self.member, but just changing this to a different function then initialize has gotten me past the nil error.

Thanks! j

Joshua Kolden wrote:

What I'm still unclear on is why in an ActiveRecord derived object one would choose to use one over the other. If there is logic happening with the self.name assignment, then why would we not always call self.name in ActiveRecord objects as a rule, however that doesn't seem to be the case. In the book examples several members were assigned as @some_data = something, while this salt value was set with self.salt.

I in general always use the function version. That way if there is custom logic it will run. If there is not then it will work just like assigning a instance variable. I guess to me the function encapsulates better.

Eric