I'm working on a photo gallery app. Photo has a belongsTo relationship to Album (Album has_many realtionship to Photo) How do I create the migration that adds this relationship to the database correctly? I have tried - rails generate add_album_to_photo but that comes through as an empty migration. I could use a push in the right direction.
Assuming tables albums and photos exist already, all you have to do is add a column album_id to your photos table:
class AddAlbumToPhoto < ActiveRecord::Migration
def self.up
add_column :photos, :album_id, :integer
end
def self.down
remove_column :photos, :album_id
end
end
Or:
class AddAlbumToPhoto < ActiveRecord::Migration
def self.up
change_table :photos do |t|
t.references :album
end
end
def self.down
change_table :photos do |t|
t.remove :album_id
end
end
end
Or if you insist on generating the code:
rails g migration add_album_to_photo album_id:integer
Related
I have an existing model 'micropost' and I found out that there is better name for the model to suit my application. What would be the better approach to rename 'micropost' model to 'story' model without affecting its indexes? I am working on Rails 5.0.0.rc1. The migration snippet is:
class CreateMicroposts < ActiveRecord::Migration
def change
create_table :microposts do |t|
t.text :content
t.references :user, index: true
t.timestamps null: false
end
add_index :microposts, [:user_id, :created_at]
end
end
1 .Make migration to change the database table name from micropost to story.
class RenameOldTableToNewTable< ActiveRecord::Migration
def change
rename_table :old_table_name, :new_table_name
end
end
2 .Change manually the Active Record model class into Story
Run command on console:
$ rails g migration RenameMicropostToStory
Edit migration file:
class RenameMicropostToStory < ActiveRecord::Migration
def change
rename_table :microposts, :stories
end
end
then,
$ rake db:migrate
I have a model called categories currently they belong to product but I'd like them to belong to store instead. I have several thousand of these so what I'd like to do is create a migration that adds a store_id to categories and then, gets the associated product.store.id from it's current association and adds that to the store_id. After that I'd like to remove the product association.
Does anybody know how to easily and safely achieve that?
Should you add the association in the wrong direction, you can use change_table to reverse the association:
class CreateFavorites < ActiveRecord::Migration[5.0]
def change
create_table :favorites do |t|
t.belongs_to :article
t.timestamps
end
end
end
class RemoveArticleFromFavorites < ActiveRecord::Migration[5.0]
def change
change_table :favorites do |t|
t.remove_references :article
end
end
end
class AddFavoriteToArticles < ActiveRecord::Migration[5.0]
def change
change_table :article do |t|
t.belongs_to :favorite
end
end
end
First rename column to store_id,
rename_column :categories, :product_id, :store_id
Then change the assosciation.
Now you can either write a rake task to transfer the data or you can manually do it via console.
It's better way to write a rake task.
According to your requirement your rake task can be, get the store from the product and assign to the category according to your requirement.
require 'rake'
namespace :category do
task :product_to_store => :environment do
Category.all.each do |category|
product = Product.find(category.store_id) //you will get product,as now it chnaged to store_id
if product.present?
category.store_id = product.try(:store).try(:id) //assign the product's store_id to the category, use try to reject errored records
category.save
end
end
end
end
Now run, **`rake category:product_to_store`**, thats it, the data gets transfered.
You can just add new migration that will create the new reference with categories as store.
class YourMigrationName < ActiveRecord::Migration
def up
add_reference :categories, :store, index: true
Category.all.each do |category|
category.store_id = category.product_id
category.save
end
remove_column :product_id
end
def down
add_reference :categories, :product, index: true
Category.all.each do |category|
category.product_id = category.store_id
category.save
end
remove_reference :categories, :store, index: true
end
end
May be if you have added the product reference and index then write the same as the store so then it will delete the index as well.
you have data in the column you don't want to lose, then use rename_column
I'm trying to add product attachment functionality to a Spree store. E.g. a product has many attached documents: brochures, instruction manuals, etc. I can't get the relationship between documents and products to work.
I can use the Paperclip gem for the attachment functionality since Spree already uses it for images.
I have the "document" model: models/spree/document.rb:
class Spree::Document < ActiveRecord::Base
belongs_to :products, class_name: "Spree::Product"
has_attached_file :pdf
end
Then I try to relate the document model to the Spree::Product model in models/spree/product_decorator.rb:
Spree::Product.class_eval do
has_many :documents, dependent: :destroy
end
Then I add migrations:
class CreateDocuments < ActiveRecord::Migration
def change
create_table :spree_documents do |t|
t.timestamps
end
end
end
class AddPdfToDocuments < ActiveRecord::Migration
def self.up
add_attachment :spree_documents, :pdf
end
def self.down
remove_attachment :spree_documents, :pdf
end
end
Now I go into the rails console to see if it worked:
#=> prod = Spree::Product.first
#=> prod.document
#=> PG::UndefinedColumn: ERROR: column spree_documents.product_id does not exist
#=> LINE 1: ..."spree_documents".* FROM "spree_documents" WHERE "spree_doc...
^
#=> : SELECT "spree_documents".* FROM "spree_documents" WHERE "spree_documents"."product_id" = $1
Seems like I'm not defining the relationship between documents and products correctly, but I'm not sure what the issue is.
It looks like you never added a product_id column to your Spree::Documents table. When you define a model belongs_to another model, it tells ActiveRecord that the first one will be a [relation]_id column in its table.
You just need to make sure to add t.references :product in your migration, so it'd look like:
class CreateDocuments < ActiveRecord::Migration
def change
create_table :spree_documents do |t|
t.references :product
t.timestamps
end
end
end
I would like to add a has_many relationship to two existing tables/models in my app & I'm not too sure how to di it?
When I did this before with a new model the rails generate command handled everything for me, with just rails generate model Photo image:string hikingtrail:references it created the below migration
class CreatePhotos < ActiveRecord::Migration
def change
create_table :photos do |t|
t.string :image
t.references :hikingtrail
t.timestamps
end
add_index :photos, :hikingtrail_id
end
end
Now I would like set up a relationship between users & photos with each user has_many :photos.
When I generate a migration to achieve this it does not include the add_index :photos, :user_id, is this something I should be doing manually or are the below steps enough for setting up this relationship in my database?
rails g migration AddUserIdToPhotos user_id:integer
which creates...
class AddUserIdToPhotos < ActiveRecord::Migration
def change
add_column :photos, :user_id, :integer
end
end
& then run...
rake db:migrate
It is enough to set up your relationship. You can add a index to improve the speed of your record searching. In fact some recommend to put a index to all the foreign keys. But don't worry about this now, i guess you are not going to have that many records to use a index.
If you have already migrated everything and want to add a index make do:
rails g migration AddIndexToUserIdToPhotos
and inside add the index column:
class AddUserIdToPhotos < ActiveRecord::Migration
def change
add_index :photos, :user_id
end
end
I have a 2 Models, User and Post.
I want the Post model to have a User in it i.e. add a user_id in the Posts table.
What will my migration look like? Or do I just do this manually like:
add_column :posts, :user_id:integer
yep, just do it manually. It'll look like this:
class AddUserIDToPosts < ActiveRecord::Migration
def self.up
add_column :posts, :user_id, :integer
end
def self.down
remove_column :posts, :user_id
end
end