3

Is there a better way to get the public "properties" of a Ruby object?

def props
  self.public_methods.grep(/.=$/) - ["==","==="]
end
Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
BuddyJoe
  • 69,735
  • 114
  • 291
  • 466

3 Answers3

3

Your regular expression is incomplete: it matches methods that start in any character, rather than just word characters. The best way to get all the "writers" would be

methods.grep /^\w+=$/

And the regular expression can be shortened to

methods.grep /\w=$/

but is less clear.

Aaa
  • 1,854
  • 12
  • 18
  • The regular expression doesn't have a `^` at the start, so it matches method names of any length. – Andrew Grimm Mar 15 '11 at 22:14
  • The `^` in regular expressions denote the beginning of the string or a line, which is completely irrelevant to the length of the string and especially unimportant in method names, which have only one line. – Aaa Mar 15 '11 at 22:40
  • @Refactor: I meant to refer to tyndall's regular expression, not your regular expression. I was meaning to say that it already matches all the "writers". – Andrew Grimm Mar 15 '11 at 22:47
  • @Andrew Grimm: If you are referring to Tyndall's regular expression already matching all "writers", then you may have forgotten that the real "writers" actually need to start with word characters and not anything (`.`). – Aaa Mar 15 '11 at 22:52
  • @Refactor: Which'd mean that `["[]=", ">=", "<=", "!="]` would be wrongly included, true enough. But Tyndall's regular expression doesn't only match methods that only consist of a single character and then an equal sign. – Andrew Grimm Mar 16 '11 at 03:09
  • @Andrew Grimm: True, but if it was you that voted me down, then why? – Aaa Mar 16 '11 at 23:21
  • I found "it only matches public methods with one character before "="" misleading IMO. Solving a specific problem but giving misleading information is like giving someone a good fish but bad advice on how to fish. – Andrew Grimm Mar 16 '11 at 23:30
  • @Andrew Grimm: Oh. Then I'll fix that...it's good to know that by comment rather than down-vote. – Aaa Mar 16 '11 at 23:34
  • @Refactor: I was trying to say it from the very first comment. Sorry that it was so confusing. – Andrew Grimm Mar 17 '11 at 00:59
  • @Refactor: Your explanation is still wrong. `/.=$/` does not match methods that _start_ with any character, it matches methods that _end_ with any character followed by a `=`. Likewise, your suggestion `/\w=$/` matches methods that _end_ in a word character followed by a `=` (but I think it still works, because the element set and operator methods never have a word character before the `=`). – wyattisimo Jan 11 '13 at 19:56
2

In ruby, unless you do metaprogramming to break encapsulation, the only way to change an instance variable of another object is to call a method that happens to do so. And without using metaprogramming there's no way to tell what instance variable is being changed by a method.

For example, if I had a person, and that class had methods height_feet= and height_meters= in it, I wouldn't be able to tell if the implementation of that the person's height was based on @height_feet or @height_meters or even @height_cubits.

This is a Good Thing, as it means you program purely to the interface, not the implementation.

Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
1

Well, there is no such thing as a "property" in Ruby. And basically, since you made the word up (or more precisely: you made up its definition as it applies to Ruby), you get to define what it means, but on the flipside it also means you have to implement its semantics yourself.

So, if you define "property" to mean "method which ends with an equals sign but does not exclusively consist of equals signs", then, yes, your definition is the best possible way. (BTW: your definition of "property" includes methods such as <=, >= and !=, which may or may not be what you want.)

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • I guess I mean attributes. Variables internal to the class that have been exposed (public). Was looking at the YAML stdlib code and can't find where it loops over these. I'm sure it is there, but I can't find it. – BuddyJoe Dec 17 '10 at 00:28
  • 1
    @tyndall: Potayto, Potahto. It's the same thing. An "attribute" is simply a *social* construct. A method is an attribute because you decided to call in an attribute. There is no algorithm, program, method, procedure, function that can determine whether any particular method is an attribute or not, because the only thing that determines whether or not it *is* an attribute is not some technical trait of the method itself, it's simply whether or not *you* want to call it an attribute. Is `Array#length` an attribute? How about `String#length`, which actually has to walk along the entire string? – Jörg W Mittag Dec 17 '10 at 02:00