0

What are my options for molding existing database table(s) to my model in rails? I have a has_one and belongs_to relation between two tables, but I'd like to join them and use that as a model (and select only the fields relevant). As this is an external table I'd also like to minimize the amount of queries.

I am inheriting an existing app and would like to not touch anything from the existing environment and slowly migrate. The existing database seems to have been made different from the rails way. I have a model of IdCard and IdCardRequest. One would assume that one IdCard hasmany IdCardRequests, however the IdCard has a property to the last IdCardRequest. It seems that the basic info such as applicant_name is a property of the IdCardRequest rather than IdCard. Luckily they both have a common property id_card_number and I could join it based on that by specifying foreign_key and primary_key to id_card_number. However for now I'd like a model IdCard with the rest of the fields of the IdCardRequest as property.

    class IdCard < ExternalTable
      self.table_name = 'id_cards'
      belongs_to :security_id_request, :foreign_key => 'request_id'
      default_scope { includes(:id_request) }
    end
    class IdRequest < ExternalTable
      self.table_name = 'id_request'
      has_one :id_card, :foreign_key => 'request_id'
    end
    # I would like IdCard.first.applicant_lastname
    # I have to call IdCard.first.id_request.applicant_lastname
    # I have to call IdCard.first.id_request.applicant_firstname
    # I could write a delegate_to for every property, but this seems cumbersome and inefficient.
Ig Norand
  • 23
  • 3
  • In the past, when I had a similar situation I did go for the `delegates` option. You can wrap the delegates in a loop over the attributes of `IdCard`, so you don't manually have to maintain them. That did work quite well. – niels Jan 17 '19 at 12:34
  • How would you do something like order by IdCard.first.applicant_lastname? – Ig Norand Jan 17 '19 at 17:08
  • Yeah, that's limit, you lose some flexibility. When you want that you have to do the plumbing yourself. I can't remember how we had those issues and how we dealt with them. Perhaps you could use scopes to deal with those cases, which doesn't really solve the issue but at least hides it? – niels Jan 18 '19 at 09:41

1 Answers1

1

Do you have the option of creating a database view that encapsulates both tables, and renames columns to rails conventions?

e.g.

create view id_card_requests as 
select 
  existing_column as desired_rails_column_name,
  ... 
from id_cards 
join id_card_requests on <whatever the join is>

You can then make a rails model IdCardRequests that will work as normal. You can make one of the columns a primary key in the view, or tell the model to use one of the columns with self.primary_key = :my_key_column

Matt
  • 13,948
  • 6
  • 44
  • 68
  • This was my train of thought too. It will allow me to do things easier and faster. I would however prefer to stay out of the database as much as possible. Could I make a seperate database for my models and place the view there where it gets the data from the 'untouched' database? – Ig Norand Jan 17 '19 at 17:07
  • 1
    Views are already separate from tables and making views doesn't affect data, it's a very safe approach and arguably neater than delegates.You won't break anything by creating a view. – Matt Jan 18 '19 at 10:33
  • I'd like it if we could create migrations that generate views – Ig Norand Feb 15 '19 at 11:58
  • @IgNorand You can, just have your migrate execute a sql command. `ActiveRecord::Migration.execute("CREATE VIEW [name] AS SELECT FROM ")` – Matt Feb 15 '19 at 17:07