Misunderstanding of instance variables

M

Matthew D Moss

I'm learning Rails, and trying to setup image upload in a form. As part
of that, my image model looks something like this:

class Image < ActiveRecord::Base
validates_presence_of :content_type
validates_format_of :content_type, :with => /^image/, :message =>
"must be an image"

def image_file=(arg)
self.content_type = arg.content_type.chomp
end
end


Okay, so the above basically works. But I wondered why the author I
borrowed this from used "self." instead of @ -- I thought both would
essentially reference an instance variable.

So I replaced the one line to look like this:

@content_type = arg.content_type.chomp

and it fails, triggering my validation checks.

What gives?
 
M

Matthew D Moss

I think I understand... self.content_type is an accessor, I'm
guessing, defined by ActiveRecord based on my table. So
self.content_type is a method, and @content_type is invalid. (Or at
least doesn't do what I expect.)

Does that seem right? Or am I missing something else?
Thanks...
 
D

Devin Mullins

Matthew said:
Okay, so the above basically works. But I wondered why the author I
borrowed this from used "self." instead of @ -- I thought both would
essentially reference an instance variable.

So I replaced the one line to look like this:
@content_type = arg.content_type.chomp
and it fails, triggering my validation checks.
self.content_type = blahblahblah is an invocation of an instance method
named "content_type=". In typical implementations of this method*,
invocation causes an instance variable @content_type to be set. In the
case of ActiveRecord, I guess that's not the case.

Devin
*see attr_writer
 
H

Hal Fulton

Devin said:
self.content_type = blahblahblah is an invocation of an instance method
named "content_type=". In typical implementations of this method*,
invocation causes an instance variable @content_type to be set. In the
case of ActiveRecord, I guess that's not the case.

Chances are, it does some extra housekeeping in addition to merely
setting the instance variable.

Bear in mind that "x.foo=" is doing a method call. If you defined that
method using attr_writer (or attr_accessor), then it will simply set
the @foo instance variable.

But if you define it manually, it may do anything and everything before
(or after) setting the variable. Or, if you wished to mislead people
or work according to some other model, foo= need not correspond to @foo
at all:

def foo=(value)
# Evil and nonsensical
# Ignore the value
puts "Haha! Fooled you!"
end


But in this real-life case, Rails has to do a lot of "bookkeeping" and
I'll bet that's what this is about.


Hal
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,781
Messages
2,569,615
Members
45,301
Latest member
BuyPureganics

Latest Threads

Top