How do I create a foreign key in rails 5 if I've already created the models for the tables I want to associate? - foreign-keys

All of the references I've found either show me how to do it upon table creation, or are for a much earlier version of rails. Ideally, I'd like like the foreign_key to be named 'author_id' in the questions table to distinguish it from other users who may be leaving comments or answers later.
class Question < ApplicationRecord
belongs_to :user
end
class User < ApplicationRecord
has_many :questions
end

You can create a new empty migration file in your terminal via rails generate migration RenameUserFkOnQuestion. Open it up and build your migration. This is a handy guide if you're not sure on the name of something.
def change
change_table :questions do |t|
t.rename :user_id, :author_id
end
end
Run the migration and head over to your models. You'll need to update your relationships like so:
class Question
belongs_to :author, class_name: 'User'
end
class User
has_many :questions, inverse_of: :author
end
Then you should be good to go.

Related

Rails 4 - has_and_belongs_to_many assocation

I created a has_and_belongs_to_many association between users and projects so that a user would be able to join in on a project. The association table exists however, I am unsure how I would create the association.
View
Schema
I definitely must recommend you to not use has_and_belongs_to_many, because there is no way for you do to callbacks, validations and so on.
It is definitely nice to use a real join model and use has_many, through.
class User
has_many :project_users, dependent: :destroy
has_many :projects, through: :project_users
end
class Project
has_many :project_users, dependent: :destroy
has_many :users, through: :project_users
end
class ProjectUser
belongs_to :project, required: true
belongs_to :user, required: true
validates :project, uniqueness: { scope: :user }
end
This works very seamlessly, you can do:
User.update(project_ids: [1,5,6,7])
And it will join the user to these project unless any validations fail.
I started out a big project with these tables everywhere, after a few months we started running into duplication issues, bad state of records and it was a hot mess. Using a real join model is so worth it.
Since you have your project ID inside hidden you could just do this inside JOIN (post) action
def join
#project = Project.find(params[:project][:id])
current_user.projects << #project
end
so if you have instance of #project and instance of user - in my example it is current_user( for example if you use devise) then you would just assign them using operator <<
Here is the reference:
http://guides.rubyonrails.org/association_basics.html#has-many-association-reference
Hope it helps

How to add foreign_key pointing to same table?

I've got a table 'users' but one user might be a manager of another user, one user could also be a manager of many other users, so its a one-to-many relationship, and it only involes one table. heres my approach:
1.I've added 'manager_id'(which really stores another uners id) column to users table.
2.I've defined relationship in User model class:
belongs_to :manager, foreign_key: 'manager_id',class_name:'User'
has_many :minions, class_name:'User'
Now, say in rails console if i set one users 'manager_id' to another users id its all fine. but if i try to use methods like 'user.manager' or 'user.minions' it says those methods aren't defined. Were have i gone wrong?
I think you want to implement self inheritance that can be done as :
class User < ActiveRecord::Base
self.inheritance_column = :child_class
has_many :minions, :foreign_key => :parent_id, :as => :parent
belongs_to :parent, :polymorphic => true
end
This is just a sketch of what i understood from the above description, it can be enhanced.

Rails user experience vs file structure with carrierwave and nested forms - Need input on design decisions

I have 2 models, product and a photos model as follows:
product.rb
class Product < ActiveRecord::Base
has_many :photos, dependent: :destroy
accepts_nested_attributes_for :photos, allow_destroy: true
end
photo.rb
class Photo < ActiveRecord::Base
belongs_to :product
validates :album, presence: true
mount_uploader :image, PhotoUploader
end
I'm using carrierwave & s3 for file uploads.
I can nest the forms so that users can upload photos at the same time that they create the product. In this scenario, the photo models are saved before the product model is saved, which leads to a photo file path of something like:
uploads/photos/images/photo_id
But the file structure would make more sense if it was something like:
uploads/product/id/photos/
However, product.id is nil at the time of photo creation.
With that in mind, a few questions:
Does the file structure really matter that much or am I over thinking it?
Should I do something instead where the product is saved first with basic info and then the files are attached on a separate form?
Is there something I'm overlooking like a way to trigger carrierwave to move the files after the product model is saved?
From a UI standpoint is it bad practice to have users go thru a multi-step process (in this case for creating a product)?
My solution to have a path such as uploads/products/id/photos/ is to configure the PhotoUploader as follows:
def store_dir
"uploads/products/#{model.product_id}/images"
end
Just be careful that there are no validations that would cause product_id to be non-existant at the time the store_dir method is called.

Rails associations has_many through

I'm unable to grasp the detail understanding of following rails association.
has_many through
has_and_belongs_to_many
What this associations do and the effect on table? please help
Has_many is basically saying that one thing links to many, for example one category has many products within in. Belongs_to is basically the other way around, so a product belongs to category. They allow you to retrieve data from a table that links to the other table e.g. You could get the category title from the product table for a certain product through that link. Does that help?
From Choosing Between has_many :through and has_and_belongs_to_many
Rails offers two different ways to declare a many-to-many relationship
between models. The simpler way is to use has_and_belongs_to_many,
which allows you to make the association directly:
class Assembly < ActiveRecord::Base
has_and_belongs_to_many :parts
end
class Part < ActiveRecord::Base
has_and_belongs_to_many :assemblies
end
The second way to declare a many-to-many relationship is to use
has_many :through. This makes the association indirectly, through a
join model:
class Assembly < ActiveRecord::Base
has_many :manifests
has_many :parts, through: :manifests
end
class Manifest < ActiveRecord::Base
belongs_to :assembly
belongs_to :part
end
class Part < ActiveRecord::Base
has_many :manifests
has_many :assemblies, through: :manifests
end
The simplest rule of thumb is that you should set up a has_many
:through relationship if you need to work with the relationship model
as an independent entity. If you don't need to do anything with the
relationship model, it may be simpler to set up a
has_and_belongs_to_many relationship (though you'll need to remember
to create the joining table in the database).
You should use has_many :through if you need validations, callbacks,
or extra attributes on the join model.
Let me highlight the most important sentence:
The simplest rule of thumb is that you should set up a has_many :through relationship if you need to work with the relationship model as an independent entity. If you don't need to do anything with the relationship model, it may be simpler to set up a has_and_belongs_to_many relationship
has and belongs to many is very simple to use, but you don't have direct access to related objects, you can only hold references to two models, and nothing else.
While has many through will enable you to do things like user.role and to get a list of all connected second model instances. It will also enable you to get access to data specific to the relation between first and second models.
It all depends if you need something quick and easy, like for a mockup or you want to build a long-term project. I recommend you to check this out for more details.

Add Many Weeks to Record

I currently have application which allows users to upload an image.
Currently. each image belongs to a certain event, or in my case a certain week.
To reduce redundancy and server overload with the same image being uploaded multiple times, I would like to allow the user to upload (1) image and give them the option to assign it to multiple weeks that are load in the database.
Here is the setup now:
Creative Model
class Creative < ActiveRecord::Base
belongs_to :week
mount_uploader :image, CreativeUploader
end
Week Model
class Week < ActiveRecord::Base
has_many :creatives
end
The issue I am having is getting my application to pass multiple [week_id]'s to a single creative.
Should this be converted to a has_and_belongs_to_many relationship with a join table?
NestedForm
<%= creative_form.collection_select(:week_id, #campaign.weeks, :id, :start_at) %>
TIA
EDIT If it's a many-to-many relationship then your associations will look like this, and yes, you need a new join table.
Creative Model
class Creative < ActiveRecord::Base
has_and_belongs_to_many :week
mount_uploader :image, CreativeUploader
end
Week Model
class Week < ActiveRecord::Base
has_and_belongs_to_many :creatives
end