I have a ActiveRecord model GPA that doesn't have a primary key:
class GPA < ActiveRecord::Base
end
When I try to call GPA.first.to_json I get TypeError: false is not a symbol. I'm guessing that this is due to ActiveRecord trying to lookup the primary key. What is the correct way to implement a model without a primary key?
Normally there is either some column or combination of columns which together do form a primary key. When you say your table doesn't have a primary key do you mean it doesn't have an id field?
Is there another column that is a unique/natural key? If so you can do:
class GPA < ActiveRecord::Base
set_primary_key :strm # eg column strm is a unique/natural key
end
You can also use composite keys with the composite keys gem, as follows:
class GPA < ActiveRecord::Base
set_primary_keys :student_id, :strm
end
You need something like this on your migrations or schema
create_table :gpas, :id => false do |t|
t.int :strm
t.string :gpa
t.string :acad_career
t.int :student_id
end
It is highly advisable to use the rails default conventions when modelling your data. Only override defaults if you are dealing with legacy tables.
Option 1
You have to override the primary key for your model by doing the following:
class Foo < ActiveRecord::Base
self.primary_key = "strm"
end
Now if you call .to_json the json will include the key id instead of strm.
Option 2
Alternative is to use a json constructors such as jbuilder, so it does not try to convert non-existent 'id' to json using default Rails json constructor.
Add a migration that adds id as a column. It's not going to hurt any existing code. Just make sure it's got an autoincrement on it so it's not going to moan about duplicate entry 0.
Have you tried ActiveModel::Serializers::JSON?
Related
I was storing a log of activities using an ActiveRecord model and it seems that one can dispose of the primary key:
class NetLog < ApplicationRecord
def self.primary_key
nil
end
I can create records, query for them, and loop across results. Surely I will unable to update, but it is a log, no updates expected. So it seems to work for my purposes. Now I wonder, am I using a documented option?
EDIT: Ah, I see, the problem was that also my ApplicationRecord (legacy) likes to set a primary_key, and then it seems to override the setting in the migration.
So perhaps a cleaner question is: How does the setting of self.primary_key interacts with the settings in db/schema.rb? My guess now is that if no primary_key is defined, schema.rb is examined to set the primary_key, but that if a primary_key getter is defined, schema.rb "id: false" is ignored
This is one of the ways, but why have a id column in the first place if you want the value to be nil? You can create a table without primary key using Rails migrations
create_table :net_logs, id: false do |t|
t.string ...
end
Hope that helps!
I have a table called Contracts. Its current default primary key is the :id field that Rails automatically generates, which is an integer. I want to have a field called contractId that is a string type and use it as a primary key instead. What I want to know is:
Is this a best practice? Are there any potential issues with doing this?
How I would go about it
Ruby on Rails (RoR) likes to emphasise the concept of convention over configuration. Therefore, it seeks to minimialise the amount of configuration.
So if you want contractId that is a string type then you can add one extra field in your table and use it wherever you want and let the Rails use id as primarykey.
Change PrimaryKey
Generate a new migration file name it "ChangePrimaryKey" (You can give any name).
class ChangePrimaryKey < ActiveRecord::Migration
def up
remove_column :table, :id # remove existing primary key
rename_column :table, :udid, :id # rename existing UDID column
execute "ALTER TABLE table ADD PRIMARY KEY (id);"
end
def down
# Remove the UDID primary key. Note this would differ based on your database
execute "ALTER TABLE table DROP CONSTRAINT table_pkey;"
rename_column :table, :id, :udid
add_column :table, :id, :primary_key
end
end
If you are creating a new table, your migration might look like this:
class AddTableWithDifferentPrimaryKey < ActiveRecord:Migration
def change
create_table :table, id: false do |t|
t.string :id, null: false
# other columns
t.timestamps
execute "ALTER TABLE table ADD PRIMARY KEY (id);"
end
end
end
Notice the id: false options you pass into the table — this asks Rails not to create a primary key column on your behalf.
Changes to Model
In the model, it is essential that you add the following line in order for
Rails to programmatically find the column you intend to use as your primary key.
class Table < ActiveRecord::Base
self.primary_key = :id
# rest of span
end
I hope you can do rest of the things.
Don't change default id if you want to see Rails real Magics :)
As you may know, Rails supports changing the primary id column out of the box:
class Contract < ActiveRecord::Base
self.primary_key = "contractId"
end
Please note that even if the contractId column has a unique index, an index on a string column will always be a bit slower than an index in an integer column.
Furthermore, this is not the Rails way and might confuse other developers that work with this application. Especially building associations or routes are error-prone when your table has a non-standard primary key. IMHO that is a good reason to avoid using this technic as long as possible.
Well I googled my question but I couldn't find anything or I it's not the correct question..
The issue is I need modify the primary_key name of the database :id with :another_id, in my project I need to use pgrouting and it contains several plsql functions and these functions uses the primary-key with the name gid and instead of modify the plsql functions is better change the id name, and I was thinking do this with a migration becouse I thought it's the rails way.
Is it possible, and how I can do this ??
Thanks in advance and sorry for my english.
Edit
create_table :pruebas, primary_key: :gid do |t|
t.string :name
t.timestamps
end
This do the trick, and with this active record generate and uses the pk as gid.
Sorry if my question was not clear.. Gracias por las respuestas.
To set the primary key yourself, when you create the table, you would do:
create_table(:table_name, primary_key: 'gid') do |t|
...
end
And you need to define the primary key name in your model:
self.primary_key = 'gid'
I don't have any experience using PostgreSQL or pgRouting, but I believe what you're looking for is a method for instructing ActiveRecord to use a different column as the primary key.
I believe you're looking for set_primary_key.
class Project < ActiveRecord::Base
set_primary_key "gid"
end
I want to create a model 'Relation' which extends ActiveRecord::Base, set it's table name as 'questions_tags', and without primary key. What should I do?
class Relation < ActiveRecord::Base
set_table_name 'questions_tags' # set table name, right?
# how to define 'no-pk'?
end
UPDATE
I know use 'create_table' can solve this problem, but this is just what I want to know: What is the magic behind create_table(:id=>false)? How can I get the same effect without using create_table(:id=>false)?
Create a migration that looks like this:
class CreateQuestionsTags < ActiveRecord::Migration
def self.up
create_table :questions_tags, {:id => false, :force => true} do |t|
...
t.timestamps
end
end
def self.down
drop_table :questions_tags
end
end
If you're looking to create a pivot table, as it looks like from the table name, then AR will handle that in the background.
However, if you're looking to create a table with more feilds then:
1) rename your table to "realtions" please
2) use a primary key "id"
There's no good reason not to be using a primary key in a table, and it is very likely that you might well find yourself regretting it later.
Why don't you want a PK?
Active Record expects a PK, and I don't see what harm it can do.
I created a new model in my rails app. Since it's a one-to-one relation with another table, there's no need for the new model to have an id column. Everything is working fine, but for some reason, all of my Shoulda tests on this model are failing. For example:
should_validate_presence_of :first_name
is throwing this error:
ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'my_new_table.id'
in 'field list': SELECT `my_new_table`.id FROM `my_new_table` WHERE
(`my_new_table`.`some_other_column` IS NULL) LIMIT 1
Does Shoulda require an ID column? If so, is there a way around this?
Did you alias the primary key for Rails purposes?
set_primary_key :my_fk_id
Rails expects your models to have an integer id column as a primary key. You can set it to the foreign key like #MattMcKnight suggests but I'd recommend you create the id column even if you don't strictly need it. In my experience it will save you tons of headaches like this, with basically no downside.
Did you run rake db:migrate and rake db:test:prepare after you created the new model?
All tables require an id column that's just the way that ActiveRecord works. As MattMcKnight points out, you can designate another column as the primary key. You can also specify that a table have no id column is creatied by providing :id => false as an option to create_table.
Matt's answer covers renaming the primary key in the model definition. Here's how to do it in a migration.
Note, providing the primary key option without giving the id option as false means that you do not have to add to column's definition to the block. Rails will create it for you. And automatically use it in any join tables.
Example:
class CreateTableWithOUtID < ActiveRecord::Migration
def self.up
create_table :my_new_table, :primary_key => :another_table_id do |t|
t.string :some_other_column
end
end
def self.down
drop_table, :my_new_table
end
end