Rails: can I use polymorphic references with non-integer primary keys? - ruby-on-rails

I have a database that uses UUIDs as primary keys, like this:
create_table "my_table", :id => false, :force => true do |t|
t.string "id", :limit => 36
end
However, when I try to use :references for foreign keys to that table, it generates integer columns for the ID. Can :references be instructed to deal with a non-integer ID? My migration for the referring table is like this:
create_table "child_table" :id => false, :force => true do |t|
t.string "id", :limit => 36
t.references :my_table
end
I know that I could just manually create :my_table_id and :my_table_type columns, but I'm wondering whether :references can be made to do its magic under these circumstances so that I don't have to handle the id+type explicitly throughout my code.

A :type option has been added when referencing since Rails 4.2
t.references :car, type: :uuid, index: true
For example:
def change
enable_extension 'uuid-ossp'
create_table :cars, id: :uuid do |t|
t.integer :seats
# And other car-specific things
end
create_table :wheels do |t|
t.references :car, type: :uuid, index: true
t.integer :radius
# And other wheel-specific things
end
end
source: https://github.com/rails/rails/pull/16231

Nope, references only creates integer columns as of this writing.
I'm sure you could override the references method to do what you want. But IMO you'd be better off specifying your UUID columns and type columns explicitly. That way the code is clear about what is going on behind the scenes.

Related

Uniqueness with scope in migration

I've been trying to find a way to achieve this but I cannot find any attempts even so I am thinking that maybe my approach is completely wrong. That said, what should I do in my migration if I want a combination of two fields to be unique? Please note that I do not want them to be indexes, just database fields.
For example, for the migration below, I can separately add unique: true to the fields, but the combo?
class CreateSomething < ActiveRecord::Migration
def change
create_table :something do |t|
t.date :datestamp, :null => false
t.integer :some_number, :null => false
t.timestamps
end
end
end
I'm not sure what you mean by
Please note that I do not want them to be indexes, just database fields.
Indexes are extra pieces on information that the database stores about the columns.
More importantly an index is exactly what you need!
class CreateSomething < ActiveRecord::Migration
def change
create_table :something do |t|
t.date :datestamp, :null => false
t.integer :some_number, :null => false
t.timestamps
end
add_index :something, [:datestamp, :some_number], unique: true
end
end

How to write foreign keys in many-to-many rich join?

I am trying to create many-to-many rich join between AdminUser and Section with join table as SectionEdit. That is created by generating model. Inside create_section_edits, we write
create_table :section_edits do |t|
t.integer :admin_user_id
t.integer :section_id
t.timestamps
t.string :summary
end
Is there any difference in between using :admin_user_id and "admin_user_id"? Same goes for the other primary keys. admin_user_id is foreign key.
No, but it is better practice to use the symbol :admin_user_id
As an alternative consider:
create_table :section_edits do |t|
t.references :admin_user, index: true
t.references :section, index: true
t.string :summary
t.timestamps
end
Notice this way that you can index the foreign keys by adding index: true
Reference:
http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html#method-i-references
It should be same in this scenario.

Problems setting a custom primary key in a Rails 4 migration

I use postgresql 9.3, Ruby 2.0, Rails 4.0.0.
After reading numerous questions on SO regarding setting the Primary key on a table, I generated and added the following migration:
class CreateShareholders < ActiveRecord::Migration
def change
create_table :shareholders, { id: false, primary_key: :uid } do |t|
t.integer :uid, limit: 8
t.string :name
t.integer :shares
t.timestamps
end
end
end
I also added self.primary_key = "uid" to my model.
The migration runs successfully, but when I connect to the DB using pgAdmin III I see that the uid column is not set as primary key. What am I missing?
Take a look at this answer. Try to execute "ALTER TABLE shareholders ADD PRIMARY KEY (uid);" without specifying primary_key parameter in create_table block.
I suggest to write your migration like this (so you could rollback normally):
class CreateShareholders < ActiveRecord::Migration
def up
create_table :shareholders, id: false do |t|
t.integer :uid, limit: 8
t.string :name
t.integer :shares
t.timestamps
end
execute "ALTER TABLE shareholders ADD PRIMARY KEY (uid);"
end
def down
drop_table :shareholders
end
end
UPD: There is natural way (found here), but only with int4 type:
class CreateShareholders < ActiveRecord::Migration
def change
create_table :shareholders, id: false do |t|
t.primary_key :uid
t.string :name
t.integer :shares
t.timestamps
end
end
end
In my environment(activerecord 3.2.19 and postgres 9.3.1),
:id => true, :primary_key => "columname"
creates a primary key successfully but instead of specifying ":limit => 8" the column' type is int4!
create_table :m_check_pattern, :primary_key => "checkpatternid" do |t|
t.integer :checkpatternid, :limit => 8, :null => false
end
Sorry for the incomplete info.
I have created migrations like this:
class CreateShareholders < ActiveRecord::Migration
def change
create_table :shareholders, id: false do |t|
t.integer :uid, primary_key: true
t.string :name
t.integer :shares
t.timestamps
end
end
end

Rails migration - many belongs_to to same table, multiply FKs

I need some table like this one:
uid:integer
pid:integer
predesposition:integer
primary_key(uid,pid)
foreign_key(uid, user(id))
foreign_key(pid, user(id))
So, two questions:
1. How can I declare multiply FKs in migration?
2. How can I declare two (or more) columns belonged to same table in migration?
Example:
create_table :encounters, :id => false do |t|
t.belongs_to :user, :polymorphic => true
t.belongs_to :user, :polymorphic => true
t.integer :predisposition
end
If you want to refrence other table then follow the concept of foreign key . And wanna to suggest to use full table name instead of uid and pid .
create_table :table_name, {:id => false} do |t|
t.integer :user_id
t.integer :pid #suppose its procedures table
t.integer :predesposition
t.references :user
t.references :procedure
t.timestamps
end
execute "ALTER TABLE table_name ADD PRIMARY KEY (user_id,pid);"
Hope that help .

Schema.rb doesn't understand SQLite virtual tables

I am using sqlite's FTS4 full-text-search functionality. The FTS table is created via a raw-sql migration using CREATE VIRTUAL TABLE fts_foo USING fts4(); When this is executed SQLite actually creates several tables fts_foo, fts_foo_content, fts_foo_docsize, fts_foo_segdir, fts_foo_segments, fts_foo_stat, as well as an index on fts_foo_segdir columns.
However, schema.rb does not understand these columns and outputs the following
# Could not dump table "fts_foo" because of following StandardError
# Unknown type '' for column 'content'
# Could not dump table "fts_foo_content" because of following StandardError
# Unknown type '' for column 'c0content'
create_table "fts_foo_docsize", :primary_key => "docid", :force => true do |t|
t.binary "size"
end
create_table "fts_foo_segdir", :primary_key => "level", :force => true do |t|
t.integer "idx"
t.integer "start_block"
t.integer "leaves_end_block"
t.integer "end_block"
t.binary "root"
end
add_index "fts_foo_segdir", ["level", "idx"], :name => "sqlite_autoindex_fts_foo_segdir_1", :unique => true
create_table "fts_foo_segments", :primary_key => "blockid", :force => true do |t|
t.binary "block"
end
create_table "fts_foo_stat", :force => true do |t|
t.binary "value"
end
I don't think any of these tables should be created in schema.rb. It should simply create a single virtual table and let sqlite build the supporting tables. Is there any way I can do this? If not, what kind of work-arounds would facilitate this?

Resources