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: http://imagebin.org/113043

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