KatPadi's Point

Yet Another Rails Adventure

I’ve been playing with storing and setting dynamic stuff in Rails because I’ve been repeating similar codes over and over and it’s becoming annoying. Luckily, I found a pattern and started to experiment from there.

In a nutshell, this is what I’m trying to achieve:

  1. Create dynamic re-usable sessions from a param[:filter] if it exists.
    For example:
    session[:teams_filter]
    session[:players_filter]
    session[:coaches_filter]
  2. That session will be used as an argument to a dynamic class.
  3. That class will be instantiated and saved to a dynamic instance variable.

The instance variable will then be used by the controller.

In this way, I am only going to include a module concern in the controller (that needs it) instead of repeating the same codes (just different variables and classes) that stores session, retrieves session, instantiates class and sets instance variable. I find this useful when especially when I have growing number of modules.

Assumptions: I have Filter::TeamFilterer, Filter::PlayerFilterer, Filter::CoachFilterer
Output: @coach_filter, @team_filter, @player_filter

[pastacode lang=”ruby” message=”” highlight=”” provider=”manual”]

module StoreFilter
  extend ActiveSupport::Concern

  included do
    before_action :store_dynamic_session, only: [:index]
  end

  def store_dynamic_session
    key = "#{controller_name}_filter"
    session[key] = params[:filter] || session[key]
    set_dynamic_instance
  end

  def set_dynamic_instance
    instance_key = "#{controller_name.singularize}_filter"
    instance_variable_set "@#{instance_key}", instantiate_dynamic_class
  end

  def instantiate_dynamic_class
    dynamic_class = "Filter::#{controller_name.singularize.camelize}Filterer"
    dynamic_class.constantize.new(session["#{controller_name}_filter"])
  end
end

[/pastacode]

store_dynamic_session

It’s the first method called but only when action=index in the controller. It stores the session based on params[:filter] or already existing session. It then calls, set_dynamic_instance.

set_dynamic_instance

It uses instance_variable_set, which I just learned about when I was trying this. Basically, it accepts symbol and the value that you want it set. It becomes an instance even though it wasn’t existing before. Here’s APIdoc’s full description:

Sets the instance variable names by symbol to object, thereby frustrating the efforts of the class’s author to attempt to provide proper encapsulation. The variable did not have to exist prior to this call.

By this time I already have an instance available to the specific controller!

instantiate_dynamic_class

This was called by the set_dynamic_instance. It instantiates a class based from string by using constantize and other Rails inflectors.

Initially, I placed these codes just in the application_controller and put “if” conditions to verify if the controller is going to implement it. The “ifs” grew bigger so, I transferred the codes to the controllers concern.

It’s more DRY as it is now. (I’d like to think so)

This is just a simple exploration. I’m not sure if there is a more elegant and correct way of doing this.

Leave a Reply

Your email address will not be published. Required fields are marked *