Rails Migration Generated Join Table Schema But No File - ruby-on-rails

I created a join table for a HABTM association in my Rails app. It created the table in the schema, but it never generated a model file in the app. Will it still work? Why did it not generate a file?
Here is my migration:
class CreateBooksAuthorsJoinTable < ActiveRecord::Migration
def change
create_table :books_authors, id: false do |t|
t.integer :book_id
t.integer :author_id
t.timestamps
end
end
end
Models
class Book < ActiveRecord::Base
has_and_belongs_to_many :feeds
end
class Author < ActiveRecord::Base
has_and_belongs_to_many :posts
end

You would have to explicitly generate a model; it doesn't happen as a by-product of creating a join table.
A has_and_belongs_to_many association doesn't actually need a model class representing the association. It is supposed to be just a join table so what you've set up is exactly right.
The other option for such associations is a has_many through: association which uses an intermediate, or join, class. This is discussed in more details in the rails guide for associations. You would have to generate that joining model yourself though.

Related

Does having has_many and belongs_to using ActiveRecord generate alter sql statements in structure.sql?

I have code like this
class Author < ApplicationRecord
has_many :books, dependent: :destroy
end
class Book < ApplicationRecord
belongs_to :author
end
While creating generate migration, I didn't use any keyword to generate foreign key associations. But I see alter sql statement with respect to adding foreign key in structure.sql . How and Why?
Merely setting up the associations in your model DOES NOT alter the schema in any way and this code will just give an undefined column error unless you actually create the books.author_id column through a migration.
Running the model generator with author:belongs_to or author:references (which are aliases) does add a foreign key column to the migration as well as a belongs_to :author association in the model.
# rails g model book title:string author:belongs_to
class CreateBooks < ActiveRecord::Migration[6.0]
def change
create_table :books do |t|
t.string :title
t.belongs_to :author, null: false, foreign_key: true
t.timestamps
end
end
end
But a association does not actually have to have a foreign key constraint. If you ran the generator with author_id:bigint the association will work but you will have no foreign key constraint to guarantee referential integrity.
Using books:has_many on the other hand in a generator will generate a bad migration since a has_many association is not a database column.

Creating a new table in mongoid for has_and_belongs_to_many relationship

I just started to code in rails using mongoid ,previously I coded in sql,sqlite etc,Now Iam a bit confused between associations.like in sql when you want a has_and_belongs_to_many association between two models you do in such a way
for example
class Student < ActiveRecord::Base
has_and_belongs_to_many :subjects
end
class Subject < ActiveRecord::Base
has_and_belongs_to_many :students
end
and we create a new table as
rails g migration CreateJoinTableStudentSubject student subject
In our migration file we do like this
def change
create_table :students_subjects do |t|
t.references :student
t.references :subject
t.timestamps
end
end
now my question is is this neccesary to create a new table when using mongoid or der is a alternative way for doing this.plz help Iam new to mongoid and rails.thank you
You just need to include some code into your classes like this:
class Student
include Mongoid::Document
has_and_belongs_to_many :subjects
end
class Subject
include Mongoid::Document
has_and_belongs_to_many :students
end
There is a great documentation here.
Hope it will help you!

Ruby On Rails scaffold need to include foreign keys?

I'm learning the basics of ruby on rails and I want to make some simple queries but I have a doubt:
I will have these models:
class Client < ActiveRecord::Base
has_one :address
has_many :orders
has_and_belongs_to_many :roles
end
class Address < ActiveRecord::Base
belongs_to :client
end
class Order < ActiveRecord::Base
belongs_to :client, counter_cache: true
end
class Role < ActiveRecord::Base
has_and_belongs_to_many :clients
end
Now, I will use scaffold to generate all the things, and I want to know if I have to directly put the foreign keys in the scaffols, like:
rails generate scaffold Adress street:string number:integer client_id:integer
Or when I make those associations and then migrate my db they will be implicit?
I don't know if I explain myself in the best way.
Thanks
Yep, there is no reference. You need to either pass the client_id or a reference to Client model, e.g:
rails generate scaffold Address street:string number:integer client_id:integer:index
or
rails generate scaffold Address street:string number:integer client:references
Either, in rails 4 you can use belongs_to this way:
Assume that you have a user model in your application
rails g scaffold comment belongs_to:user text:string
it generates that class in your migrate folder:
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :text
t.belongs_to :user, index: true, foreign_key: true
t.timestamps null: false
end
end
end
you should execute rake db:migrate then, this command create user_id properties as a index column in your database table.

ActiveRecord, polymorphic has_many, :through, :as

I am new to Rails and I'm having a superb deal of difficulty wrapping my head around what seems to be a very simple database structure, but I'm thrown by the idea that objects must belong to other objects.
In a site that I am creating, a User may create many Posts.
A Post may fit into any number of many different Topics.
So what Rails would like is that Posts belong to both Topics and to Users, while Topics also belong to Posts (many-to-many?). This makes some sense in my head, but then I can't imagine how to create a Topic independent of a Post (which is reasonable to the site's function).
Is this possible? Any help would be greatly appreciated - this is giving me a headache!
You can use has_and_belongs_to_many (HABTM) for this kind of relationship:
class User < ActiveRecord::Base
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :user
has_and_belongs_to_many :topics
end
class Topic < ActiveRecord::Base
has_and_belongs_to_many :posts
end
in addition to the tables for users, posts and topics, you will need to create a migration for the HABTM relationship:
rails g migration create_posts_users post:references user:references
Note that the model names appear in alphabetical order in the table name
I don't think you are using polymorhpic relations here, just a regular many-to-many relation. Your model relations should look something like:
class User
has_many :posts
end
class Post
has_many :post_topics
has_many :topics, through: :post_topics
belongs_to :user
end
class Topic
has_many :post_topics
has_many :posts, through: :post_topics
end
class PostTopic
belongs_to :post
belongs_to :topic
end
This scenario is perfectly fine, a Topic can have may Posts, and a Post can have many Topics, which is a many-to-many relationship. In rails that would generally translate to has_and_belongs_to_many. Therefore you can define your models as follows:
class Post < ActiveRecord::Base
has_and_belongs_to_many :topics
end
class Topic < ActiveRecord::Base
has_and_belongs_to_many :posts
end
The corresponding generated Migration and database tables will look like this:
class CreatePotsAndTopics < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.timestamps
end
create_table :topics do |t|
t.string :name
t.timestamps
end
create_table :posts_topics, id: false do |t|
t.belongs_to :post
t.belongs_to :topic
end
end
end
As you can see both Topic and Post tables are standalone tables with no reference to any other table, which means they can be treated on their own. they way they get linked is through the posts_topics join table. Which enables you to do have access to #post.topics and #topic.posts
If you are uncomfortable with such a scenarios pick up a good rails book or do an online tutorial or course which walk you through creating a full rails application.

ActiveRecord : database relationship definition in models vs foreign keys definitions in tables setup?

I was following an online tutorial on ActiveRecord where the instructor writes the following code when defining a table and its relationship:
#Setup of the database table
class CreateTimeEntries < ActiveRecord::Migration
def change
create_table :time_entries do |t|
t.float :time
t.belongs_to :customer
t.belongs_to :employee
t.timestamps
end
end
end
#Relationship definition in the relevant model
class TimeEntry < ActiveRecord::Base
belongs_to :customer
belongs_to :employee
end
Aren't those lines redundant ?
#in table setup
t.belongs_to :customer
t.belongs_to :employee
#in the relevant model
belongs_to :customer
belongs_to :employee
I understood that the lines in the db table setup are here to define foreign keys, how come then that we need to define the relationship in the model as well?
I thought foreign keys were by themselves defining such relationship.
What am I missing here? Can't find any clear answer on the web. Thanks a lot.
Those are two completely different methods:
Within migration belongs_to :parent only creates parent_id column - it is only executed when you run migration. No foreign key is defined here - rails do not believe those are needed. This is just a syntatic sugar for:
t.integer :parent_id
After migrations are run, all rails know is that your TimeEntry model has parent_id column - it has absolutely no other meaning. This is why you have to give it the meaning with belongs_to - this method executed in context of ActiveRecord objects will create the association - it will create a method parent with all the arel power behind it to fetch referenced object as well as provide some validation and save hooks to make working with the object easier. It is not always necessary to have this defined.
In short, without belongs_to you would only be able to call my_model.parent_id (provided by belongs_to in migration), but not my_model.parent
They have different goals. The migartion define de db table and allow create or modify the table. The model define to the Rails framework how to work with db tables.
You must define your models like this:
class Customer < ActiveRecord::Base
has_many :time_entries
end
class Employe < ActiveRecord::Base
has_many :time_entries
end
class TimeEntry < ActiveRecord::Base
belongs_to :customer
belongs_to :employe
end
At the migration level, belongs_to :customer add a field customer_id that relate models.

Resources