Get Table Name from Activerecord

Get table name from ActiveRecord

Have you tried table_name? Docs.

How does Rails guess the table name from model?

To fix your issue, just add: self.table_name = "funnel_datas" below your model definition.


Behind the scenes ActiveRecord uses the method #tableize. From the guides:

The method tableize is #underscore followed by #pluralize.

As a rule of thumb, tableize returns the table name that corresponds to a given model for simple cases. The actual implementation in Active Record is not straight tableize indeed, because it also demodulizes the class name and checks a few options that may affect the returned string.

Pluralize, by default uses common english inflections to get the plural form of the word, but "data" is plural. So:

> "FunnelData".underscore #=> "funnel_data"
> "funnel_data".pluralize #=> "funnel_data"

So your model looks for the "funnel_data" table by default.

How to determine table name within a Rails 3 model class

But I need that information in the
model's instance method. How to get
it?

You can simply do this in your instance method:

class Model
def instance_method
puts Model.table_name
end
end

How to list of all the tables defined for the database when using active record?

Call ActiveRecord::ConnectionAdapters::SchemaStatements#tables. This method is undocumented in the MySQL adapter, but is documented in the PostgreSQL adapter. SQLite/SQLite3 also has the method implemented, but undocumented.

>> ActiveRecord::Base.connection.tables
=> ["accounts", "assets", ...]

See activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb:21, as well as the implementations here:

  • activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:412
  • activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:615
  • activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:176

Changing table name at query run time in a Rails application

The method

def self.for_tenant(tid)
self.table_name = "products_" + tid.to_s
self
end

makes sense, however, it has a side effect: it changes table name for Product class. When this class is used later in the same request, for example, in this way:

Product.where(name: "My other product") ...

the table name won't be products as you may expect; it will stay the same as changed by for_tenant method previously.

To avoid this ambiguity and keep code clean you can use another strategy:

1) Define a module which holds all logic of work with tenant partitions:

# app/models/concerns/partitionable.rb

module Partitionable
def self.included(base)
base.class_eval do
def self.tenant_model(tid)
partition_suffix = "_#{tid}"

table = "#{table_name}#{partition_suffix}"

exists = connection.select_one("SELECT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'public' AND tablename = '#{table}')")
unless exists['exists'] == 't' || exists['exists'] == true # different versions of pg gem give different answers
return self # returning original model class
end

class_name = "#{name}#{partition_suffix}"

model_class = Class.new(self)

model_class.define_singleton_method(:table_name) do
table
end

model_class.define_singleton_method(:name) do
class_name
end

model_class
end
end
end
end

2) Include this module in your model class:

class Product < PostgresDatabase
include Partitionable

...
end

3) Use it the same way as you intended:

Product.tenant_model(TENANT_ID).where(name: "My product")...

What's happened there:

Method tenant_model(TENANT_ID) creates another model class for the tenant with ID TENANT_ID. This class has name Product_<TENANT_ID>, works with table products_<TENANT_ID> and inherits all methods of Product class. So it could be used like a regular model. And class Product itself remains untouched: its table_name is still products.

Active Record .includes and where query requires table name in where clause?

The code within the where() scope is closer to sql than to activerecord. You could also write it directly as sql:

where("course_plans.code = 'ENG'")  

The course_plans: key on the hash in the where scope is taken as the name of the table, not the name of the belongs_to association; hence the PG error - there is no table named 'course_plan'.



Related Topics



Leave a reply



Submit