Where to place private methods in Ruby?
The best practice in my point of view is to go sequentially and declare your methods without keeping private in point of view.
At the end, you can make make any method private by just adding: private :xmethod
Example:
class Example
def xmethod
end
def ymethod
end
def zmethod
end
private :xmethod, :zmethod
end
Does this justify your question?
How to define a private method in Ruby?
It's fairly standard to put private/protected methods at the bottom of the file. Everything after private
will become a private method.
class MyClass
def a_public_method
end
private
def a_private_method
end
def another_private_method
end
protected
def a_protected_method
end
public
def another_public_method
end
end
As you can see in this example, if you really need to you can go back to declaring public methods by using the public
keyword.
It can also be easier to see where the scope changes by indenting your private/public methods another level, to see visually that they are grouped under the private
section etc.
You also have the option to only declare one-off private methods like this:
class MyClass
def a_public_method
end
def a_private_method
end
def another_private_method
end
private :a_private_method, :another_private_method
end
Using the private
module method to declare only single methods as private, but frankly unless you're always doing it right after each method declaration it can be a bit confusing that way to find the private methods. I just prefer to stick them at the bottom :)
Private methods in Ruby
Private methods cannot be called with an explicit receiver. But they can be called by any subclasses and instances of the class.
Here's a nice explanation of public
, protected
and private
methods in Ruby.
Understanding private methods in Ruby
Here's the short and the long of it. What private means in Ruby is a method cannot be called with an explicit receivers, e.g. some_instance.private_method(value). So even though the implicit receiver is self, in your example you explicitly use self so the private methods are not accessible.
Think of it this way, would you expect to be able to call a private method using a variable that you have assigned to an instance of a class? No. Self is a variable so it has to follow the same rules. However when you just call the method inside the instance then it works as expected because you aren't explicitly declaring the receiver.
Ruby being what it is you actually can call private methods using instance_eval:
class Foo
private
def bar(value)
puts "value = #{value}"
end
end
f = Foo.new
begin
f.bar("This won't work")
rescue Exception=>e
puts "That didn't work: #{e}"
end
f.instance_eval{ bar("But this does") }
Hope that's a little more clear.
-- edit --
I'm assuming you knew this will work:
class Foo
def public_m
private_m # Removed self.
end
private
def private_m
puts 'Hello'
end
end
Foo.new.public_m
Calling a private instance method from a class method in Ruby
Using private or protected really don't do that much in Ruby. You can call send on any object and use any method it has.
class Foo
def Foo.bar(my_instance, n)
my_instance.send(:plus, n)
end
end
How to access private methods
Yes, this is possible with Kernel#send
:
receiver.send :method_name, parameters
Though there are workarounds like BasicObject#instance_eval
, or Kernel#binding
manipulations, the common way to call private method is to call send
on the receiver.
Working with private methods in ruby on rails
You can make them class methods to call them in your controllers.
private
def self.create_notification_on_accept(event)
# I don't know where are you getting participant id, so pass it if you need
# additionally, if they are available on event object then you could do
# event.participant.id, event.user_id since the background of the code is not given
# hence I'm making some assumptions
event.notifications.create(action_type: "Accept", actor_id: participant.id,
user_id: user_id)
end
def self.create_notification_on_reject(event)
event.notifications.create(action_type: "Reject", actor_id: participant.id,
user_id: user_id)
end
And in your controller you can do this
def accept_invitation
#find event so you can pass it as a param
Event.create_notification_on_accept(event)
@participants.where(user_id: current_user.id).update_all(is_attending: true)
render "update"
end
However, a better thing to do this would be to have callbacks instead of class methods. That way you can reduce the overhead of calling the method everywhere, instead you can leave it onto the model to know when to call.
Is Ruby private method accessible in sub class?
Here's a brief explanation from this source:
- Public methods can be called by anyone---there is no access control. Methods are public by default (except for initialize, which is always private).
- Protected methods can be invoked only by objects of the defining class and its subclasses. Access is kept within the family.
- Private methods cannot be called with an explicit receiver. Because you cannot specify an object when using them, private methods can be called only in the defining class and by direct descendants within that same object.
This answer from a similar question expands on the topic in more detail: https://stackoverflow.com/a/1565640/814591
How to create a private class method?
private
doesn't seem to work if you are defining a method on an explicit object (in your case self
). You can use private_class_method
to define class methods as private (or like you described).
class Person
def self.get_name
persons_name
end
def self.persons_name
"Sam"
end
private_class_method :persons_name
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name
Alternatively (in ruby 2.1+), since a method definition returns a symbol of the method name, you can also use this as follows:
class Person
def self.get_name
persons_name
end
private_class_method def self.persons_name
"Sam"
end
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name
Related Topics
Webpack Error on Heroku Deployment
Editing JSON Array Contents in Ruby
Adding Nested Attributes to Devise User Model
No Such File to Load -- Soap4R -- Why
Ruby: Append Text to the 2Nd Line of a File
Illegal Quoting in Line 1 Using Ruby CSV
Local Server Error After Upgrading Ruby from 1.8.7 to 1.9.2 (With Rails 3.1.1)
Print Unicode Escape Codes from Variable
Can't Run a Ruby Hello World Application in Aptana
How to Mimic Browser X509 Client Certificate Verification Without Access to Http Layer
Placing Sub Arrays in Neat Rows
How to Handle Partials in an SCSS Project
Twitter API - Ruby Twitter Gem
Find a Unique Element in a Compound Array
How to Create This File Input and Output Assignment in Ruby