Adding in class attribute with a Module


#1

Is it possible to add class attributes (cattr_accessor) using a module?
If so could you give an example?

Many thanks.


#2

Worked pretty much how I expected it to:

module TestModule
attr_accessor :attribute
end
=> nil

class TestClass
include TestModule
end
=> TestClass

tc = TestClass.new
=> #TestClass:0x2dc17c8

tc.attribute = “Hello, world”
=> “Hello, world”

puts tc.attribute
Hello, world
=> nil

Farrel


#3

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I think the OP wanted class level attribute accessor, not instance level
accessors. You showed how-to do instance level accessors:

zdennis@lima:~$ irb
irb(main):001:0> class A ; attr_accessor :foo ; end
=> nil
irb(main):002:0> a = A.new
=> #<A:0xb7cdc8a8>
irb(main):003:0> a.foo = 5
=> 5
irb(main):004:0> a.foo
=> 5

but using mixins:

irb(main):007:0> module M ; attr_accessor :foo ; end
=> nil
irb(main):008:0> class B ; include M; end
=> B
irb(main):009:0> b = B.new
=> #<B:0xb7cb20a4>
irb(main):010:0> b.foo = 5
=> 5
irb(main):011:0> b.foo
=> 5

I think OP wants the equivalent of:

irb(main):012:0> class C ; class << self ; attr_accessor :foo ; end ;
end
=> nil
irb(main):013:0> C.foo = 5
=> 5
irb(main):014:0> C.foo
=> 5

But with using mixins. The OP should just open up the instance of the
class and include the module there. For example:

irb(main):015:0> class D
irb(main):016:1> class << self
irb(main):017:2> include M
irb(main):018:2> end
irb(main):019:1> end
=> #Class:D
irb(main):020:0> D.foo = 99
=> 99
irb(main):021:0> D.foo
=> 99

Zach

Farrel L. wrote:

include TestModule
=> “Hello, world”

puts tc.attribute

Hello, world
=> nil

Farrel

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFEOkNJMyx0fW1d8G0RAvzeAKCCzOvJoBDK/zHyDeI9uPdBd3I4RgCfWsIU
l9QTe4RbggocfasjnJQ4tw8=
=Sv/o
-----END PGP SIGNATURE-----


#4

Hi –

On Mon, 10 Apr 2006, kris wrote:

Is it possible to add class attributes (cattr_accessor) using a module?
If so could you give an example?

There’s no cattr_accessor method in Ruby. If you’ve written one, or
are using one written by someone else, you’ll have to show us what it
does before we can tell you how to use it :slight_smile:

David


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” coming in PDF April 15, and in paper May 1!
http://www.manning.com/black


#5

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Robert K. wrote:

Right you are. thx Robert!

Zach
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFEOkojMyx0fW1d8G0RAtd/AJ4nGn/mvB2eI4E/2CUSnfmEnTaMzQCeOOCU
zLYzESEnYvgrLpDXIQiZOHA=
=JQcj
-----END PGP SIGNATURE-----


#6

2006/4/10, zdennis removed_email_address@domain.invalid:

irb(main):003:0> a.foo = 5
irb(main):009:0> b = B.new
irb(main):013:0> C.foo = 5
irb(main):019:1> end
=> #Class:D
irb(main):020:0> D.foo = 99
=> 99
irb(main):021:0> D.foo
=> 99

There’s an easier way:

class D
extend M
end

or

class D;end
D.extend M

There are other options (e.g. use #included) but it depends what the
OP really wants.

Kind regards

robert


#7

On 4/10/06, kris removed_email_address@domain.invalid wrote:

PS. I didnt write cattr_accessor. I’m using Rails but I dont think it is
opart of that?

cattr_accessor is a Railsism. It is not part of standard Ruby.

I’m undecided whether it should be or not, but it is potentially very
useful.

You will need to add an “included” hook. See “ri Module#included”.

-austin


#8

Thanks very much for all the examples. I think I need to clarify,
basically I have a base class called “System” from which all my models
decend. This class has a class attribute called user_id which is set to
the current_user every request by application.rb:

BASE MODEL CLASS
class System < ActiveRecord::Base
cattr_accessor :user_id
end

MODEL
class Documents < System

this model know the current user’s id

end

APPLICATION CONTROLLER
class ApplicationController < ActionController::Base
before_filter :set_user

set class attribute for all models

def set_user
if logged_in?
System.user_id = current_user.id
end
end
end

By using a class attribute instead of a instance attribute I can set the
current user id for all models at once.

This works but I want to use a module/mixin instead of inheritance.

Many thanks again.

PS. I didnt write cattr_accessor. I’m using Rails but I dont think it is
opart of that?

unknown wrote:

Hi –

On Mon, 10 Apr 2006, kris wrote:

Is it possible to add class attributes (cattr_accessor) using a module?
If so could you give an example?

There’s no cattr_accessor method in Ruby. If you’ve written one, or
are using one written by someone else, you’ll have to show us what it
does before we can tell you how to use it :slight_smile:

David


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” coming in PDF April 15, and in paper May 1!
http://www.manning.com/black


#9

Its very useful, the trouble is the models can’t see the session (for
good reasons) but they need information from the controller level, such
as current logged in user, and passing it every time you create a model
is a pain and can easily be forgottern. Using cattr_accessor you can set
and forget.

Is this maybe a question better asked on the Rails forum?

Austin Z. wrote:

On 4/10/06, kris removed_email_address@domain.invalid wrote:

PS. I didnt write cattr_accessor. I’m using Rails but I dont think it is
opart of that?

cattr_accessor is a Railsism. It is not part of standard Ruby.

I’m undecided whether it should be or not, but it is potentially very
useful.

You will need to add an “included” hook. See “ri Module#included”.

-austin


#10

removed_email_address@domain.invalid wrote:

cattr_accessor is a Railsism. It is not part of standard Ruby.

I’m undecided whether it should be or not, but it is potentially very
useful.

If it ever is, I think it needs a new name. It’s a wrapper for class
variables, but class variables, in my view, are not really suitable
for implementing “attributes”, because they are not uniquely
associated with one object.

But isn’t a class an instance of Class?

Foo = Class.new # instance object of class Class
f = Foo.new # instance object of class Foo

I don’t like the sprawl of the concept of
an “attribute” of a class-hierarchy-plus-instances-of-those-classes.

The ‘attribute’ concept is messy as it is, but this class use seems to
be a natural extension of the ‘methods that get/set an object variable
of the same name’ idea.

James B.

?Design depends largely on constraints.?
? Charles Eames


#11

Hi –

On Mon, 10 Apr 2006, Austin Z. wrote:

On 4/10/06, kris removed_email_address@domain.invalid wrote:

PS. I didnt write cattr_accessor. I’m using Rails but I dont think it is
opart of that?

cattr_accessor is a Railsism. It is not part of standard Ruby.

I’m undecided whether it should be or not, but it is potentially very useful.

If it ever is, I think it needs a new name. It’s a wrapper for class
variables, but class variables, in my view, are not really suitable
for implementing “attributes”, because they are not uniquely
associated with one object. I don’t like the sprawl of the concept of
an “attribute” of a class-hierarchy-plus-instances-of-those-classes.

David


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” coming in PDF April 15, and in paper May 1!
http://www.manning.com/black


#12

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Kris wrote:

Its very useful, the trouble is the models can’t see the session (for
good reasons) but they need information from the controller level, such
as current logged in user, and passing it every time you create a model
is a pain and can easily be forgottern. Using cattr_accessor you can set
and forget.

It is useful, the question is, is it useful for ruby to have this
functionality in the core language.

Is this maybe a question better asked on the Rails forum?

There is a rails-aspect and a ruby-aspect to what you brought up. For
the type of question you will probably get answers from
either list, although the one from the ruby list will be more
ruby-specific, whereas the answer from the rails list may be more
rails framework related.

Zach
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFEOoLrMyx0fW1d8G0RAqZMAJ9Z/21k9aEjoh8wS11UwA3gamHBxgCfQiSW
mKcZt5yT89hRW1xuIbV9jZU=
=iBTi
-----END PGP SIGNATURE-----


#13

If it ever is, I think it needs a new name. It’s a wrapper for class
variables, but class variables, in my view, are not really suitable
for implementing “attributes”…

I am using the as attributes, but a class variable would be better.
And if they where var’s you could add getter/setter methods to make them
look like attributes.

Inside a model:

self.created_by = System.current_user.id
self.save

It would be better if I could get rid of the System bit and just do:

self.created_by = current_user.id


#14

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

James B. wrote:

I don’t like the sprawl of the concept of
an “attribute” of a class-hierarchy-plus-instances-of-those-classes.

I think this is what you are referring to David, and I think it is
strange to:

zdennis@lima:~$ irb
irb(main):001:0> class A
irb(main):002:1> @@myvar = 5
irb(main):003:1> class << self ; @myvar = 10 ; end
irb(main):004:1> end
=> 10
irb(main):005:0> A.instance_variables
=> []
irb(main):006:0> A.class_variables
=> ["@@myvar"]
irb(main):007:0> a = class A ; class << self ; self ; end ; end
=> #Class:A
irb(main):008:0> a.instance_variables
=> ["@myvar"]
irb(main):009:0> a.instance_eval “@myvar
=> 10
irb(main):010:0> A.module_eval “@@myvar
=> 5
irb(main):011:0>

It seems like, @@myvar and @myvar should refer to the same reference
point. I would expect @@ to signify a class level attribute,
which is actually an instance attribute on the class itself. In my head
that makes sense.

The ‘attribute’ concept is messy as it is, but this class use seems to
be a natural extension of the ‘methods that get/set an object variable
of the same name’ idea.

+1

Zach
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFEOoW9Myx0fW1d8G0RAtr1AJ4hnjfSYe4cK1Ky42WAiE/xbEAlDQCffyq6
tsuod8moO45731DlZryH/SI=
=Wdyv
-----END PGP SIGNATURE-----


#15

Hi –

On Tue, 11 Apr 2006, James B. wrote:

But isn’t a class an instance of Class?

Of course, but class variables aren’t per-class, so using them to
implement “attributes” of a class object doesn’t make sense.

David


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” coming in PDF April 15, and in paper May 1!
http://www.manning.com/black


#16

“It is useful, the question is, is it useful for ruby to have this
functionality in the core language.”

I have only really used Ruby in the context of Rails so couldn’t really
answer that one, but with regards to Model-Controller-View, which is not
just a concept used by Rails it is very useful.

I can see class attributes/var’s being very useful in general though.


#17

Hi –

On Tue, 11 Apr 2006, zdennis wrote:

zdennis@lima:~$ irb
=> #Class:A
is actually an instance attribute on the class itself. In my head
I wouldn’t want to see any crossover between class variables and
between)?

  • From a usage perspective as the end-user of the langauge nothing changes:

irb(main):025:0> C.m = 5
=> 5
irb(main):026:0> C.m
=> 5
irb(main):027:0> D.m = 10
=> 10
irb(main):028:0> D.m
=> 10

Sure – it’s just two ways to implement the method. But I wouldn’t
call the second one an attribute, because:

class E < D
@@m = 12
end

so E (a different object from D) can directly, and without being
“impolite” (i.e., no instance_eval, etc.), manipulate the same
variable as the one storing the value in D.m. And instances of D also
have direct, non-invasive access to that same @@m.

It definitely seems that if the two are to stay separate by
implementation and conceptualization that it would nice to have
those class accessor methods, which don’t invade the class’s
civilian state. I use that as a shortcut to writing my own
accessors…
class << self ; attr_* :foo ; end

Saves me typing in light of a class get/set shortcut existing…

I would actually expect something called cattr_* to work like that,
rather than the way the Rails one works. Whether or not it’s
necessary is another question :slight_smile: But as a shortcut-shortcut, it
could make sense.

David


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” coming in PDF April 15, and in paper May 1!
http://www.manning.com/black


#18

Hi –

On Tue, 11 Apr 2006, zdennis wrote:

James B. wrote:

Actually I wrote this bit :slight_smile:

irb(main):004:1> end
=> 10
irb(main):010:0> A.module_eval “@@myvar
=> 5
irb(main):011:0>

It seems like, @@myvar and @myvar should refer to the same reference
point. I would expect @@ to signify a class level attribute, which
is actually an instance attribute on the class itself. In my head
that makes sense.

I disagree. If @@myvar is just the instance variable @myvar of some
class object, then it would presumably have exactly the same scope as
that instance variable – in which case, there’s no reason for it to
exist. If it’s visible to other objects (i.e., when ‘self’ is
something other than the class object), then it isn’t the same as an
instance variable anyway.

I wouldn’t want to see any crossover between class variables and
instance variables. A class object’s instance variables are strictly
the business of the class in its “civilian” capacity as a regular
object. Class variables, on the other hand, are a special case.
The two things are really not related conceptually at all.

David


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” coming in PDF April 15, and in paper May 1!
http://www.manning.com/black


#19

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

removed_email_address@domain.invalid wrote:

I don’t like the sprawl of the concept of
irb(main):004:1> end
=> 10
I disagree. If @@myvar is just the instance variable @myvar of some
The two things are really not related conceptually at all.

I see what you are saying, if there was crossover, then anything dealing
with the class as an object, in it’s “civilian” state as
you put it would essentially become a class variable which it is not.

On a implementation note, we achieve the same end result don’t we (focus
on the end part of that statement, and nothing in
between)?

class C
class << self ; attr_accessor :m ; end
end

class D
def self.m ; @@m ; end
def self.m=arg ; @@m = arg ; end
end

  • From a usage perspective as the end-user of the langauge nothing
    changes:

    irb(main):025:0> C.m = 5
    => 5
    irb(main):026:0> C.m
    => 5
    irb(main):027:0> D.m = 10
    => 10
    irb(main):028:0> D.m
    => 10

It definitely seems that if the two are to stay separate by
implementation and conceptualization that it would nice to have those
class accessor methods, which don’t invade the class’s civilian state. I
use that as a shortcut to writing my own accessors…
class << self ; attr_* :foo ; end

Saves me typing in light of a class get/set shortcut existing…

Zach

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFEOo6CMyx0fW1d8G0RArdFAJ474mMynkv3EZSr0NHPOs7o4BHVLACeK+QZ
6UMsY80gJKd/fK+zBB/yzH0=
=d/7i
-----END PGP SIGNATURE-----


#20

On Mon, Apr 10, 2006 at 08:57:04PM +0900, Robert K. wrote:

There’s an easier way:

class D
extend M
end

or

class D;end
D.extend M

Is there an easy way to extend classes with both class and object
methods at the same time?

module M
  def self.create
    # would do something special here
    new
  end
  def objmethod
  end
end

class A
  extend M
end

a.create   # <-- nope, doesn't work

I sometimes have a number of classes that I want to share
implementation, but that don’t have an “isa” relationship. Modules are
great for this, but when that implementation includes both object and
class methods, I’m not sure what to do.

Sam