Search code examples
ruby-on-railssinatradatamapperpadrinoruby-datamapper

Datamapper [ruby] on Legacy Schemas


I'm working with a legacy schema which has 3 particular tables backing a single class, listed below:

  • table_1_month
    • # All items that are < 1 month old.
  • table_1_year
    • # All items that are between 1 month and 1 year old.
  • table
    • # All items that are older than 1 year.

All 3 tables have the same schemas, but the only difference between them is that the time it was last updated determines which table the rows exist in.

I know Datamapper has the ability to specify different storage_names via the following syntax:

class Klass
  storage_name[:default] = "table"
  storage_name[:onemonth] = "table_1_month"
  storage_name[:oneyear] = "table_1_year"
end

How would I write a query that specifies the repository by which an article is accessed? (For example, the query to access all rows that are 2 months old would require retrieving and appending all rows from table_1_month to a subset of the rows in table_1_year)


Solution

  • The easiest way that I was able to get something along the lines of what I wanted was to add new repositories.

    Datamapper.setup(:default), <Insert database connection url>
    DataMapper.setup(:onemonth), <Insert the same database url>
    Datamapper.setup(:oneyear), <Insert the same database url>
    

    In the model class,

    class Klass
      storage_name[:default] = "table"
      storage_name[:onemonth] = "table_1_month"
      storage_name[:oneyear] = "table_1_year"
    
      # Psuedocode
      def get_from_timeperiod(start_time, end_time)
        time_one_year_ago = <some other int>
        time_one_month_ago = <some int>
        if end_time < time_one_month_ago
          DataMapper.repository(:onemonth) { self.all( self.updated => (start_time..end_time) ) }
        elif end_time < time_one_year_ago
          DataMapper.repository(:oneyear) { self.all( self.updated => (start_time..end_time) ) }
        else
          self.all( self.updated => (start_time..end_time) )
        end
      end
    end
    

    (Update 10/31 6:13pm) The other alternative that I found is to use a direct database query instead of the DataMapper.repository(:onemonth) { } which results to struct objects:

     repository(:default).adapter.select("SELECT * FROM table_one_month WHERE updated between #{start_time} and #{end_time}")
    

    I personally find that the first way is a lot cleaner.

    Please let me know if there's anything better that I can do!