Forum: Ruby on Rails Model Inheritance, Mixins and Database design

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Anthony G. (Guest)
on 2006-03-05 12:49
I'm trying to understand how best to use inheritance and wonder if
Rail's Single Table Inheritance model too restricting.

I have a model Companies who provide 1+ Services (HABTM relationship).

I assume the best way to represent this is with a series of child models
representing each type of service : ServiceType < Company.

I want to return lists of companys for each service and then link to
show more details about them.

With the show method inherited from the Companies controller though
changing the :id on the end of the url displays the next record in the
companies table whereas I want to display the next company that also has
that service available.



I was  wondering a number of things:

1/ Should be overloading the find method in the ServiceType models.

2/ a/ Should I be trying to inherit the View for Company for ServiceType
   b/ by invoking Ruby's super keyword somehow.

3/ Would it be better to have individual db table representing each
ServiceType
 will the extra properiies that each ServiceType has in addition to the
inherited Company properities require this


_tony
Alain R. (Guest)
on 2006-03-05 13:36
(Received via mailing list)
Anthony

    > I have a model Companies who provide 1+ Services (HABTM
relationship).
    > I assume the best way to represent this is with a series of child
models
    > representing each type of service : ServiceType < Company.

I don't understand your reasoning for using STI in this simple case.
You'd be better served by a plain and standard habtm

     Company
         has_and_belongs_to_many :services

     Service
         has_and_belongs_to_many :companies


That would offer you simple access and manipulations :

     ikea = Company.find_by_name "ikea"
     is = ikea.services

     fs = Service.find_by_description "furnitures selling"
     companies_selling_furnitures = fs.companies


Alain
Anthony G. (Guest)
on 2006-03-05 14:21
>      Company
>          has_and_belongs_to_many :services
>
>      Service
>          has_and_belongs_to_many :companies

This is what I started with.

> That would offer you simple access and manipulations :
>
>      ikea = Company.find_by_name "ikea"
>      is = ikea.services
>
>      fs = Service.find_by_description "furnitures selling"
>      companies_selling_furnitures = fs.companies

How to I access
  company_selling_furniture.details

If I simply use an :id to have a url like

/companies/show/3

Then someone could just alter the url to

/company/show/4

which might not be a company selling furniture

But I also have access the additional properties of each service

    company_selling_furniture.tables_for_sale

I'm trying to grasp how all the best practice concepts interlock

I'd assumed I should be generating models like

SellingFurnitureCompany < Company

MakingFurnitureCompany < Company

DeliveryCompany < Company

Is this not the right approach ? Its just in the Pickaxe book they give
the example of

JukeBoxSong < Song
KarokeSong < Song

I assumed I should adopt a similar methodology.

_tony
joey__ (Guest)
on 2006-03-05 15:03
Anthony G. wrote:

> If I simply use an :id to have a url like
>
> /companies/show/3
>
> Then someone could just alter the url to
>
> /company/show/4
>
> which might not be a company selling furniture
>
> But I also have access the additional properties of each service
>
>     company_selling_furniture.tables_for_sale
>
> I'm trying to grasp how all the best practice concepts interlock
>
> I'd assumed I should be generating models like
>
> SellingFurnitureCompany < Company
>
> MakingFurnitureCompany < Company
>
> DeliveryCompany < Company
>
> Is this not the right approach ? Its just in the Pickaxe book they give
> the example of
>
> JukeBoxSong < Song
> KarokeSong < Song
>
> I assumed I should adopt a similar methodology.
>
> _tony
This sounds like the right way to it, but what do you mean about the
id's. Can you explain further?

joey__
http://www.feedreed.com
Anthony G. (Guest)
on 2006-03-05 15:23
> This sounds like the right way to it, but what do you mean about the
> id's. Can you explain further?

Its the way Rails does its routing by default..
:controller/:action/:id

In the list view its

/servicetype/list

in the show view its

/company/show/1

Now /servicetype/list will generate a list of links that point to the
show controller passing also an :id value

the value :id that Rails generates points to the primary key of the
record in the companies table

so we have

<a href=/company/show/2">FirstCompanyWithThisServiceType</a>
<a href=/company/show/5">SecondCompanyWithThisServiceType</a>

clicking on the first link goes to a url
/company/show/2
that invokes the :controller => company, the :action => show and :id =>
2

if edit the url to /company/show/3 they'll see the details of a company
they shouldn't.

_tony
Pat M. (Guest)
on 2006-03-05 15:52
(Received via mailing list)
On 3/5/06, Anthony G. <removed_email_address@domain.invalid> wrote:
>
> so we have
> they shouldn't.
> http://lists.rubyonrails.org/mailman/listinfo/rails
>

If you want to restrict users from viewing certain objects, you can
build in an authentication system.  Rails Recipes has a nice chapter
on it.  This would require you to do something like
class User < ActiveRecord::Base
  has_one :company
end

class Company < ActiveRecord::Base
  belongs_to :user
end

Then in your list controller you do

def list
  @services = session[:user].company.services
end

Since you're accessing it all through the model, it's protected (you
still have to write the auth code of course, but that's simple).

I highly recommend picking up Rails Recipes, it has a lot of stuff
you'll use.

Pat
Anthony G. (Guest)
on 2006-03-05 18:57
> If you want to restrict users from viewing certain objects, you can
> build in an authentication system.

You've misunderstodd the issue.
I'm trying to understand why how child classes and inheritance interact
in the rails framework.

_tony
Pat M. (Guest)
on 2006-03-05 19:03
(Received via mailing list)
On 3/5/06, Anthony G. <removed_email_address@domain.invalid> wrote:
>
> > If you want to restrict users from viewing certain objects, you can
> > build in an authentication system.
>
> You've misunderstodd the issue.
> I'm trying to understand why how child classes and inheritance interact
> in the rails framework.

"if edit the url to /company/show/3 they'll see the details of a
company they shouldn't."

I was responding to that.  If I misinterpretted it, please explain it
better.  The only way I can interpret that is "Users should not be
able to see the details of arbitrary companies."

Pat
Anthony G. (Guest)
on 2006-03-05 20:36
> I was responding to that.  If I misinterpretted it, please explain it
> better.  The only way I can interpret that is "Users should not be
> able to see the details of arbitrary companies."

Keep in mind the thread is about inheritance and how it works with ORM.

The parent class maps to a table, an instance of that class mapping to a
record in that table. The default list and show actions use :id to pick
out a record in the table by its primary key.

Now a child class maps to the same table as their parent but the
instance only maps to records based on particular criteria. It this
situation using the combination of the show action and :id needs to be
restricted from showing records not belonging to that child.

To try and keep the thread on track the things I asked originally asked
were:

1/ Should I be overloading the find method in the ServiceType models.

2/ a/ Should I be trying to inherit the View for Company for ServiceType
   b/ by invoking Ruby's super keyword somehow.

3/ Would it be better to have individual db table representing each
ServiceType
 will the extra properiies that each ServiceType has in addition to the
inherited Company properities require this

_tony
This topic is locked and can not be replied to.