Group has_and_belongs_to_many - ruby-on-rails

Given a model with ActiveStorage: DayFrame, Day, Session. Models and migration see below. DayFrame and Session are many-to-many relationship. day_frames_sessions intermediate join table that includes foreign keys referring to each of the classes DayFrame and Session. How can I get day_frames group by session and sort by day.date like this:
{session_id_1=> [DayFrame1, DayFram2, DayFram3], session_id_2 => [DayFrame2, DayFram1, DayFram4]}
class DayFrame
has_and_belongs_to_many :sessions
belongs_to :day
end
class Day
has_and_belongs_to_many :sessions
has_many :day_frames
end
class Session
has_and_belongs_to_many :conference_day_frames
end
The migrations are:
class CreateDay < ActiveRecord::Migration[5.2]
def up
create_table :days do |t|
t.date :date
t.string :day_type
t.timestamps
end
end
def down
drop_table :days
end
end
class CreateDayFrame < ActiveRecord::Migration[5.2]
def up
create_table :day_frames do |t|
t.string :name
t.time :begin_time
t.time :end_time
t.string :frame_type
t.timestamps
t.references :day, index: true
end
def down
drop_table :day_frames
end
end
class CreateSessions < ActiveRecord::Migration[5.2]
def up
create_table :sessions do |t|
t.integer :number, limit: 1
t.string :title
t.string :short_title
t.boolean :is_active
t.timestamps
end
end
def down
drop_table :sessions
end
end
class CreateDayFramesSessions < ActiveRecord::Migration[5.2]
def up
create_join_table :day_frames, :sessions do |t|
t.index :day_frame_id
t.index :session_id
end
end
def down
drop_table :day_frames_sessions
end
end

Related

"TypeError: no implicit conversion of nil into String" on HABTM association

I have to deal with this error when I try to associate a record to another one via a HABTM association:
Person.first.communities = Communities.all
Models and migrations:
class CreatePeople < ActiveRecord::Migration
def change
create_table :people do |t|
t.string :name
t.string :email
t.timestamps null: false
end
end
end
class CreateCommunities < ActiveRecord::Migration
def change
create_table :communities do |t|
t.string :name
t.text :description
t.timestamps null: false
end
end
end
class CreateJoinTablePersonCommunity < ActiveRecord::Migration
def change
create_join_table :people, :communities do |t|
# t.index [:person_id, :community_id]
# t.index [:community_id, :person_id]
end
end
end
I use the pg (0.18.4) gem with the Postgres (9.5.2)
Youcan use below code to create relationship.
Person.first.communities << Communities.all
If this not works please check your associations via reflect association method on the model.

How to add database level foreign key in the migration file in rails 4.2?

I have gone through some of similar question people asked but couldn't find the appropriate solution for it. I have also seen some people using this method - add_foreign_key
class CreateTaskLists < ActiveRecord::Migration
def change
create_table :task_lists do |t|
t.string :name
t.references :user
t.timestamps
end
add_foreign_key :task_lists, :users
end
end
but it is throwing undefined method error.
undefined method `add_foreign_key' for
#<CreateTaskLists:0x007ffe9a5cd578>
/Users/sushilkumar/.rvm/gems/ruby-2.2.3/gems/
activerecord-4.0.0/lib/active_record/
migration.rb:624:in `block in method_missing'
How to add foreign key in rails migration with different table name
I don't know, How does this work for them?
You can simply try this way using references
class CreateTaskLists < ActiveRecord::Migration
def change
create_table :task_lists do |t|
t.string :name
t.references :user, index: true
t.timestamps
end
add_foreign_key :task_lists, :users
end
end
class CreateTaskLists < ActiveRecord::Migration
def change
create_table :task_lists do |t|
t.string :name
t.references :user, index: true
t.timestamps
end
add_foreign_key :task_lists, :users
end
end
try this
Did you meant to reference the table User and not Users? If so, you must use the singular (:user) when making a reference:
class CreateTaskLists < ActiveRecord::Migration
def change
create_table :task_lists do |t|
t.string :name
t.references :user
t.timestamps
end
add_foreign_key :task_lists, :users
end
end
Hope this will work for you.
class CreateTaskLists < ActiveRecord::Migration
def change
create_table :task_lists do |t|
t.string :name
t.references :user
t.timestamps
end
add_foreign_key :users, :task_lists
end
end

rails unable to index a foreign key

I have a two separate migration files:
class CreateLeadProfiles < ActiveRecord::Migration
def change
create_table :lead_profiles do |t|
t.belongs_to :Contact
t.timestamps
end
add_index :lead_profiles, :contact_id
end
end
and:
class CreateClientProfiles < ActiveRecord::Migration
def change
create_table :client_profiles do |t|
t.belongs_to :Contact
t.belongs_to :LeadProfile
t.timestamps
end
add_index :client_profiles, :contact_id
add_index :client_profiles, :lead_profile_id
end
end
when running rake db:migrate, I get the following error:
Mysql2::Error: Key column 'lead_profile_id' doesn't exist in table: CREATE INDEX `index_client_profiles_on_lead_profile_id` ON `client_profiles` (`lead_profile_id`)
client_profile belongs_to lead_profile, and so should have a lead_profile_id. And I want that foreign key to be indexed. What am I doing wrong?
Try:
class CreateClientProfiles < ActiveRecord::Migration
def change
create_table :client_profiles do |t|
t.belongs_to :contact
t.belongs_to :lead_profile
t.timestamps
end
add_index :client_profiles, :contact_id
add_index :client_profiles, :lead_profile_id
end
end

How to inherit from another Rails migration?

I have a Rails migration for a simple User model:
class Users < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name, :default => :null
t.float :weight
t.datetime :recorded_at
t.timestamps
end
end
end
I would like to have a second table for the history of the user. It should have the same columns but another name, obviously. Also it should reference the user table.
require_relative '20130718143019_create_history.rb'
class History < Users
def change
create_table :history do |t|
t.references :user
# ...?
end
end
end
How can use inheritence to avoid copying all the migration configuration?
After leaving the keyboard tomatoes fell off my eyes and it was clear how I can set this up:
class Users < ActiveRecord::Migration
def change
create_table :users do |t|
prepare_columns(t)
end
end
protected
def prepare_columns(t)
t.string :name, :default => :null
t.float :weight
t.datetime :recorded_at
t.timestamps
end
end
...
require_relative '20130718143019_create_history.rb'
class History < Users
def change
create_table :history do |t|
t.references :user
prepare_columns(t)
end
end
end

STI and has_many association with "type" column as Key

I am using Single Table Inheritance for managing different types of projects.
I decided to store some information associated with each project type. So i created new table "project_types" with "model_type" field as primary key. Primary key values are values of "type" field of "projects" table. Problem: When i trying to get associated with Project object ProjectTypes object it always returns null.
>> p = Project.find(:first)
=> #<SiteDesign id: 1, type: "SiteDesign", name: "1", description: "dddd", concept: "d", client_id: 40, created_at: "2009-10-15 08:17:45", updated_at: "2009-10-15 08:17:45">
>> p.project_type
=> nil
Getting projects associated with ProjectTypes project is OK. Is there way to make it works properly?
Models:
class Project < ActiveRecord::Base
belongs_to :project_type, :class_name => "ProjectTypes", :foreign_key => "model_name"
end
class SiteDesign < Project
end
class TechDesign < Project
end
class ProjectTypes < ActiveRecord::Base
self.primary_key = "model_name"
has_many :projects, :class_name => "Project", :foreign_key => "type"
end
Migrations:
class CreateProjectTypes < ActiveRecord::Migration
def self.up
create_table :project_types, :id => false do |t|
t.string :model_name , :null => false
t.string :name, :null => false
t.text :description
t.timestamps
end
add_index :project_types, :model_name, :unique => true
#all project types that are used.
models_names = {"SiteDesign" => "Site design",
"TechDesign" => "Tech design"}
#key for model_name and value for name
models_names.each do |key,value|
p = ProjectTypes.new();
p.model_name = key
p.name = value
p.save
end
end
def self.down
drop_table :project_types
end
end
class CreateProjects < ActiveRecord::Migration
def self.up
create_table :projects do |t|
t.string :type
t.string :name
t.text :description
t.text :concept
t.integer :client_id
t.timestamps
end
end
def self.down
drop_table :projects
end
end
Not surprising you're getting problems. By moving from a pure STI system to your current system you are horribly breaking the patterns you are using by intermingling parts of one with parts of another.
I'd personally go for something like:
class Project < ActiveRecord::Base
attr_readonly(:project_type)
belongs_to :project_type
before_create :set_project_type
def set_project_type()
project_type = ProjectType.find_by_model_name(this.class)
end
end
class SiteProject < Project
end
class TechProject < Project
end
class ProjectType < ActiveRecord::Base
has_many :projects
end
with migrations:
class CreateProjectTypes < ActiveRecord::Migration
def self.up
create_table :project_types do |t|
t.string :model_name , :null => false
t.string :name, :null => false
t.text :description
t.timestamps
end
add_index :project_types, :model_name, :unique => true
#all project types that are used.
models_names = {"SiteDesign" => "Site design",
"TechDesign" => "Tech design"}
#key for model_name and value for name
models_names.each do |key,value|
p = ProjectTypes.new();
p.model_name = key
p.name = value
p.save
end
end
def self.down
drop_table :project_types
end
end
class CreateProjects < ActiveRecord::Migration
def self.up
create_table :projects do |t|
t.string :type
t.references :project_type, :null => false
t.text :description
t.text :concept
t.integer :client_id
t.timestamps
end
end
def self.down
drop_table :projects
end
end
It just cleans things up and it also helps clarify what you're doing. Your 'ProjectType' table is purely for extra data, your inheritance tree still exists. I've also thrown in some checks to make sure your project type is always set (and correctly, based on the model name) and stops you from changing project type once it's been saved by making the attribute read only.

Resources