ActiveRecord ignores table_name_prefix - ruby

I've got situation where I need to define table_name and table_name_prefix within a model and for some reason table_name overrides table_name_prefix.
class ScheduleItem < ActiveRecord::Base
self.table_name = "schedule_item"
self.table_name_prefix = 'ACQ_IBM_T.'
end
The prefix is completely ignored in the queries. But, when I comment out the table_name part then the prefix is added. Anyone has seen strange behavior like this before?

In ActiveRecord::ModelSchema::ClassMethods, the table_name setter puts the value in #table_name:
def table_name=(value)
...
#table_name = value
And the table_name getter just uses the #table_name value if it is defined:
def table_name
reset_table_name unless defined?(#table_name)
#table_name
end
The table_name_prefix is only used to help Rails when it is trying to guess the table name based on the class name (in reset_table_name).
If you have a table name that Rails can't guess, you can do this:
class ScheduleItem < ActiveRecord::Base
self.table_name = "ACQ_IBM_T.schedule_item"
Or if you need to use the prefix somewhere else, you can do this:
class ScheduleItem < ActiveRecord::Base
self.table_name_prefix = 'ACQ_IBM_T.'
self.table_name = "#{table_name_prefix}schedule_item"

Related

Ruby on Rails inheritance? [duplicate]

How to implement inheritance with active records?
For example, I want a class Animal, class Dog, and class Cat.
How would the model and the database table mapping be?
Rails supports Single Table Inheritance.
From the AR docs:
Active Record allows inheritance by
storing the name of the class in a
column that by default is named "type"
(can be changed by overwriting
Base.inheritance_column). This means
that an inheritance looking like this:
class Company < ActiveRecord::Base; end
class Firm < Company; end
class Client < Company; end
class PriorityClient < Client; end
When you do Firm.create(:name =>
"37signals"), this record will be
saved in the companies table with type
= "Firm". You can then fetch this row again using Company.find(:first, "name
= ‘37signals’") and it will return a Firm object.
If you don‘t have a type column
defined in your table, single-table
inheritance won‘t be triggered. In
that case, it‘ll work just like normal
subclasses with no special magic for
differentiating between them or
reloading the right type with find.
A pretty good tutorial is here: http://juixe.com/techknow/index.php/2006/06/03/rails-single-table-inheritance/
Models:
class Animal < ActiveRecord::Base; end
class Dog < Animal; end
class Cat < Animal; end
Migration:
class CreateAnimals < ActiveRecord::Migration
def self.up
create_table :animals do |t|
# Other attributes...
t.string :type
end
end
def self.down
drop_table :animals
end
end
ActiveRecord supports mapping inheritance hierarchies to a single table(Single-table inheritance. Table would have a column type which stores name of actual class and is used to select other class-specific columns.
It is possible to implement multi-table inheritance mapping, as shown here, but this particular way is not portable, AFAIK.
Delegated Types
One particular way of doing this is via Delegated Types - this makes sense only if you want to paginate all animals together, and to view cats and dogs together, then the delegated type is particularly useful. I also like it because you don't need to have empty columns, for where it doesn't make sense, as is the case with Single Table Inheritance solutions.
# Schema: entries[ id, created_at, updated_at, animalable_type, animalable_id ]
class Animal < ApplicationRecord
delegated_type :animalable, types: %w[ Cat Dog ]
end
module Animalable
extend ActiveSupport::Concern
included do
has_one :animal, as: :animalable, touch: true
end
end
# Schema: cats[ id, selfishness_level ]
class Cat < ApplicationRecord
include Animalable
end
# Schema: dogs[ id, favourite_game, wag_tail_level ]
class Dog < ApplicationRecord
include Animalable
end

how to get single latest record from a view and test it in console

I kinda have 2 questions. I have following model and method to get the latest record from view. but when i try to test in console i get error undefined method or variable vCustomerDetails why i am getting the error?
Also, how do i select only one column from view?
SELECT TOP 1 HasConditionFlag FROM vCustomerDetails
WHERE vCustomerDetails.UserID = #user_id
ORDER BY EntryDate DESC
Model
module Customer
class CustomerUsage < ActiveRecord::Base
self.table_name = 'vCustomerDetails'
def self.has_condition_flag(user_id)
vCustomerDetails
.where("vCustomerDetails.UserID = #{user_id}")
.order('vCustomerDetails.EntryDate DESC')
.last
end
end
end
this one worked
def self.has_condition_flag(user_id)
CustomerUsage
.select("vCustomerDetails.HasConditionFlag")
.where("vCustomerDetails.UserID = #{user_id}")
.order('vCustomerDetails.EntryDate DESC')
.first
Remove vCustomerDetails
module Customer
class CustomerUsage < ActiveRecord::Base
self.table_name = 'vCustomerDetails'
def self.has_condition_flag(user_id)
where("vCustomerDetails.UserID = #{user_id}")
.order('vCustomerDetails.EntryDate DESC')
.last
end
end
end
to select a limited number of columns use
.select('HasConditionFlag')

Ruby (without rails) using activerecord, insert into does not work

I need to insert a new record into an existing table in a databse. I tried both approaches below:
class UserDetail < ActiveRecord::Base
def self.add_new_user
new_user = UserDetail.new
new_user.first_name = 'Joe'
new_user.last_name = 'Smith'
new_user.user_id = 'TEST'
new_user.save
end
def self.add_new_user_2
UserDetail.create(user_id: 'TEST', first_name: 'Joe',
last_name: 'Smith')
end
However, both approaches give me the error below:
ActiveRecord::StatementInvalid: OCIError: ORA-00926:
missing VALUES keyword: INSERT INTO "USER_DETAIL" DEFAULT VALUES
What am I missing? Please share your solutions.
(Using Ruby 1.9.3, ActiveRecord 4.2.4)
ActiveRecord makes assumptions about primary keys. It is expecting to find a primary key on your UserDetail table called "ID". Should look something like.
class UserDetail < ActiveRecord::Base
self.table_name = :user_detail
self.primary_key = :user_id
def self.add_new_user
new_user = UserDetail.new
new_user.first_name = 'Joe'
new_user.last_name = 'Smith'
new_user.user_id = 1
new_user.save
end
end

ActiveRecord mapping to table name with schema name as prefix

Has anyone experienced this issue on mapping table in ActiveRecord when table name need a schema name as a prefix (oracle)?
Gemfile
gem 'activerecord', '4.2.4'
gem 'activerecord-oracle_enhanced-adapter', '1.6.7'
....
db_helper.rb
class Student < ActiveRecord::Base
self.abstract_class = true
self.table_name_prefix = 'OPT_ABC.'
self.table_name = 'STUDENT'
def self.list_student
puts Student.take(1) #testing
end
end
The actual table name looks like:
SELECT * FROM OPT_ABC.STUDENT;
I am able to connect to the database instance, but when the code gets line:
puts Student.take(1) # SELECT * FROM STUDENT LIMIT 1
I get the following error:
ActiveRecord::StatementInvalid:
table or view does not exist: SELECT "STUDENT".* FROM "STUDENT"
I am looking for solution on how to handle 'OPT_ABC." table prefix. Please share your solution.
It looks like the problem is that you're trying to use both self.table_name_prefix= and self.table_name= together when you should be using one OR the other.
First let's consider how both self.table_name_prefix= and self.table_name= work.
self.table_name_prefix=
According to the documentation, self.table_name_prefix= works by prepending the passed in value to the table name that ActiveRecord automatically generates based off of the name of the class.
So, if the class name is Student and you do self.table_name_prefix = 'OPT_ABC.', your table name will be OPT_ABC.STUDENTS. Note that the generated table name is plural (and ends in an s).
self.table_name=
According to the documentation, self.table_name= sets the table name explicitly. This means that it completely overrides the table name to the value that you pass in.
So, if you do self.table_name = 'OPT_ABC.STUDENT' your table name will be OPT_ABC.STUDENT.
So, given that, to set the table name to OPT_ABC.STUDENT, you should be able to simply pass the value into self.table_name like this:
class Student < ActiveRecord::Base
self.abstract_class = true
self.table_name = 'OPT_ABC.STUDENT'
def self.list_student
puts Student.take(1) #testing
end
end

How to remove table column in Active Record

I would like to remove column from the table by using Active record. Please find the below snippet
require "active_record"
require 'sqlite3'
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => 'test_one')
class Account < ActiveRecord::Base
table_name = "AccountBean"
primary_key = "process_id"
remove_column "xxx" // I need this type of method to remove column "xxx" from accounts table
end
Is there any class method in ActiveRecord which satisfy this requirement ?
I guess ActiveRecord presumes that changes to structure shall be done using migrations.
If you really need to, you could use the same methods rails uses in migrations to e.g. remove a column - like here
I don't recommend this :)
ActiveRecord::Base.connection.remove_column("persons", "first_name")
Within a class that would look something like:
class Account < ActiveRecord::Base
table_name = "AccountBean"
primary_key = "process_id"
connection.remove_column(table_name, "xxx")
end

Resources