3

We have a Real-Estate app in which the User can be a Renter or Landlord(Owner). Renters can search for specific houses listed by the Owners. Renters can also add other persons(friends or acquaintances who are staying with that specific renter). In the app we treat them as Coapplicants.

Models

# user.rb
class User < ActiveRecord::Base
  has_one :renter
  has_one :owner
end

# renter.rb
class Renter < ActiveRecord::Base
  belongs_to :user
  has_many :coapplicants
end

# coapplicant.rb
class Coapplicant < ActiveRecord::Base
  belongs_to :renter
end

Now as to increase the number of users for the app,we implemented a mailing system which sends an Welcome Mail(when the Renter adds a Coapplicant) to signup as a User.And that Coapplicant can choose to be Renter and can add many Coapplicants too. And the process goes on again resulting in increasing the users.

It's like a tree structure and now I want to set-up a perfect database relations(associations) to track the users flowing in and through which renter/coapplicant they are coming.

Now the Current Model structure(not yet developed) looks like this

# user.rb
class User < ActiveRecord::Base
  has_one :renter
  has_one :owner
end

# renter.rb
class Renter < ActiveRecord::Base
  belongs_to :user
  has_many :coapplicants
  has_many :coapp_renters,
           :through => :coapplicants
  has_many :inverse_coapplicants,
           :class_name => "Coapplicant",
           :foreign_key => "coapp_renter_id"
  has_many :inverse_coapp_renters,
           :through => :inverse_coapplicants,
           :source => :renter
end

# coapplicant.rb
class Coapplicant < ActiveRecord::Base
  belongs_to :renter
  belongs_to :coapp_renter,
             :class_name => "Renter"
end

I guess i messed up things a bit. Which database-relationships(associations) would be the best for my current situation.

Can someone throw some light on this please.I'm thinking about using the ancestry gem but how to implement to my current situation.

janfoeh
  • 10,243
  • 2
  • 31
  • 56
Pavan
  • 33,316
  • 7
  • 50
  • 76

3 Answers3

2

I've found that sometimes even a small change in perspective when designing your associations can make them flow a lot more naturally.

You have focused exclusively on person entities; User.find(1).renter for example isn't very intuitive, since both models depict essentially the same person.

Instead of trying to model what people are, I would try to model what they have. In this case, instead of a User having a Renter, let them have many Rentals:

class User < ActiveRecord::Base
  has_many :rentals,
            foreign_key: 'renter_id'
end

class Rental
  belongs_to :renter,
              class_name: 'User'
  belongs_to :property
end

I assume here that you have a model Property that stands for what is being rented - leave that out if it doesn't exist.

It's the same thing for owners. A User becomes an owner just by having Ownerships:

class User < ActiveRecord::Base
  has_many :ownerships,
            foreign_key: 'owner_id'
end

class Ownership
  belongs_to :owner,
              class_name: 'User'
  belongs_to :property
end

A co-application is slightly different in that it belongs to a Rental:

class CoApplication
  belongs_to :co_applicant,
              class_name: 'User'
  belongs_to :rental
end

class Rental
  has_many :co_applications
end

class User < ActiveRecord::Base
  has_many :co_applications,
            foreign_key: 'co_applicant_id'
  has_many :received_co_applications,
            through: :rentals,
            source: :co_applications
end

Now your Users can be owners, renters, co-applicants - all at the same time. And these associations allow you to capture everything that happened - who signed on whom through what is just a matter of chronological order.

From here on it's a matter of nesting your has_many :through associations to get whatever you want.

Want to know the properties a landlord owns?

has_many :owned_properties,
          through: :ownerships,
          source: :property

The rentals to her properties?

has_many :leases,
          through: :owned_properties,
          source: :rentals

The people who rented her properties?

has_many :renters,
          through: :leases,
          source: :renter

Same thing with co-applications. Want to know who co-applied with a user?

has_many :co_applicants,
          through: :received_co_applications,
          source: :co_applicant
janfoeh
  • 10,243
  • 2
  • 31
  • 56
  • I like your approach. I will use this if my current approach needs to review from the scratch. Thank you :) – Pavan Apr 06 '15 at 09:14
  • Ah, I thought you were still in the design phase. Well, in this case these changes would have been a bit too sweeping ;) – janfoeh Apr 06 '15 at 09:45
1

I would refactor your code and make the co-applicants just a renter that is a child of another renter

in your renter model you have to add a "parent_id" to know whom the co-applicants belongs to.

now in your model you can do something like

#renter.rb
class Renter < ActiveRecord::Base
  belongs_to :user
  has_many :children, :class_name => "Renter"
  belongs_to :parent, :class_name => "Renter" 
end

# Example calls 
Renter.first.children 
Renter.first.parent 

I hope this helps

MZaragoza
  • 10,108
  • 9
  • 71
  • 116
1

Create a table called Relationship (or something) with two foreign_ids concerning what you want the User and Renter to be able to do with one another (example to be able to "Follow" one another => Follower_id and Following_id). Define methods in your Models related to those ids and then call those methods in your views to display the relations.

Zippo9
  • 706
  • 2
  • 5
  • 24