Multiple Table Class Inheritence for ruby on rails - ruby-on-rails-3

I need to set up a multiple class inheritance model here for the following models. Basically I'm building an extensible contacts directory. From a base class Contact I intend to derive other classes i.e something on the lines of :
class Contact
# the super class
attr_accessible :name, :about
end
class Person < Contact
attr_accessible :first_name, last_name, :description, :works_for_company_id
end
class Company < Contact
attr_accessible :company_name, :location, :services
end
Each model corresponds to a different table - I'm assuming that there would be a has_one belongs_to relation ship between teh parent and the child classes however I was wondering if theres a gem that can ease it a bit. Or if I have to do it myself how would I actually accomplish it.
For example contact.name is actually person.first_name+' '+person.last_name for a person or company.company_name for the company. How do I structure my database and associations to get this right?

Related

How to manually join two different table with different attribute name in Ruby on Rails controller

I am currently making a website that runs on Ruby on Rails. I am facing some issues while I was trying to join two tables, Rates and Locations, that I have with two different attributes name.
Rates: id rater_id rateable_id (and a few more attributes in this table)
Locations: id title body user_id (and a few more attributes in this table)
Here is the query that I am trying to do in SQL.
SELECT *
FROM rates, locations
WHERE rates.rater_id = locations.user_id AND rates.rateable_id = locations.id
I have read the official active record documents that provided by rubyonrails.org. I have tried doing these, but it does not work. Here is the code that I am trying to implant in app\controllers\users_controller.rb
#join_rating = Rate.joins(:locations).where("rates.rateable_id = locations.id AND rates.rater_id = locations.id")
#all_rating = #all_rating.where(rater_id: #user)
#count_all_rating = #all_rating.count
#join_rating, is trying to join the attributes with different names.
#all_rating, is trying to filter which location to show using the user ID
#join_rating, is trying to calculate the total numbers of locations that are rated by the user
Assume that everything is setup correctly and the only error is in the query that I am trying to do, how should I rewrite the statement so that I am able to show the locations that the user has rated using #all_rating.
Thank you!
A few points:
When in ActiveRecord you're starting a statement with the Rate class, it means the result is going to be a collection of Rate objects. So if you're trying to show locations, you should start with a Location class.
#locations_user_rated = Location.joins('INNER JOIN rates ON
rates.rateable_id = locations.id').where('rates.rater_id' => #user)
And if your ActiveRecord associations are well defined, you could simply do:
#locations_user_rated = Location.joins(:rates).where('rates.rater_id' => #user)
"Well defined" simply means you'll need to do something like the following. Note that I am not sure I understand your model relationships correctly. I assume below that every location has multiple rates, and that the reason your Rate model has the field called rateable_id instead of a location_id is because you want :rateable to be polymorphic. This means you probably also have a rateable_type field in rates table.
class Location < ActiveRecord::Base
has_many :rates, as: :rateable
end
class Rate < ActiveRecord::Base
belongs_to :rateable, polymorphic: true
end
If this polymorphism is not the case, things should actually be simpler, and I highly recommend that you follow Rails's conventions and simply name the relationship field location_id on your Rate model instead of rateable_id. Then you can do:
class Location < ActiveRecord::Base
has_many :rates
end
class Rate < ActiveRecord::Base
belongs_to :location
end
If still you are not convinced about the field name, you can customize things and do:
class Location < ActiveRecord::Base
has_many :rates, foreign_key: :rateable_id
end
class Rate < ActiveRecord::Base
belongs_to :location, foreign_key: :rateable_id
end
You can find more about how to customize associations here, and here.
I highly recommend taking advantage of ActiveRecord's has_many, belongs_to, and has_many through: functionality.
If you set up a model for each of these tables, with the correct relationships:
class User < ActiveRecord::Base
has_many :ratings, foreign_key: :rater_id
has_many :rated_locations, through: ratings, class_name: Location.name, source: :rater
end
class Rating < ActiveRecord::Base
belongs_to :rater, class_name: User.name
belongs_to :location
end
class Location < ActiveRecord::Base
has_many :ratings
end
Then to access the locaitons that a user has rated, you just call
user.rated_locations

Handling relationship with ActiveRecord

I have two models to make a relationship between them, where I need to access stores of a radar and the radars of a store. A radar could monitoring zero or many stores. A store could belong to zero, one or many radars.
I would like to have something like this:
store = Store.first
store.radars #all radars of the store location
And the opposite too:
radar = Radar.first
radar.stores #all stores of the radar location
My classes:
class Store < ActiveRecord::Base
attr_accessible :title, :description, :user, :store_group, :city,
:neighborhood, :sublocality, :post_code, :route,
:street_number, :latitude, :longitude
end
class Radar < ActiveRecord::Base
attr_accessible :name, :radius, :latitude, :longitude, :user
end
How can I create a migration to handle this?
What you are looking for is a has_and_belongs_to_many association between radars and stores. The question you need to ask your self is will there ever be any attributes on the the joining between the two models? If so you might considering using an explicit join model, that will hold those attributes. In that case you would be looking at a has_many :through association.
see http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association for information on the HABTM association.
your migration for a HABTM would be something like this.
class CreateRadarStores < ActiveRecord::Migration
create_table :radars_stores, :id => false do |t|
t.belongs_to :radar
t.belongs_to :store
end
end
The order of the table name is important, since by default rails creates it in alphabetical order of the models.
Your models would need to be updated to include the HABTM
class Store < ActiveRecord::Base
has_and_belongs_to_many :radars
....
end
class Radar < ActiveRecord::Base
has_and_belongs_to_many :stores
....
end
or if using a has many :through look here http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
Building that join model would be up to you depending upon attributes reuqired.

Using relations for models with namespace in Rails

How do I write relations for models with namespace?
if I have Class Foo::Bar and Class Employee and I want to have habtm between them would I write
Class Foo::Bar
has_and_belongs_to_many :employees
end
and in
Class Employee
has_and_belongs_to_many ???? # <- how do I write this part?
end
You could do something like:
class Employee
has_and_belongs_to_many :foo_bars, :class_name => "Foo::Bar"
end
And then you should be able to access all the Foo::Bar objects on an Employee instance with employee.foo_bars

Polymorphic has_one association and multiple inheritance with Rails 3

I've seen some posts dealing with this, and am trying to determine the best solution.
Semantically, I want a Client model with a one-to-one relationship with a Survey. There are different kinds of surveys that have different fields but I want to share a significant amount of code between them. Because of the different fields I want different database tables for the surveys. There is no need to search across different types of surveys. It feels like I want the foreign key in the Client table for fast retrieval and potential eager-loading of the Survey.
So theoretically I think I want polymorphic has_one and multiple inheritance something like this:
class Client < ActiveRecord::Base
has_one :survey, :polymorphic => true
end
class Survey
# base class of shared code, does not correspond to a db table
def utility_method
end
end
class Type1Survey < ActiveRecord::Base, Survey
belongs_to :client, :as => :survey
end
class Type2Survey < ActiveRecord::Base, Survey
belongs_to :client, :as => :survey
end
# create new entry in type1_surveys table, set survey_id in client table
#client.survey = Type1Survey.create()
#client.survey.nil? # did client fill out a survey?
#client.survey.utility_method # access method of base class Survey
#client.survey.type1field # access a field unique to Type1Survey
#client2.survey = Type2Survey.create()
#client2.survey.type2field # access a field unique to Type2Survey
#client2.survey.utility_method
Now, I know Ruby does not support multiple inheritance, nor does :has_one support :polymorphic. So is there a clean Ruby way to achieve what I'm getting at? I feel like it's right there almost...
Here's how I would do this:
class Client < ActiveRecord::Base
belongs_to :survey, :polymorphic => true
end
module Survey
def self.included(base)
base.has_one :client, :as => :survey
end
def utility_method
self.do_some_stuff
end
end
Type1Survey < ActiveRecord::Base
include Survey
def method_only_applicable_to_this_type
# do stuff
end
end
Type2Survey < ActiveRecord::Base
include Survey
end

Struggling with rails_admin multiple HABTM associations to same model

I'm looked all over Google, the Rails_Admin dox, etc and can't find an answer.
I have a model agency:
class Agency < ActiveRecord::Base
has_and_belongs_to_many :kids
And the kids model:
class Kid < ActiveRecord::Base
has_and_belongs_to_many :agencies
attr_accessible :agency_ids
In Rails_Admin, I access the agencies with this code:
config.model Kid do
edit do
field :agencies
end
end
However, for the life of me, I can't figure out how to have an association to the same model in a different field. Something like:
config.model Kid do
edit do
field :agencies
field :agencies_previous
end
end
where agencies_previous and agencies would reference the same agencies model.
I think that what you need is something like https://github.com/benedikt/mongoid-tree where you can reference a self model, its that what you need?