Rubies of private and public accessories

When defining accessories in Ruby, there can be tension between the multiplicity (which we all love) and best practice.

For example, if I want to set a value in an instance, but prevent any external objects from updating it, I could do the following:

class Pancake
  attr_reader :has_sauce

  def initialize(toppings)
    sauces = [:maple, :butterscotch]
    @has_sauce = toppings.size != (toppings - sauces).size
...

But all of a sudden, I use a raw instance variable that makes me twitch. I mean, if I needed to process has_sauce before setting it for a future date, I would need to do a lot more refactoring than just redefining the accessory. And come on, raw instance variables? Blech.

I could just ignore the problem and use attr_accessor. I mean, anyone can set an attribute if they really want to; it is, after all, ruby. But then I lose the idea of ​​encapsulating data, the interface of the object is less defined, and the system is potentially much more chaotic.

Another solution would be to define a pair of accessories under different access modifiers:

class Pancake
  attr_reader :has_sauce
  private
    attr_writer :has_sauce
  public

  def initialize(toppings)
    sauces = [:maple, :butterscotch]
    self.has_sauce = toppings.size != (toppings - sauces).size
  end
end

Which does its job, but it's a piece of the template for easy access and frankly: ew.

So, is there a better Ruby way?

+4
source share
3 answers

attr_readeretc. - these are just methods - there is no reason why you can determine options for your own use (and I share your feelings) For example:

class << Object
  def private_accessor(*names)
    names.each do |name|
      attr_accessor name
      private "#{name}="
    end
  end
end

private_accessor, attr_accessor ( , , private_accessor)

+3

private arg, ...

class Pancake
  attr_accessor :has_sauce
  private :has_sauce=
end

class Pancake
  attr_reader :has_sauce
  attr_writer :has_sauce; private :has_sauce=
end

....

"" ? ; , , pancake.rb, . , @, , , "blech", . @ private, .

, , : , , , .

+2

. attr_accessor , , .

, toppings , , has_sauce " ", , toppings.

- :

class Pancake
  def initialize(toppings)
    @toppings = toppings
  end

  def has_sauce?
    sauces = [:maple, :butterscotch]
    (@toppings & sauces).any?
  end
end

attr_accessor :toppings. , Pancake PancakeToppingDetector;)

0

All Articles