denote rails model if not stored in database - ruby-on-rails

Is there a specific naming convention for a model that will not be stored in the database? For example, i have a schedule which will be a model, but will not be in the database because it is just a data structure. In other words it will not extend ActiveRecord::Base?

I view this as an internal implementation detail; I wouldn't reflect it in the name, because other models that are interacting with a given model should not know or care whether it is persisted. And your requirements could change later and it would become persisted.

If you want to create a class in the Model that doesn't persist to the database than just don't inherit ActiveRecord::Base
e.g
class SomeClass
end
The class definition is still saved to the file some_class.rb in the model directory
As for naming convention. Well a Model class is a Model class, it doesn't matter if it persists to the database, or some place else, or not at all. I see no need for any special naming convention.
Your Controller and Views should just interact with the your Model objects without being concerned about that object's underlying persistence mechanism. That's one of the main advantages of Model-View-Controller ... The Controller and View need not be concerned with the inner working on the Model objects. So neither should your naming convention.

I tend to make non-active record models to inherit from the NonActiveRecordModel class (or something like that, which you can define yourself). The abstract NonActiveRecordModel class can have common behavior that is used by all of your non-active record models, such as validations via validatable gem, etc.

Related

Why does Rails use the base class name, and not the subclass name, with polymorphic associations and STI?

Say I have Single Table Inheritance with BuyerInvoice inheriting from Invoice.
If I assign such an invoice to a polymorphic association, Rails will store e.g. record_type: "Invoice" rather than record_type: "BuyerInvoice". It stores record.class.base_class.name.
What are some reasons they may have done this? I'm implementing something vaguely similar and would like to understand why Rails might have made that decision.
Best I can think of is that it makes it a bit easier to rename subclasses without affecting associations, though doing it the other way would make it easier to rename abstract superclasses…
STI is an implementation detail of a model, it should not leak into its relations.
Other than renaming subclasses:
STI can be implemented with custom class resolution (with type column not being a class name at all), even have some weird cases where class changes dynamically based on attributes etc.
STI can be added to a model after it already has relations
STI can be removed at all

Does a controller extend from a model in Rails?

Been working on Rails for a bit I can't get my head wrapped around how there is almost nothing written in a model.rb file when just creating a basic CRUD application.
I was looking at a controller.rb file and was wondering why the controller file has access to model methods like all and create when there seems to be no connection between the two files.
Should't the model object methods like modelname.all and modelname.create etc. be written in the model file instead of the controller file?
TL;DR
No, it doesn't.
General Answer
A controller does not have access to model methods as you think, in the controller you never just write all or create, you write something like User.all or #user.create. You are calling the methods on the model class or instance. You are simply using the model in the controller, but this is not limited to the controller, you could do exactly the same thing in the views if you really wanted to, or you could create custom service objects, or policy objects, or repository objects, and you could still call User.all etc from inside them too.
For a very basic application you are correct you can get by writing very little or no logic, but this is only because Rails provides us with methods and does it all for us (hooray!).
Nothing in a model file just means nothing specific to this particular model... inheriting from ApplicationRecord or ActiveRecord::Base means you have built in all the class methods (all, where, find, find_by, etc) and all the instance methods (new, create, update_attributes, etc) pre-defined for the model.
The controller determines what needs to happen, the model has the methods to make it happen, so
def index
#model = Model.all
end
Means that at the point of displaying a list of all model records, you access the model's class method all

Where to place business-logic classes

For example, I have a class which collect data from web-sites and return object collections. This data doesn't store in the database so it is not model. This class is used by many controllers so it is not controller.
Where can I place such files?
Should go into lib folder! As Modules perhaps!
I would put them in app/models. Then you don't have to deal with the autoload path or with require vs. require_dependency.
Just because a class isn't persisted to your database doesn't mean it isn't part of your data model. Putting them in lib suggests they're some sort of utility class that doesn't have much to do with your app.
Rails confuses model and persistence. I think it's fine to have some of your business logic along with your persistent entities, but there's no reason why you can't have model logic outside of your ActiveRecord objects.
I usually place those classes in the lib directory. and than just require them.
Its a value object and should remain same for whole site, and your controller or other components should use its refernce from model, class refernce should be in model and class it self can be put with value object

Is it possible to put all data access related methods in a separate class?

I like having separate classes, one class represents the entity, and that a separate DAO (database access object).
Is this possible with rails and active record?
Most of what you would put into a DAO is already hidden inside of ActiveRecord anyway, so there's not much of a need to split these up. But, if you insist you can split out whatever methods you want into a separate Module and then include it in your model.

Polymorphic models hackery

Even though I know that, at least to my knowledge, this is not the default way of doing associations with ActiveRecord I'm looking for help in order to implement an "hibernatish" Polymorphic model.
For instance, consider the following base model:
# Content only has one property named path
class Content < ActiveRecord::Base
self.abstract_class = true
end
And the concrete content:
# Audio only has one property on it's own (duration).
# However, it should also inherit Content's property (path)
class Audio < Content
end
Now, something relatively interesting happens when using ActiveRecord, more accurately Rails 3 beta 3 ActiveRecord. If you set the abstract_class to false on the Content model and you execute the following:
Audio.create!(:path => '/dev/null')
It kinda works from an Hibernate perspective. That is, a Content record is created with ID 1 and an Audio record is also created with the ID = 1.
However, the problem #1 is that in order for this to work, you obviously need to turnoff the abstract_class, which kinda breaks the whole point of this abstract content example.
Furthermore, the problem #2 is that if you turn on the abstract_class you lose the content's properties when creating instances of Audio. And, if you turn it off, you lose the Audio properties when creating an instance of Audio.
Ideally, when faced with an abstract class that is then subclassed, ActiveRecord would provide the abstract + concrete properties to the concrete class being instantiated, in this case Audio. Effectively, that way, when creating an instance of Audio we would have:
audio = Audio.new #=> <Audio id: nil, duration: nil, path: nil, created_at: nil, updated_at: nil>
And then [naturally] when you assign audio.path = '/dev/null' and performed a save operation, ActiveRecord would know that the path attribute has been inherited, thus needs to be persisted at the parent class level. Furthermore, on that same save operation, should you set a non inherited property of audio ActiveRecord would also persist those changes in the audios table.
My question, after this introduction, is how one could go around active record and enhance it that way?
Effectively, let's assume that we're developing a gem that aims to provide active record with this kind of functionality. How would you go about and do it?
PS: I'm actually considering to develop such gem, though such hackery shouldn't go by without prior thinking. So, your feedback is most welcomed.
Best regards,
DBA
I see what you're going for here, but unfortunately I don't think you can get this to work out of the box the way you'd like.
Basically ActiveRecord uses model inheritance for two things:
Abstract classes, from which subclasses can inherit code and behavior but NOT table structure. You could implement a #path attribute on Content using attr_accessor and it would be inherited by subclasses, but it would not be persisted to the database unless the table for your model subclass had a 'path' column.
Single table inheritance, where subclasses inherit both behavior and table persistence.
You can mix the two, but there is no scenario where an ActiveRecord model can inherit a persistable column from an abstract class. There's always a 1:1 mapping between persisted attributes and table columns.

Resources