For example, I want to make Object#rescue another name so I can use in my code like:
def dangerous
something_dangerous!
dont_worry # instead of rescue here
false
end
I tried
class ::Object
alias :dont_worry :rescue
end
But cannot find the rescue method on Object:
`<class:Object>': undefined method `rescue' for class `Object' (NameError)
Another example is I would like to have when in the language to replace:
if cond
# eval when cond is truthy
end
to
when cond
# eval when cond is truthy
end
Is it possible to give a Ruby keyword alias done in Ruby?
Or I need to hack on Ruby C source code?
Thanks!
This is not possible without some deep changes to the Ruby language itself. The things you describe are not methods but keywords of the language, i.e. the actual core of what is Ruby. As such, these things are not user-changeable at all.
If you still want to change the names of the keywords, you would at least have to adapt the language parser. If you don't change semantics at all, this might do it as is. But if you want to change what these keywords represent, things get messy really quick.
Also note that Ruby in itself is sometimes quite ambiguous (e.g. with regards to parenthesis, dots, spacing) and goes to great length to resolve this in a mostly consistent way. If you change keywords, you would have to ensure that things won't get any more ambiguous. This could e.g. happen with your change of if to when. when is used as a keywords is case statements already and would thus could be a source of ambiguity when used as an if.
I'd like to avoid my method:
def page_cover
return cover_title unless cover_title.match(/#{ capitalised_acronyms }/).present?
cover_title.gsub(/#{ capitalised_acronyms }/, $&.upcase)
end
because it looks Perly, and I heard of a news that it might be deprecated in the future. From the book:
Prefer String#match to String#=~. The former returns all the match information in a MatchData object instead of several special global variables.
Use the longer, more descriptive global variable aliases as opposed to their short cryptic names (e.g., $LOAD_PATH instead of $:). Most of the longer names are only available after loading the English library.
Avoid methods that implicitly read from, or write to, the $_ global variable (e.g., Kernel#print, Regexp#~, etc.).
I think I violated #3 in:
$&.upcase
Any suggestions are welcome.
While I neither agree nor disagree with a general principle of avoiding "Perlisms," I do agree that avoiding $+punctuation variables is a good way to improve the readability of your code.
There is no in-place substitute for $& (which holds the last regex match). You can, however, access the matched string using the MatchData object returned by String#match.
def page_cover
if matchdata = cover_title.match(/#{capitalised_acronyms}/)
cover_title.gsub(/#{capitalised_acronyms}/, matchdata[0].upcase)
else
cover_title
end
end
NOTE:
As written, this method (like your example method) will replace all matched lowercase acronyms with an uppercase version of only the first acronym matched: i.e. "I love the nfl and nba" becomes "I love the NFL and NFL". If that is unintentional, there is a much simpler way to write this method:
def page_cover
cover_title.gsub(/#{capitalised_acronyms}/, &:upcase)
end
This uses the & operator (which is completely unrelated to $&) to convert the symbol :upcase into the block {|x| x.upcase } behind the scenes.
I personally like to iterate using the for keyword in Ruby since it reads very clean, from my eye. I generally assume that for may be an alias to Enumerable#each, but I do not know whether is is correct. In the most basic example:
for i in (1..10)
puts i
end
behaves the same as
(1..10).each do |i|
puts i
end
just without creating a new variable scope. Moreover, ruby-doc says
The for loop is rarely used in modern ruby programs.
which makes me feel there is a specific, technical reason against the usage. Does it matter that there's no new variable scope? In what way?
behaves the same as
This is incorrect. for is built on top of each, but it is semantically distinct:
array = %w(a b c d)
array.each { |character| }
defined? character # nil
for character in array; end
defined? character # "local-variable"
The for keyword doesn't introduce a new scope. Any variables introduced inside the block remain visible outside of it; as if it was written inline.
You should take this fact into account when you decide which form to use.
Is there something built-in with Ruby to determine if a string is a reserved word? Something like "next".is_keyword??
The only way I can think of is loading an array with all the keywords you know about.
class String
def is_keyword?
%w{__FILE__ __LINE__ alias and begin BEGIN break case class def defined? do else elsif end END ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield}.include? self
end
end
"foobar".is_keyword? # => false
"for".is_keyword? # => true
For reference:
I know this isn't a built-in way, it's just the only way I could think of. Don't downvote me for it.
The list I included is that of true keywords. public, protected and friends aren't really keywords, just the names of important methods which are called during the creation of modules or classes. You can think of it as elements of the Ruby DSL.
As far as I know, protected isn't really a reserved word. It's just the name of an important method.
http://wiki.rubyonrails.org/rails/pages/reservedwords lists reserved words you can't use (some of them only apply if you're using Rails or its dependencies), and method names that can cause problems.
If this doesn't fully answer your question, can you define more fully whether you're interested in method names or variable names, and whether you're worried about words that can't be used at all, or words that may cause other things to go wrong?
Use Ruby gem rubykeyword. It does more than identifying the keyword. string.keyword? tells you if its keyword or not. string.define gives a definition of the keyword. There is string.example too.
If you have a class where you want to implement a method called "protected", then before you define that method make an instance of that class and call
instance.methods
This will show you all the methods inherited for the class, and if "protected" is there then it is reserved by ruby.
In Ruby some methods have a question mark (?) that ask a question like include? that ask if the object in question is included, this then returns a true/false.
But why do some methods have exclamation marks (!) where others don't?
What does it mean?
In general, methods that end in ! indicate that the method will modify the object it's called on. Ruby calls these as "dangerous methods" because they change state that someone else might have a reference to. Here's a simple example for strings:
foo = "A STRING" # a string called foo
foo.downcase! # modifies foo itself
puts foo # prints modified foo
This will output:
a string
In the standard libraries, there are a lot of places you'll see pairs of similarly named methods, one with the ! and one without. The ones without are called "safe methods", and they return a copy of the original with changes applied to the copy, with the callee unchanged. Here's the same example without the !:
foo = "A STRING" # a string called foo
bar = foo.downcase # doesn't modify foo; returns a modified string
puts foo # prints unchanged foo
puts bar # prints newly created bar
This outputs:
A STRING
a string
Keep in mind this is just a convention, but a lot of Ruby classes follow it. It also helps you keep track of what's getting modified in your code.
The exclamation point means many things, and sometimes you can't tell a lot from it other than "this is dangerous, be careful".
As others have said, in standard methods it's often used to indicate a method that causes an object to mutate itself, but not always. Note that many standard methods change their receiver and don't have an exclamation point (pop, shift, clear), and some methods with exclamation points don't change their receiver (exit!). See this article for example.
Other libraries may use it differently. In Rails an exclamation point often means that the method will throw an exception on failure rather than failing silently.
It's a naming convention but many people use it in subtly different ways. In your own code a good rule of thumbs is to use it whenever a method is doing something "dangerous", especially when two methods with the same name exist and one of them is more "dangerous" than the other. "Dangerous" can mean nearly anything though.
This naming convention is lifted from Scheme.
1.3.5 Naming conventions
By convention, the names of procedures
that always return a boolean value
usually end in ``?''. Such procedures
are called predicates.
By convention, the names of procedures
that store values into previously
allocated locations (see section 3.4)
usually end in ``!''. Such procedures
are called mutation procedures. By
convention, the value returned by a
mutation procedure is unspecified.
! typically means that the method acts upon the object instead of returning a result. From the book Programming Ruby:
Methods that are "dangerous," or modify the receiver, might be named with a trailing "!".
It is most accurate to say that methods with a Bang! are the more dangerous or surprising version. There are many methods that mutate without a Bang such as .destroy and in general methods only have bangs where a safer alternative exists in the core lib.
For instance, on Array we have .compact and .compact!, both methods mutate the array, but .compact! returns nil instead of self if there are no nil's in the array, which is more surprising than just returning self.
The only non-mutating method I've found with a bang is Kernel's .exit! which is more surprising than .exit because you cannot catch SystemExit while the process is closing.
Rails and ActiveRecord continues this trend in that it uses bang for more 'surprising' effects like .create! which raises errors on failure.
From themomorohoax.com:
A bang can used in the below ways, in order of my personal preference.
An active record method raises an error if the method does not do
what it says it will.
An active record method saves the record or a method saves an
object (e.g. strip!)
A method does something “extra”, like posts to someplace, or does
some action.
The point is: only use a bang when you’ve really thought about whether
it’s necessary, to save other developers the annoyance of having to
check why you are using a bang.
The bang provides two cues to other developers.
that it’s not necessary to save the object after calling the
method.
when you call the method, the db is going to be changed.
Simple explanation:
foo = "BEST DAY EVER" #assign a string to variable foo.
=> foo.downcase #call method downcase, this is without any exclamation.
"best day ever" #returns the result in downcase, but no change in value of foo.
=> foo #call the variable foo now.
"BEST DAY EVER" #variable is unchanged.
=> foo.downcase! #call destructive version.
=> foo #call the variable foo now.
"best day ever" #variable has been mutated in place.
But if you ever called a method downcase! in the explanation above, foo would change to downcase permanently. downcase! would not return a new string object but replace the string in place, totally changing the foo to downcase.
I suggest you don't use downcase! unless it is totally necessary.
!
I like to think of this as an explosive change that destroys all that has gone before it. Bang or exclamation mark means that you are making a permanent saved change in your code.
If you use for example Ruby's method for global substitutiongsub!the substitution you make is permanent.
Another way you can imagine it, is opening a text file and doing find and replace, followed by saving. ! does the same in your code.
Another useful reminder if you come from the bash world is sed -i has this similar effect of making permanent saved change.
Bottom line: ! methods just change the value of the object they are called upon, whereas a method without ! returns a manipulated value without writing over the object the method was called upon.
Only use ! if you do not plan on needing the original value stored at the variable you called the method on.
I prefer to do something like:
foo = "word"
bar = foo.capitalize
puts bar
OR
foo = "word"
puts foo.capitalize
Instead of
foo = "word"
foo.capitalize!
puts foo
Just in case I would like to access the original value again.
Called "Destructive Methods" They tend to change the original copy of the object you are referring to.
numbers=[1,0,10,5,8]
numbers.collect{|n| puts n*2} # would multiply each number by two
numbers #returns the same original copy
numbers.collect!{|n| puts n*2} # would multiply each number by two and destructs the original copy from the array
numbers # returns [nil,nil,nil,nil,nil]
My answer explains the significance of Ruby methods with exclamation marks/shebangs in the context of Ruby on Rails (RoR) model validations.
Essentially, whenever developers define Model validations (explained here), their ultimate goal is to decline a database record change & raise/throw the relevant exception(s) in case invalid data has been submitted to update the record in question.
RoR ActiveRecord gem defines various model manipulation methods (Ruby on Rails guides.). Among the methods, the valid? method is the only one that triggers validation without database action/modification. The rest of the methods attempt to change the database.
These methods trigger callbacks whenever they run. Some of the methods in the list feature a sister method with a shebang. What is the difference between the two? It has to do with the form of callback returned whenever a record validation fails.
Methods without the exclamation/shebang merely return a boolean false in the event of record validation failure while the methods with a shebang raise/throw an exception which can then be handled appropriately in code.
Just as a heads-up, since I experienced this myself.
In Ruby, ! mutates the object and returns it. Otherwise it will return nil.
So, if you are doing some kind of operations on an array for example, and call the method .compact! and there is nothig to compact, it will return nil.
Example:
arr = [1, 2, 3, nil]
arr.compact!
=> [1, 2, 3]
Run again arr.compact!
=> nil
It is better to explicitly return again the array arr if you need to use it down the line, otherwise you will get the nil value.
Example:
arr = [1, 2, 3]
arr.compact! => nil
arr # to get the value of the array