views:

40

answers:

2

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?

A: 

Try this:

class MessageSortOption

  def self.get_cached_option(id)
    # store the hash of the options in a class variable
    (@@option_cache ||= Hash[ *all.collect{|o| [o.id, o]}.flatten])[id]
  end

end

class PerPageOption

  def self.get_cached_option(id)
    # store the hash of the options in a class variable
    (@@option_cache ||= Hash[ *all.collect{|o| [o.id, o]}.flatten])[id]
  end
end

class User
  has_one :preference
end


class Preference

  def sort_preference
    MessageSortOption.get_cached_option(attributes['sort_preference'])
  end

  def per_page_preference
    PerPageOption.get_cached_option(attributes['per_page_preference'])
  end

end

Now you can access the preference as follows:

current_user.preference.sort_preference
current_user.preference.per_page_preference
KandadaBoggu
Sorry, it seems like you've got exactly what I'm looking for, but I'm not sure where to define the options.
Mike
You still need to store the `options` in your tables but now the data is cached.
KandadaBoggu
ohh, gotcha. Thanks :)
Mike
I have added another solution which does not require two tables to store options
KandadaBoggu
A: 

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)
KandadaBoggu