Skip to content

Instantly share code, notes, and snippets.

@tooky
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tooky/5673afd4599b02aef0eb to your computer and use it in GitHub Desktop.
Save tooky/5673afd4599b02aef0eb to your computer and use it in GitHub Desktop.
require 'minitest/autorun'
class Foo
attr_accessor :a
def initialize
@a = :unchanged
end
# call 'a' with explicit 'self' as receiver
def b; self.a; end
def b=(v); self.a = v; end
# call 'a' with implicit 'self' as receiver
def c; a; end
def c=(v); a = v; end
def value
@a
end
end
class ProtectedFoo < Foo
protected :a, :a=
end
class PrivateFoo < Foo
private :a, :a=
end
class PublicVisibilityTest < Minitest::Test
def setup
@foo = Foo.new
end
def test_reader_explicit_receiver_succeeds
assert_equal :unchanged, @foo.a
end
def test_writer_explicit_receiver_succeeds
@foo.a = 4
assert_equal 4, @foo.value
end
def test_reader_explicit_self_receiver_succeeds
assert_equal :unchanged, @foo.b
end
def test_writer_explicit_self_receiver_succeeds
@foo.b = 4
assert_equal 4, @foo.value
end
def test_reader_implicit_self_receiver_succeeds
assert_equal :unchanged, @foo.c
end
def test_writer_implicit_self_receiver_succeeds_but_does_nothing
@foo.c = 4
assert_equal :unchanged, @foo.value
end
end
class ProtectedVisibilityTest < Minitest::Test
def setup
@foo = ProtectedFoo.new
end
def test_reader_explicit_receiver_fails
assert_raises(NoMethodError) do
@foo.a
end
end
def test_writer_explicit_receiver_fails
assert_raises(NoMethodError) do
@foo.a = 4
end
assert_equal :unchanged, @foo.value
end
def test_reader_explicit_self_receiver_succeeds
assert_equal :unchanged, @foo.b
end
def test_writer_explicit_self_receiver_succeeds
@foo.b = 4
assert_equal 4, @foo.value
end
def test_reader_implicit_self_receiver_succeeds
assert_equal :unchanged, @foo.c
end
def test_writer_implicit_self_receiver_succeeds_but_does_nothing
@foo.c = 4
assert_equal :unchanged, @foo.value
end
end
class PrivateVisibilityTest < Minitest::Test
def setup
@foo = PrivateFoo.new
end
def test_reader_explicit_receiver_fails
assert_raises(NoMethodError) do
@foo.a
end
end
def test_writer_explicit_receiver_fails
assert_raises(NoMethodError) do
@foo.a = 4
end
assert_equal :unchanged, @foo.value
end
def test_reader_explicit_self_receiver_fails
assert_raises(NoMethodError) do
@foo.b
end
end
def test_writer_explicit_self_receiver_fails
assert_raises(NoMethodError) do
@foo.b = 4
end
assert_equal :unchanged, @foo.value
end
def test_reader_implicit_self_receiver_succeeds
assert_equal :unchanged, @foo.c
end
def test_writer_implicit_self_receiver_succeeds_but_does_nothing
@foo.c = 4
assert_equal :unchanged, @foo.value
end
end
# Run options: --seed 18945
#
# Running:
#
# ................F.
#
# Finished in 0.002823s, 6376.1955 runs/s, 7084.6617 assertions/s.
#
# 1) Failure:
# PrivateVisibilityTest#test_writer_explicit_self_receiver_fails [visibility_test.rb:126]:
# NoMethodError expected but nothing was raised.
#
# 18 runs, 20 assertions, 1 failures, 0 errors, 0 skips
@JEG2
Copy link

JEG2 commented Jun 26, 2014

self, and only self, is allowed on private writer methods. This is a needed special exception to the rules because just a = 42 is a local variable assignment, not a method call. Line 16 of your example does not call a=().

@tooky
Copy link
Author

tooky commented Jun 26, 2014

@JEG2 thanks.

It started as a discussion about why ruby issues warnings for private attr_*.

We'd assumed that the only way to send a private writer message would be using #send.

Of course it makes sense to make an exception for the = operator – which then leaves us back with the question about the warnings!

@JEG2
Copy link

JEG2 commented Jun 26, 2014

I'm not a fan of that warning. I avoid it by doing what you showed in the thread and specifically naming what I want to be private. I'm not sure why the warning exists, sorry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment