1
votes

I think it is more of a "Model Design" issue than a rails issue.

For clarity sake here is the business logic: I've Venues and I want to implement multiple APIs to get data about those venues. All this APIs have a lot in common, therefore I used STI.

# /app/models/venue.rb
class Venue < ApplicationRecord
  has_one :google_api
  has_one :other_api
  has_many :apis
end

# /app/models/api.rb
class Api < ApplicationRecord
  belongs_to :venue
end

# /app/models/google_api.rb
class GoogleApi < Api
  def find_venue_reference
    # ...
  end
  def synch_data
    # ...
  end
end

# /app/models/other_api.rb
class OtherApi < Api
  def find_venue_reference
    # ...
  end
  def synch_data
    # ...
  end
end

That part works, now what I'm trying to add is Photos to the venue. I will be fetching those photos from the API and I realise that every API might be different. I thought about using STI for that as well and I will end up with something like that

# /app/models/api_photo.rb
class ApiPhoto < ApplicationRecord
  belongs_to :api
end

# /app/models/google_api_photo.rb
class GoogleApiPhoto < ApiPhoto
  def url
    "www.google.com/#{reference}"
  end
end

# /app/models/other_api_photo.rb
class OtherApiPhoto < ApiPhoto
  def url
    self[url] || nil
  end
end

My goal being to have this at the end # /app/models/venue.rb class Venue < ApplicationRecord has_one :google_api has_one :other_api has_many :apis has_many :photos :through => :apis end

# /app/views/venues/show.html.erb
<%# ... %>
@venue.photos.each do |photo|
   photo.url
end
<%# ... %>

And photo.url will give me the right formatting that is dependent of the api it is.

As I'm going deeper in the integration, something seems not right. If I had to Api the has_many :google_api_photo then every Api will have GoogleApiPhoto. What does not make sense to me.

Any idea how I should proceed from here?

1

1 Answers

0
votes

I think I solved it.

By adding this to venue.rb

has_many :apis, :dependent => :destroy
has_many :photos, :through => :apis, :source => :api_photos

By calling venue.photos[0].url call the right Class based on the type field of the ApiPhoto