Search code examples
ruby-on-railsrubyoopmethodsaccessor

How can I access a ruby object's method by using a hash syntax?


I am working on Ruby on Rails, and I want to create a helper method for my view. I must pass an active record object, a symbol variable and a title to the method.

The objective of this method is to take the data, create some < strong > and < p > tags to put the title and the object attribute on the database (by accessing with the symbol variable) and get a nice HTML bit of code to put on my view.

Everything works fine, except when I need to display some of the object's attribute (like a datetime attribute, or a boolean value) which I need to call a specific object's method. For example, get the status of the user If he has confirmed his email, return string "Confirmed", if not, return string "Unconfirmed".

  • Helper code
module UsersHelper
    def user_show_field(user, column, title=nil)
        title ||= column.titleize
        return "<p><strong>#{title}</strong>: #{user[column]}</p>".html_safe
    end
end
  • View code
<%= user_show_field(@user, :city, "City") %>

In the example above, there will be no problem, because :city is a attribute from the user. So the helper method will attempt to make the call

@user[:city]

However, if I want to get the status of my user, I'll need to call the get_status method of my user:

@user[:get_status]

This Will return nil, because :get_status is not a attribute on the database of my user model: it is a method defined on my app/models/user.rb

class User < ApplicationRecord
    def get_status
        return registered ? "Email confirmed" : "Unconfirmed user"
    end

end

How can I add some code to my user model, so I can use the helper with both the attributes on the database or model's method?


Solution

  • You can invoke methods with a symbol or a string using send (note that you can even call private methods with send, you can use public_send instead).

    @user.send(:get_status)
    

    If your method requires parameters, just add the separated by comma:

    @user.send(:another_method, param1, param2)
    

    https://ruby-doc.org/core-2.1.0/Object.html#method-i-public_send