Ruby symbol naming - ruby-on-rails

I am currently reviewing a clients code base for the company I am interning for. The API is built with Ruby on Rails. I am new to Ruby, but have programmed in other languages, so looking through the code (and some tutorials), I have been able to understand most of what is going on, but there is a line that looks like the code below that is throwing me off. Why do the names of the symbols have equals in front? This feels illegal, but ruby is kinda cool. Thank you for your help.
delegate :name=, :description=, :tags=, to: :user

Another point: In Ruby, as a pattern you don't use the prefixes set or get, instead you use just the attribute name for the get and suffix = for the set. Example: setName and getName methods would be name= and name respectively.
Ruby allows you to use the setter method in these sintaxes: obj_instance.name = 'Name' (You can omit the () and use space before caracteres like =) or obj_instance.name=('Name').

A ruby symbol has very few restrictions concerning the characters it can have, and it's mainly linked to the "easy" representation we usually choose.
It's totally possible to have the following symbols:
:"hello/world"
:€
:"a+b"
It becomes a bit trickier when the symbol is used to represent a method, because we like the easy syntax that comes with it, but it's actually the same as sending the symbol using e.g. public_send:
foo.public_send(:"a+b")
This code will work if you define a method named :"a+b". Of course, you can't define it with the usual def, but it's still possible.
Now, some methods such as name= offer an additional semantic, so that the following are equivalent:
object.name = "Fubar"
object.send(:name=, "Fubar")

Related

Rails - Call a method form a model or helper with an alias

I have a helper called GlobalHelper.
There are a couple of constants (e.g. GLOBAL_URL) and methods (e.g. self.get_url) in it.
I'm trying to make an alias or an equivalent of the macros in C (#define URL) to access the constant and methods from any of my views and controllers easily.
For now I have to do it like this:
GlobalHelper.get_url(GlobalHelper::URL_TYPE_PAGE, ["page1"])
And I want to get rid of the GlobalHelper everywhere with alias/macro to get a code like this instead:
aliasmethod(aliasconstant, ["page1"])
How can I do that?
ruby is not c, so you should take a look how to write ideomatic ruby code before trying to bring such concepts into your project.
since i don't know what exactly your get_url method does, i can only give limited recommendations.
one thing that would probably result in much nicer code is using symbols instead of constants:
GlobalHelper.get_url(:page, ["page1"])
when using a Module instead of Class you can include it and call the method directly:
include GlobalHelper
get_url(...)
these are just examples of what could be done. not saying that this is better than explicitly calling GlobalHelper directly. nothing wrong with that at all.

Shortcut for conditional variable manipulation in Ruby/Rails

One of the parameters my API controller receives has a big key name and I need to convert it from string to integer, if it is present, before sending it to the model to be persisted. Usually I would do one of the following:
params[:really_big_key_name] = params[:really_big_key_name].to_i unless params[:really_big_key_name].blank?
or
params[:really_big_key_name] = params[:really_big_key_name].present? ? params[:really_big_key_name].to_i : nil
As you can see, the code line becomes big, with more than 80 characters, and I want to stick with Ruby best practices. Is there a shorter, more Ruby way to do the same? Maybe "in place" methods. Something like arrays do with bang methods. Unfortunately, to_i! does not exist for strings, which is exactly what I need.
You could do this:
params[:really_big_key_name] = params[:really_big_key_name].try(:to_i)

See where a symbol is defined in irb

I work on a pretty large rails project at work. Sometimes I need to hunt down class / constant definitions. Is there some built-in method in Ruby to do this for me? Example:
irb> SOME_CONSTANT.__file__
=> /some/path/to/a/file
This isn't exactly what you're looking for, but methods do have a .source_location method on them. You can use this to find out where a class is actually implemented. (Since ruby lets you reopen classes, this could be in multiple places)
for example, given an instance of an object, i:
i.methods.map do |method_name|
method_obj = i.method(method_name)
file, line = method_obj.source_location
file #map down to the file name
end.uniq
will give you a list of all the files where i's methods are implemented.
This will work for classes that have at least 1 method implemented in ruby. It won't work for constants, though.
At the very beginning before any file is loaded, insert a line that defines the class/constant that you want to check as something other than a module. For example, suppose you have class or other kind of constant A within your code, and want to know where it is defined. Then, at the very beginning of the main file, write
A = nil
Then, when the program is run, whenever it first meets the definition of class/constant A, it will show something like
some_path_to_a_file:line_number in `some_method': A is not a class (TypeError)
or
some_path_to_a_file:line_number: warning: already initialized constant A
Then, some_path_to_a_file:line_number will be the location where A is defined.
If you're using Ruby 1.9.2, #YenTheFirst's answer is correct: call #source_location on a Method object.
If you're using Ruby 1.8.7, then #source_location doesn't exist (yet). You'll need something like this implementation of a method. (There's another one or two floating around, but I can't find the other one real quick).

Ruby on Rails- :symbols, #iVars and "strings" - oh my!

New to Rails and trying to get my head around when/why to use :symbols, #ivars , "strings" within the framework.
I think I understand the differences between them conceptually
only one :symbol instance per project
one #ivar per instance
multiple "strings" - as they are created whenever referenced (?)
Feel free to correct me!
The main confusion comes from understanding the rules & conventions of what Rails expects - where and WHY?
I'm sure there's an "Ah ha!" moment coming but I haven't had it yet...as it seems pretty arbitrary to me (coming from C/Obj-C).
-thx
The #instance_variable is an instance variable. It is usually defined in the controller and accessible in the views.
The "string" is a string, like as in any other language.
The :symbol, is as you mentioned it's an efficient way of representing names and strings; they are literal values. It is initialized and exists only once during the ruby session. It's not a string, since you don't have access to String methods; it's a Symbol. On top of that, it's immutable. For those reasons, it becomes very handy in representing keys in hashs. Rails methods uses hashes, thus, you find symbols a bit everywhere in Rails.
Instance variables are pretty straightforward: they track properties/values of a particular instance, so you use them when you the values will vary across instances.
Symbols vs. strings are a bit more arbitrary. Symbols are generally used for constant values, in much the same way that a language such as C would use enums; Ruby doesn't have enums, so symbols are often used to fill that gap. Strings are used for more varied pieces of text that won't be used as a flag or similar constant.
Symbols are kind of like pointers (not in the C-ish way, but in C-ish thinking, they point). Well, you use symbols when you are manipulating properties. They are one of the great benefits of dynamic typing if you'd ask me. (For potential voters I do not mean any harm, I do know that they are not pointers, but it felt 'ah-ha!' for me).
:action => "index"
Instance variables are needed when you fetch data from your model and you want to use them across your views (inside your controller method).
def my_controller_method
#myposts = Post.find(:all)
end
# inside view
<% for #myposts do |m| %>
<i><%= m.title %></i>
<% end %>
Just a heads up, the rules and conventions kinda change rapidly (as I discovered on my Rails journey) quite a lot per version. Having the right guide with the right Rails helps. Good luck with coding!
Instance variables don't really belong in the same list as strings and symbols. Strings and Symbols are types of classes whereas instance variables are a type of variable. So instance variables (#var) are just a way to store a value between methods of one instance of one class:
class Calculator
#counter = 0
def inc
#counter += 1
end
def dec
#counter -= 1
end
end
Here is a good article on the distinction between symbols and strings.
The Rails controller access the rails database through Models by ORM (Object Relation Mapping)i.e Model class will mapped to its corresponding table and Objects are directly mapped to rows in the table.In order to get the results for a given user query,the instance variable (#instance_variable) is the perfect choice to deal with it.

When you say Ruby is reflective, does this mainly refer to "duck typing"?

I was reading a text describing Ruby and it said the following:
Ruby is considered a “reflective”
language because it’s possible for a
Ruby program to analyze itself (in
terms of its make-up), make
adjustments to the way it works, and
even overwrite its own code with other
code.
I'm confused by this term 'reflective' - is this mainly talking about the way Ruby can look at a variable and figure out whether it's an Integer or a String (duck typing), e.g.:
x = 3
x = "three" # Ruby reassigns x to a String type
To say Ruby is "reflective" means that you can, for instance, find out at runtime what methods a class has:
>> Array.methods
=> ["inspect", "private_class_method", "const_missing",
[ ... and many more ... ]
(You can do the same thing with an object of the class.)
Or you can find out what class a given object is...
>> arr = Array.new
=> []
>> arr.class
=> Array
And find out what it is within the class hierarchy...
>> arr.kind_of?
>> arr.kind_of? Array
=> true
>> arr.kind_of? String
=> false
In the quote where they say "it’s possible for a Ruby program to analyze itself" that's what they're talking about.
Other languages such as Java do that too, but with Ruby it's easier, more convenient, and more of an everyday part of using the language. Hence, Ruby is "reflective."
No, it means that you can issue a ruby command to get information about, well, just about anything. For example, you can type the command File.methods() to get a listing of all methods belonging to the File module. You can do similar things with classes and objects -- listing methods, variables, etc.
Class reopening is a good example of this. Here's a simple example:
class Integer
def moxy
if self.zero?
self - 2
elsif self.nonzero?
self + 2
end
end
end
puts 10.moxy
By reopening a standard Ruby class - Integer - and defining a new method within it called 'moxy', we can perform a newly defined operation directly on a number. In this case, I've defined this made up 'moxy' method to subtract 2 from the Integer if it's zero and add two if it's nonzero. This makes the moxy method available to all objects of class Integer in Ruby. (Here we use the 'self' keyword to get the content of the integer object).
As you can see, it's a very powerful feature of Ruby.
EDIT: Some commenters have questioned whether this is really reflection. In the English language the word reflection refers to looking in on your own thoughts. And that's certainly an important aspect of reflection in programming also - using Ruby methods like is_a, kind_of, instance_of to perform runtime self-inspection. But reflection also refers to the the ability of a program to modify its own behavior at runtime. Reopening classes is one of the key examples of this. It's also called monkey patching. It's not without its risks but all I am doing is describing it here in the context of reflection, of which it is an example.
It refers mainly at how easy is to inspect and modify internal representations during run-time in Ruby programs, such as classes, constants, methods and so on.
Most modern languages offer some kind of reflective capabilities (even statically typed ones such as Java), but in Ruby, it is so easy and natural to use these capabilities, that it really make a real difference when you need them.
It just makes meta-programming, for example, an almost trivial task, which is not true at all in other languages, even dynamic ones.

Resources