Why callbacks use symbols in Ruby on Rails

I am trying to figure out when and when not to use symbols in Rails. I understand that characters are not too different from a string without many methods. I also understand that symbols make good keys, since symbols with the same name take up a single address in memory.

I am trying to understand why Rails decides to use symbols in some cases. If I had a callback

before_action :ask_stack_overflow_question

def ask_stack_overflow_question
  puts "why did I just use a symbol?"
end

      

I don't quite understand why treat the method as a symbol? Why do I need to maintain a constant method?

I cannot find an answer to this in the documentation.

thank

+3


source to share


4 answers


It's not as difficult as it sounds.

When called, before_action

you don't want the method to be executed immediately, but you need to describe the action that you want to perform in some way. The symbol is used here to denote the name of the method being called.

So, if it's fixed as name

, and then, somewhere in the code, it will be converted to send(name)

at the appropriate time.

There is a big difference between the two. Direct version:

before_action method_name

      



As a result of execution method_name

immediately, since Ruby will be forced to run method_name

to find out what it is returning, and then pass that before before_action

as an argument.

Deferred Agreement:

before_action :method_name

      

This is just a polite request before_action

passing a character as an argument. You leave him up before_action

to handle this, however he sees fit, so he may or may not execute this method in the future, it depends on the situation.

This is how it works in Ruby, with very few exceptions. The only one I can think of is not executing the method right away when it points right away and not as a representative symbol - this is a tricky construct alias

.

+7


source


If you are reading this code that defines the before_action on the second line :

[:before, :after, :around].each do |callback|
    define_method "#{callback}_action" do |*names, &blk|
      _insert_callbacks(names, blk) do |name, options|
        set_callback(:process_action, callback, name, options)
      end
    end

      



Which invocation is called set_callback

, which invokes the method when the method is called Which creates the callback chain. This chain of callbacks is formed here and then this method is used to execute. Now you can pass a string or as a character. But the preferred way is to pass the symbol as it is immutable and cannot be changed at runtime. get_callback

+1


source


Ruby symbols are immediate values. The importance in a symbol is the symbol itself. Therefore, in places where identity is important, you can use the symbol.

Memory wise, it is something that is persistent (during program startup), is immutable, is always the same object.

Strings don't have that luxury in Ruby. "this string" and "this string" will be two separate objects and are subject to garbage collection.

: this_symbol will not depend on garbage collection, it is always the same object, and as such is memory efficient. A symbol can refer to the local variable of the name this_symbol or the method of the name this_symbol or any other named object, but it can refer to the same object, namely this_symbol.

When not to use a symbol? When you need to have a lot of them temporarily, use them once, or use them multiple times, in the long run the program will eventually fill the memory, not hoping to reclaim that memory for other uses.

Thus, they don't use a symbol as a method, but Ruby refers to method names by their symbol. I think that method names that change will not be as useful as method names that remain unchanged.

+1


source


This is the cheapest way to refer to something, then the symbol makes sense.

There is usually an option to not use the symbol:

before_action do
  # do something
end

      

But this way you won't be able to reuse the method, just in case. You may also lose some expression.

Both options are correct in my opinion, no matter which option you choose, the important thing is that your code is readable and not redundant.

0


source







All Articles