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: http://blog.hasmanythrough.com/2007/1/22/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