Polymorphic advice for this design

With this ER diagram. should the suggestions table be polymorphic?

Or OPTION 2: should i just have two separate tables called business_suggestion and city_suggestion?

I was thinking polymorphic since the columns first_name, last_name and email will be used in the business_suggestion and city_suggestion tables.

If I go with OPTION 2, then the business_suggestion and city_suggestion tables will have first_name, last_name and email columns. Which is a bit redundant...

Here is the ER diagram: Startseite - imagebin.org

What are your thoughts?

I'd be less worried about the columns, but more focused on the entities involved...

Your 'suggestion' seems to be analogous to a 'contact', and a contact may well be tied to a business and/or a city (business leaders often sit on local/city councils/chambers/whatever they are called - sometimes with separate phone/address/email, sometimes not).

So I could perhaps see:

Business   has_many :suggestionlinks, :as => :sugglinkable   has_many :suggestions, :through => :suggestionlinks

City   has_many :suggestionlinks, :as => :sugglinkable   has_many :suggestions, :through => :suggestionlinks

Suggestion   has_many :suggestionlinks   has_many :businesses, :through => :suggestionlinks, :source => :business, :conditions => "suggestionlink.sugglinkable_type = 'Business'"   has_many :cities, :through => :suggestionlinks, :source => :city, :conditions => "suggestionlink.sugglinkable_type = 'City'"

Suggestionlink   # id INT   # suggestion_id INT   # sugglinkable_type VARCHAR()   # sugglinkable_id INT   belongs_to :suggestion   belongs_to :sugglinkable, :polymorphic => true   belongs_to :business, :class_name => 'Business', :foreign_key => 'sugglinkable_id'   belongs_to :city, :class_name => 'City', :foreign_key => 'sugglinkable_id'

Or something like that

Ar, what I am trying to do is allow users to suggest a business and or city. I want to have a database record for this.

Why do I need a Suggestionlink model?

Also note, a user does not need to be registered or signed in to suggest. Hence, why they should provide their first_name, last_name and email

Ar, your solution is not very clear. Can you also indicate columns and migration file

Hmm... seems my interpretation of what you are attempting to do doesn't match very well with your unstated goals... You were asking whether the suggestion model should be polymorphic...

Sooo, what exactly is a suggestion in the context of your application (what are your users doing)?

Hi Ar,

End-users can either be registered or non-registered users. Any type of user can suggest a business and a city.

When they suggest a city, they have to put in their first_name, last_name, email and city name.

When they suggest a business. They have to put in their first_name, last_name, email, business name and business address.

Initially, I had it working with two separate models: city_suggestion and business_suggestion. However, since both tables have fields that can be reused (i.e. first_name, last_name, email), I was thinking of using a polymorphic association.

I am not sure if this is the right approach or whether I should have just stuck with my original solution (i.e. two separate tables: city_suggestion and business_suggestion)

no you need single table inheritance

is way better in your case , read a bit about STI, it lets you create one table and one model and then inherit from that model

list this

class BaseSugesstions < ActiveRecord :: base

attr_accessible first_name, last_name, email, city_name, business_name

end

then

class citySugesstions < BaseSugesstions

attr_accessible first_name, last_name, email, city_name

end

class BaseSugesstions < BaseSugesstions

attr_accessible first_name, last_name, email, business_name

end

one table should on the database should have all the field defined in BaseSugesstions

Thanks redhames. Will look into this

Radhames, how do I go about creating the controllers for CitySuggestion and BusinessSuggestion? Can I use the scaffold generator for these two?

Or should I use the Suggestions controller to handle both? For example, where is the view/form to add new CitySuggestion? Should this be in the Suggestions controller?

I'm a bit confused here...

well, from now on you can forget about the base model if you want to and use everything as if they are 3 table and 3 models, do as you would normally would with a simple model just dont use the base BaseSugesstions unless is an admin and want to do something special. create scaffolds for citySugesstions and BussinesSuggestion (by the way there is a typo en my example the second class is supposed to be BussinesSuggestion not BaseSuggestion) with free access to create and their own views and forms. For adminsitration purposes and for your benefit create a basesugetion controller for staticstics, un the base model you can use all kinds of scopes to check and compare.

Hi Redhames,

Ok my form for city_suggestions looks like:

<% form_for @city_suggestion do |f| %>   <%= f.error_messages %>

  <p>     <%= f.label :first_name %><br />     <%= f.text_field :first_name %>   </p>   <p>     <%= f.label :last_name %><br />     <%= f.text_area :last_name %>   </p>   <p>     <%= f.label :email %><br />     <%= f.text_field :email %>   </p>   <p>     <%= f.label :city_name %><br />     <%= f.text_field :city_name %>   </p>

  <p>     <%= f.submit 'Save' %>   </p> <% end %>

When I submit this, it saves this into the Suggestions table. However, the entry is not saved in the CitySuggestions table. Should I have a line in my CitySuggestions that explicitly saves the entry to this table as well? Or is RoR supposed to do this automatically?

errr, there was suppose to be only on table, and 3 model, one that really is the table and the other that inherit from the base one, thats why it does not save to the citysuggestions table, its not suppose to exist, you are user the same table for both models because their only difference are 2 fields. Treat city_sugestions as if it has its own table , but dont create a table for it.

I forgot to maention that the table should have a field called type so that when active record saves , it will save what type of sugestions you are saving to read a sugestion user sugestion[:type]= city_sugestion or just do City_sugestion.find(:all)

i have to go to work no ill be available in 40 mintutes if you need more details

I thought you said I needed to scaffold the citysuggestion and businesssuggestion? Scaffold generates controllers, views, and models (if they already dont exist)?

If I do rake db:migrate, it generates the tables in the db. Should I remove the migration files that the scaffold generator generates before doing rake db:migrate?

Christian Fazzini wrote:

I thought you said I needed to scaffold the citysuggestion and businesssuggestion? Scaffold generates controllers, views, and models (if they already dont exist)?

If I do rake db:migrate, it generates the tables in the db. Should I remove the migration files that the scaffold generator generates before doing rake db:migrate?

Stop relying so much on the scaffold generator. You've probably gone beyond the point where it's useful.

Best,

Yes I know, I am just trying to understand how to implement this properly. It's easy enough to rollback the migration and remove the respective migration files. However, I need to know whether I need controllers, models and views for citysuggestion and businesssuggestion

sorry i forgot you use scaffold , here is the thing ill make a guide for this , from the migration step by step to the view

create a table like this

create_table :sugestions do |t| t.string first_name t.string last_name t.string email t.string business_name t.string business_address t.string city_name t.string type end

no more tables are needed

create a model

Sugestion , (singular) as normal it should inherit from active record base like this

class Sugestion < ActiveRecord::Base

attr_accessible : first_name,last_name, email, business_name, business_address, city_name

then create the tu other model that inherit from Sugestion, note that is they is a capital letter in the model name rails will put an underscore like this city_sugestions_controller

class CitySugestion < ActiveRecord::Base

attr_accessible : first_name,last_name, email, city_name

and another

class bussinessSugestion < ActiveRecord::Base

attr_accessible : first_name,last_name, email,business_name, business_address

note i think type should not be available with mass assignment.

then create the controllers for the 2 sugestions classes

city_sugestions_controller

and

bussiness_sugestions_controller

from here one this controller will never notice you have only one table they will behave as if you had 2 different tables in the db

in you views just refer to @bussinesssugestions and it will be scoped thanks to the type field that active record will automaticly use then you save an object of either class. Dont try to access the type field using @citysuggestion.type or @suggestion.type as type is a ruby method and will be called instead of the table field, use @sugestion[:type] , the other fields can be called as normal.

If you want to handle the sugestion class directly you can create a sugestions_controller, it its corresponding viwes for it and have a named scope that filter each type.

Dont be afraid to keep asking if you are still confuse and keep in mind that in most case, people are not specting that you would use scaffolds every time since scaffold are more like a learning tool that an actual way of doing things.

if you want to use scaffold anyway you can create the scaffold and skip creating the migrations with

script/generate scaffold --skip-migrations

Thanks Radhames. Ok I got it up to there. I am assuming since we are creating controllers for city_suggestions and business_suggestions, we will also need to create view for them respectively? i.e. /app/views/ city_suggestions and /app/views/business_suggestions right?

I appreciate your patience and thorough explanation regarding STI. Once I grasp this concept properly, I can apply the same knowledge on other cases :slight_smile:

yes thats rigth, everything will behave as if you had 2 tables , is normal RoR from now on.

yes dont be afraid to ask.

Redhames, got it thanks! Have tested this and now seems to work. Even the type field is put in automatically when the form submits.

Is this normal that the type field saves as "CitySuggestion" and "BusinessSuggestion" respectively? Can I change the way it saves, as "city" or "business", instead?

Can we talk about the design factor for this. I realise the potential of STI's now. However, lets assume this scenario.

Ive got user and product. A user can leave comments, like, upload products. These are called interactions. On a product page, I need to display the product and all comments for the product. I also have a user page with a section that displays all the users recent interactions, sorted by the created_at date.

I was thinking of using an STI for this, with something like:

class Interaction < ActiveRecord::Base attr_accessible :user_id, :product_id, :comment, :ip_address, :type