Anyone able to give suggestions on model design? I'm building an app to help small businesses get more reviews across the web. Concept is simple, user registers a business, and their businesses location(s). They then send emails to their clients that contain a direct link to their locations review site (google my business, facebook review page, yelp etc.) Models so far: Users, Businesses, Locations. Businesses have many locations. The end goal is there will be a review_request model (which keeps track of the review requests for each location sent to the businesses clients) and a review_sites model - which would contain info on the locations review site (example site_name:facebook, site_domain:https://facebook.com, location_page: facebook.com/business-id-here.
My question is, should I keep all review sites in one big ugly model? Or should I namespace them and give each specific review site its own model? example models/review_sites/google_site.rb?
The best advice for these types of questions will always depend upon what you want to do in the future with your app. Will you be treating Facebook, Google, etc reviews as mostly the same thing? Sure, you'll need to know the site and page the review was on, but will you have specific integrations with each site?
If they will stay mostly similar, then I'd keep it as a single model and just store the site like "google" "facebook" etc as a column and the url for the page. Then if you ever do need to add some more specific things you can just say "okay this is a google review, let's create a Google API client and sync any changes".
If you plan on having different functionality for each review type, then separate models make more sense. You can then add functionality that's unique to each site (maybe they have a lot of different attributes you want to store).
So it'll depend upon what you want to do going forward. You probably know that best since you're designing the product which means you'll probably have a better idea of which one will be most fitting with your product.
Thanks Chris! Yea I am leaning towards separate models just because eventually I would like to have each site have different functions and am limited by the different sites having different API options.
Do you think something like this would work?
User has_one business
Business has_many :locations
Location has_one :facebook_page, through => :review_sites
Location has_one :google_page, through => :review_sites
Location has_one :yelp_page, through => :review_sites
ReviewRequest belongs_to :customer belongs_to :business (if you want to attach it to a business, could also be location)
As you can see here, the concept of a "page" seems repeated so you may still want to consider how truly separate they are.
Business has_many :pages
Page belongs_to :business - site ("google", "facebook", "yelp") - url - number_of_reviews - average_rating - extra_data (json column, can be fully unique to each site)
Then you could just write other Ruby classes for handling the unique API situations. For example, to get the correct API client, you'd do something like:
def client case site when "google" GoogleApi.new(token) when "facebook" FacebookApi.new(token) end end
This would be a more generic way of approaching things. You can have a json column to store any data that's unique to each business instead of making separate models for each.
Personally I would probably take this approach with generic pages. I haven't seen anything that seems to prevent taking this approach. This is how I handle the different APIs for Hatchbox.io btw. Servers on Hatchbox are like Pages and Reviews in your app. Sure they may be on a different service, but I can still store the generic information I care about in a single table and just keep track of which service it is. Then I write Ruby classes to handle the specifics and store the data on the model. Unless the data is vastly different, you will probably be best off with the generic Page like I'm doing with Servers. You can have a json column to store your extra information that may be unique to each site. If there is a lot of unique information for each Page, then definitely split up the models.
Oh man, having a separate column with json to handle anything unique (which there really shouldn't be much of, if any) is brilliant! Just having a PORO handle any api stuff is perfect. I think that's exactly the route I will take.
Thanks so much for your help Chris! I really appreciate it.
One last question, when I'm building out forms, what would be the best way to have page-specific forms? Just create different views for specific pages?
As for the forms, you can just set the site in a hidden field. @page = Page.new(site: "google") for example.
Remember that your controllers don't have to directly map to models so you could have a controller for Google, separate from your Facebook one, and so on. Then you can have views that are unique so that you can have different designs, instructions, etc for each one.
... I never really thought about the fact that my controllers don't have to map directly to models :/ That makes perfect sense. I suppose I will do a generic Page controller, then site(yelp, facebook, google, etc.) specific when required.