Search code examples
ruby-on-railsmodelvirtual-attribute

Preference values - static without tables using a model with virtual attributes


Im trying to eliminate two tables from my database. The tables are message_sort_options and per_page_options. These tables basically just have 5 records which are options a user can set as their preference in a preferences table. The preferences table has columns like sort_preferences and per_page_preference which both point to a record in the other two tables containing the options. How can i set up the models with virtual attributes and fixed values for the options - eliminating table lookups every time the preferences are looked up?


Solution

  • Create a app_config.yml file in config directory.

    page:
      small: 10
      medium: 20
      large: 30
    
    
    sort:
      name: name DESC  
      amount: amount ASC
      date: created_at DESC  
    

    Create UserOptions class in models directory.

    class UserOptions
      def self.page_option key
        options['page'][key] rescue nil  
      end
    
      def self.sort_option key
        options['sort'][key] rescue nil
      end
    
      def self.options
        @options ||=  YAML.load_file( File.join(RAILS_ROOT, 
                        "config", "app_config.yml")) rescue {}
      end
    
    
      # use this in the view to set the preference
      def self.page_collection
        option_collection 'page'
      end
    
      # use this in the view to set the preference
      def self.sort_collection
        option_collection 'sort'
      end
    
      def self.option_collection key
        (options[key]|| {}).to_a
      end
    end
    

    Configure your models:

    class User
      has_one :preference
    end
    
    class Preference
    
      def sort_preference(default = nil)
        UserOptions.sort_option(attributes['sort_preference']) || default
      end
    
      def per_page_preference(default = nil)
        UserOptions.page_option(attributes['per_page_preference']) || default
      end
    
    end
    

    Now you can do the following:

    current_user.preference.per_page_preference
    
    # use 10 as the page size if no value is given
    current_user.preference.per_page_preference(10)