Inherit active_record in rails - ruby-on-rails

Right now my classes are look like this.
class BalanceName < ActiveRecord
def before_validation
set_blank_attributes_to_nil(#attributes)
end
end
class Balance < ActiveRecord
def before_validation
set_blank_attributes_to_nil(#attributes)
end
end
I want to inherite activer record into one class and than want to inherite that class into other classes like.
I want something like this.
class CommonActiveRecord < ActiveRecord::Base
def before_validation
set_blank_attributes_to_nil(#attributes)
end
end
class BalanceName < CommonActiveRecord
def before_validation
super
end
end
class Balance < CommonActiveRecord
def before_validation
super
end
end

You can do exactly as you have done except you do not need to redefine the before_validation methods in your subclasses (though I guess these may be here prior to being filled with more specific validation).
You will also need to indicate to rails that your CommonActiveRecord class is abstract and therefore is not persisted by adding:
class CommonActiveRecord < ActiveRecord::Base
self.abstract_class = true
end

You can create module (e.g. lib/common_active_record.rb):
module CommonActiveRecord
def before_validation
set_blank_attributes_to_nil(#attributes)
end
end
And then in your model simply include it:
class BalanceName < ActiveRecord::Base
include CommonActiveRecord
end
class Balance < ActiveRecord::Base
include CommonActiveRecord
end

Related

How to include multiple model in rails lib

In my /lib i have this class below:
module Application
class Post < ActiveRecord::Base
attr_accessor :id
def artilce_content
post.articles.content
end
private
def post
Post.find(id)
end
end
end
But the problem is article is undefined.
NoMethodError: undefined method ziptag_type' for #<Application::Api::V2::Ziptag:0x00000008edc120>
The question is, how can I use or include multiple models in /lib? I tried adding class User < ActiveRecord::Base; end above module
class Article < ActiveRecord::Base; end
module Application
class Post < ActiveRecord::Base; end
:
:
:
end
end
but is doesn't worked.
The best way here is to use require.
require 'your_model'
In your case, it should be:
require 'article'
module Application
class Post < ActiveRecord::Base
attr_accessor :id
def artilce_content
post.articles.content
end
private
def post
Post.find(id)
end
end
end
I've got the answer. It should be:
class Article < ActiveRecord::Base; attr_accessor :column1, :other_column end
Not:
class Article < ActiveRecord::Base; end
Now, it's working fine on me.

How do I add global Rails helpers like has_many and devise_for?

In Rails, I'd like to apply functionality to many models at the same time, having the ability to add it to other models in the future.
I'm looking for something like...
class Stuff < ActiveRecord::Base
some_tag
end
class Thing < ActiveRecord::Base
some_tag
end
to give those and any other models with
some_tag
the functionality of
class Functionality
has_many :other_things, polymorphic: true
def does_something
end
end
First step: Create a module with the method you want to add to your classes:
module FooFunction
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def does_something(options = {})
...
end
end
end
Next step: Include that module into the class
# in config/initializers/foo_function.rb
class Object
include FooFunction
end

How to access a specified table in database through a custom model class, Ruby on Rails?

I have this custom model, with some methods in it:
class GenericModel < ActiveRecord::Base
self.abstract_class = true
def get_settings
.....
end
end
I want to inherit this GenericModel class in my various other Models like below, so that I can have access to those custom methods:
class ProvinceSetting < GenericModel
end
class CitySetting < GenericModel
end
But, how do I write my custom method so that it acts on a specific table in the database depending upon which Model class is calling it ? Any pointers would be welcome
Is this the correct implementation of get_settings in GenericModel, where self would refer to appropriate model name ?
def self.get_settings(user_id)
user_session = SettingsSession.find_by_user_id(user_id)
if !user_session.blank?
if setting_orig = self.find_by_settings_session_id(user_session.id)
setting = setting_orig.dup
end
else
setting = self.first.dup
end
return setting
end
If you want to call the table name used by the subclass, then you're done - it will do that already:
class GenericModel < ActiveRecord::Base
def get_settings
all # this will get all settings for the subclass that calls it
end
end
If you need to use some other table name, make a method in each subclass that defines the tablename, and call that method in the abstract base model:
class ProvinceSetting < GenericModel
def special_table_name
'foo'
end
end
class CitySetting < GenericModel
def special_table_name
'bar'
end
end
class GenericModel < ActiveRecord::Base
def get_settings
... # use 'special_table_name' method in a query
end
end

Rails ActiveRecord - inheriting from a base class with no table

What i'm looking to do is have a base class for some of my models that has some default activerecord behavior:
class Option < ActiveRecord::Base
has_many :products
def some_method
#stuff
end
#etc..etc..
end
class ColorOption < Option
#stuff...
end
class FabricOption < Option
#stuff...
end
However, I want ColorOption and FabricOption to each be in their own tables. I do NOT want to use STI or have a table for the base class "Option". The only way I've gotten this to work is with some non-inheritance metaprogramming magic. But I wondered if there was a way to tell AR that the base class does not need a table. Its just there for extra behavior, and to put the other subclasses in their own table as usual.
Thanks,
Craig
What you want is an abstract class:
class Option < ActiveRecord::Base
self.abstract_class = true
end
class ColorOption < Option
...
end
class FabricOption < Option
...
end
Looks like a case for a module that you include.
module Option
def self.included(base)
base.has_many :products
end
# other instance methods
end
class ColorOption < ActiveRecord::Base
include Option
set_table_name '???' # unless ColorOption / FabricOption have same table -> move to Option module
#stuff...
end
class FabricOption < Option
include Option
set_table_name '???' # unless ColorOption / FabricOption have same table -> move to Option module
#stuff...
end
More info: http://mediumexposure.com/multiple-table-inheritance-active-record/
I had similar problem, but I wanted also to change the way AR was setting table_name for my models, that for example MyProject model would have table name "MY_PROJECT".
I've achieved it by creating abstract AR class, as #FFrançois said, and with inherited method, where I'm changing table name, like this:
class MyModel < ActiveRecord::Base
self.abstract_class = true
def self.inherited(subclass)
subclass.table_name = subclass.name.underscore.upcase
end
end
class MyProject < MyModel
end
Now MyProject.table_name gives MY_PROJECT :)

adding class methods to ActiveRecord::Base

I have created an instance method which is also a callback (if that makes sense) which does some stuff thats irrelevant. I would love to be able to just call:
class Model < ActiveRecord::Base
fix_camelcase_columns
end
Instead at the moment I have this:
def after_find
self.class.columns.each do |column|
self.instance_eval("def #{column.name.to_underscore}; self.#{column.name}; end;")
end
end
I would love to abstract this and use it on other classes. Any pointers?
Well, you can open up ActiveRecord::Base and throw a method there:
class ActiveRecord::Base
def self.fix_camelcase_columns
define_method :after_find do
...
end
end
end
For a cleaner way, create a module:
module CamelcaseFixer
def self.included(base)
base.extend(self)
end
def fix_camelcase_columns
define_method :after_find do
...
end
end
end
and then in your model do
class Model < ActiveRecord::Base
include CamelcaseFixer
fix_camelcase_columns
end
Didn't test the code, see if it works.

Resources