inserting superclass in rails, without corresponding database table - ruby-on-rails

I'd like to have a common superclass for two models in ruby, to share several methods. Let's say I want a Truck and Car inheriting from Vehicle. Here are some options:
Make class Vehicle < ActiveRecord::Base, and have class Truck < Vehicle etc. But then I get errors saying I don't have a table for Vehicle (and I don't want one, either).
Use module Vehicle and include Vehicle in class Truck < ActiveRecord::Base. But then attr_reader and friends don't get applied to Truck.
Thus, I want class Vehicle. How do I do this without requiring a table? I'm sure there's a standard, nice way of doing this...

Add a class method called abstract_class? that returns true:
class Vehicle < ActiveRecord::Base
def self.abstract_class?
true
end
end

Related

How do I add a superclass to two classes in Rails?

In my Rails application I have two classes :
UserPost and GroupPost (inheriting from ApplicationRecord), that I want to make subclasses of a new class, Post.
What would be the best way to add this in?
Is it as simple as making the class manually, and adding in the inheritance or are there problems that could cause?
I'm making the assumption that UserPost and GroupPost are inherited from ActiveRecord::Base, i.e. you want to save them in your DB
If you have class UserPost and GroupPost inherit from Post in the following way, this is known as Single Table Inheritance
class Post < ApplicationRecord
end
class GroupPost < Post
end
class UserPost < Post
end
Rails will, by default, expect you to have a column called "type" (can be configured to any other name) in the Posts table. GroupPost and UserPost will populate their respective values in the same table, adding in "GroupPost" or "UserPost" to the type. You can read up on it here
Rails also provides you the ability to have the parent class be "abstract", i.e. it shouldn't be able to persist to the database. Perhaps you noticed it in the the app/models/application_record.rb file as well. This way the parent serves as just a concept where you can add in common behaviour, STI will not kick in. There will need to be separate tables for children.
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end
If you plan on having separate tables for the classes, I'd recommend trying composition instead of inheritance using mixins. Basically you write common functionality in a "module" and include it to the classes that need the separate functionality. Concerns are a nice way to append class methods, associations etc without having to rely on arcane ruby syntax. I'd recommend having a look at the documentation
module Fooable
extend ActiveSupport::Concern
included do |base|
scope :enabled, -> { where(enabled: true) }
has_many :boos, dependent: :destroy
end
class_methods do
def having_name
where('name ILIKE ?', "#{name}%")
end
end
def hi
return 'hi'
end
end
class UserPost < ApplicationRecord
include Fooable
end
UserPost.first.boos # relationship
UserPost.enabled # calling a scope
UserPost.having_name('name') # calling a class method
UserPost.new.hi #calling an instance method

Inheriting from a class with the same name from outside the namespace

I have an application where there are multiple ways to handle creating and updating an object based on the user that is logged in. I keep getting a circular reference exception on the child classes. Is this correct or would it be better to create concerns module with shared code and have them both be independent?
class WorkOrder < ActiveRecord::Base
#parent class
end
module Dispatch
class WorkOrder < ::WorkOrder
#child class
end
end
module Service
class WorkOrder < ::WorkOrder
#child class
end
end
How are you planning on differentiating records in the database between being from the parent class or one of the child classes?
You may want to look at Single Table Inheritance (STI) and Polymorphic Associations:
http://railscasts.com/episodes/394-sti-and-polymorphic-associations

Class inheritance in rails active record

I have a Product table, which has multiple fields like product price, product manufacturer and so on which is common in every item. So I have made a belongs_to relationship with productItem. Every product item has its own specifications. Now I feel the necessity to make few common methods. From the concept of OOP, I have tried to make Parent class Sub class model, where subclass will inherit all the methods of parent. So I have tried doing following:
class Product < ActiveRecord::Base
def check
...
end
end
class ProductItem < Product
belongs_to :product
end
which raises following error:
undefined method `some_field_id' for #<ProductItem:0x007f8cac666850>
So how can I do parent subclass model in rails?
Class inheritance it's not for code sharing, you should rely on mixins for such a thing. Create a module like this, you can put it in app/shared/yourmodule.rb:
module Yourmodule
def dosomething
end
end
class Product
include Yourmodule
end
class ProductItem
include Yourmodule
end
Product.new.dosomething
ProductItem.new.dosomething
You can share attributes through STI though, but STI is recommended only if you share all parent attributes plus a few additional fields, be careful with it.
STI is simple: add (if you don't have it already) a type column to the table you want to inherit from, make it a string and don't set any default and leave it nullable. Now you can just do:
class Product < ActiveRecord::Base
end
class ProductItem < Product
end
You'll be able to access anything from Product

What is the best way to configure inheritance in this scenario?

So here is the scenario. Lets say that you have 10 different suppliers that provide products that you sell. Now for this scenario assume that each supplier has their own methods for order processing and each require their own class. This is a big assumption, but I am trying to simplify my real scenario without all of the details.
Solution with Single Table Inheritance (STI)
class Supplier < ActiveRecord::Base
has_many :products
# Methods that can be inherited by each supplier go here
end
class MySupplier1 < Supplier
# Custom per-supplier methods go here
end
class MySupplier2 < Supplier
# Custom per-supplier methods go here
end
What is strange about this solution is that you will have 10 rows in your suppliers table. For example, you will never have more than one instance of MySupplier1.
Here is another solution:
Alternative Modular Solution
class Supplier < ActiveRecord::Base
has_many :products
end
class Suppliers::Base
# Methods that can be inherited by each supplier go here
end
class Suppliers::MySupplier1 < Suppliers::Base
# Custom per-supplier methods go here
end
class Suppliers::MySupplier2 < Suppliers::Base
# Custom per-supplier methods go here
end
With this solution, I like that it feels more modular, but the relationship between the ActiveRecord Supplier and the Suppliers::MySupplier1 is really awkward. Basically, I have to store the supplier class in the suppliers table so I know what class to instantiate for processing.
Does anyone think there is a right or wrong or maybe even a better approach?

How can I create activerecord models that are subsets of a certain model?

I've seen this before but can't figure out what the correct term is. Basically, I'd like to create models for a specific subset of table data. E.g. (these are not the real classes)
class Person < ActiveRecord::Base
class Man < Person
<something here> :gender => 'male'
If you are trying to create a single table inheritance, than I am fairly certain that this is the correct syntax. Just don't forget to define the type field in the table.
class Person < ActiveRecord::Base
end
class Man < Person
end
Edit: Removed the

Resources