I have a model called WalksSection and another called WalkSectionButton. I have created the WalksSection model (and done migration).
Now I want to create WalkSectionButton but want to create two references between the two tables:
walk_sections.id = walk_section_buttons.section_button_id
walk_sections.id = walk_section_buttons.next_section_button_id
The first is the standard one but the other (I think) I need to tell the migration and the model the column name.
So the standard one in the model is
belongs_to :WalkSection
and in the migration is
t.references :WalkSection, foreign_key: true
So I guess I need to have a second line in model and migration which specifies the foreign (and primary) key name but not sure of the syntax.
The other way to do this maybe is to run the migration to create the first reference then do another migration that adds the column and key for the second foregn key.
add_column :walk_section_buttons, :next_section_button_id, :integer
add_foreign_key :walk_section_buttons, :walk_sections, column: :next_section_button_id, primary_key: :id
But not sure what to do to the model. Maybe I don't need to but in the WalksSections model I think I should add a has_many, but again would need to specify a column name for the second one.
Related
What is the correct way to add reference column migration in Rails 6 without getting SQLite3::SQLException: Cannot add a NOT NULL column with default value NULL?
I can hack it to get it working; but, I am preparing a tutorial for a grad class, so I want to make sure I'm doing it "by the book".
The starting point is a Post class (think "blog post"). I want to add an Author class and set up an 1-to-many relationship between authors and posts. After adding the author class and running the corresponding migration, I then create a migration to add an Author reference to Post:
rails g migration AddAuthorToPost author:references
This command generates:
class AddAuthorToPost < ActiveRecord::Migration[6.0]
def change
add_reference :posts, :author, null: false, foreign_key: true
end
end
The problem is, of course, that SQLite complains because it won't tolerate the potential for a null foreign key --- even if the Post table is empty: (How to solve "Cannot add a NOT NULL column with default value NULL" in SQLite3?)
I looked back at the previous year's tutorial (prepared by a different instructor) and the generator did not add null: false to the migration. (See also Add a reference column migration in Rails 5)
Removing null: false from the migration allows the migration to run; but, "disabling safety features" doesn't seem appropriate in a classroom setting :)
Is there a better way to do this?
By default, a foreign_key is required (on app level, not on database).
To disable, in config/application.rb add
config.active_record.belongs_to_required_by_default = false
Or
class YourModel < ApplicationRecord
belongs_to :another_model, optional: true
end
I've created a join table with
rails generate migration CreateJoinTableFoosBars foos bars
and it has indeed created a working joining table, however I can't see the model for it and thus I can't add the
validates_uniqueness_of :foo_id, scope: :bar_id
How can I do it in this case? Thanks in advance.
Add a unique index that includes both columns. That will prevent you from inserting a record that contains a duplicate foo_id/bar_id pair.
add_index :foo_bars, [:foo_id, :bar_id], unique: true
generating a migration does not generate a model as well. If you use the model generator then it will also produce a migration file and the model file:
rails generate model foo_bar foo_id:integer bar_id:integer
I have a number of many-to-many relationships in my app.
I do not need to store information about the relationships themselves, so am using the has_and_belongs_to_many relation in my models.
I've read the Active Record documentation and it seems to confirm my strategy, BUT I'm not clear if I still need to create join tables in the database or if ActiveRecord in Rails 3.2 is smart enough to handle it using the model relations alone.
Any references or explanations would be appreciated.
----- Break -----
If I did need to store data about the relationship itself and I were using has_many => through in my model, would I need to remove the Primary Key from the "through" table (e.g. so that it only has the two foreign keys?)
Thank you!
Yes, you need to create the join table for a has_and_belongs_to_many association. Remember in Rails you need to 'migrate to create'. Using this article as an example, say we have an Account model and a Role model, we can create a join table through this migration:
rails generate migration create_accounts_roles_join_table
Now we will edit the migration file that was just created
create_table :accounts_roles, :id => false do |t|
t.integer :account_id
t.integer :role_id
end
It is important to include :id => false as this will leave off the primary key that is normally generated when you create a table. Also, we specified the two foreign keys account_id and role_id.
run rake db:migrate and add the HABTM associations in both models and everything is set up.
Also, as a side note, adding join_table to the end of the migration generator is not required but is more descriptive and integer can be replaced with references when adding the foreign keys. They are equivalent but maybe a bit more descriptive.
On the second part of your question, you don't need to remove the primary key from the table.
I have a Rails 3.1 app with a User model and a Venue model. These two models have a HABTM relationship - A user may manage many venues and a venue may be managed by many users.
I'd like users to be able to select a default venue so I'm trying to add a default_venue_id attribute to User with the following migration:
class AddDefaultVenueIdToUser < ActiveRecord::Migration
def self.up
add_column :users, :default_venue_id, :integer
end
def self.down
remove_column :users, :default_venue_id
end
end
The problem is that when I run that migration against my PostgreSQL database, it's assuming that default_venue_id is the foreign key for a relationship with the non-existent default_venues table and throws the following error:
PGError: ERROR: relation "default_venues" does not exist
: ALTER TABLE "users" ADD FOREIGN KEY ("default_venue_id") REFERENCES "default_venues" ("id")
Should I be doing something to tell the database that I'm not trying to create a relationship or am I going about this the wrong way?
Edit: I've just realised that another developer who worked on the project added the schema_plus gem which automatically defines constraints for columns ending in _id
That explains why I've never run into this behaviour before!
It would be helpful to see the Models as well to diagnose this problem.
However with that being said, I think that if you are using HABTM associations here it might be a good idea to take a look at a has many through relationship. example: VenueManagement which would have your user_id and venue_id. That way you could handle extra attributes on the association where it makes sense, like a default flag.
Hope that helps.
Since Rails seems to pick up on the _id part of the tag and tries linking it to a table, the easy solution to this is to try name it differently as convention says a field with _id links to a table.
An example of which could be
:default_id_for_venue, or just :defualt_venue
I am new to RoR. I used "rails generate model ServiceConfigs" command to generate a table.
so may commands are as below
rails generate model ServiceConfigs configs:string
rake db:migrate
-- can see app/db/service_config.rb created.
Now edited service_config.rb file to add 2 columns and which has a foreign key relation to service table. So here is code
class ServiceConfigs < ActiveRecord::Base
belongs_to :service, :dependent => :destroy
validates_presence_of :configs
end
Now when I login to underline database, and look at the table I don't see foreign key relation in table schema. Whats wrong/more I need to do?
highly appreciate your time and help
Krishna
So a few notes for you as you're getting started here: Firstly, I'd name your model in the singular form, as though you are describing a single instance of it: ServiceConfig and in the case where it belongs to a service, you may want to think of a different name all together.
Secondly validates_presence_of suggests that you have that field, so firstly, I'd remove the validation until you know that your DB has that column and that the migration worked. You can make sure by looking at your migration file and confirming that the column is being created.
You can define the relationship the "rails way" in your migration too:
http://guides.rubyonrails.org/association_basics.html
create_table :service_configs do |t|
t.string :configs
t.references :service
t.timestamps
end
Update
If you want to rerun a particular migration run:
rake db:migrate:redo VERSION=20100421175455
You can take a look in your schema to see what migration you are currently at as well. And you can also take a look at the schema to see what your DB is expected to look like as well.