How to migrate with data update on *one time* joined columns? - ruby-on-rails

I'm adding a new association to existing models with existing data in a Rails 3.2.x + AR project.
The Migration script:
class AddUserToSignups < ActiveRecord::Migration
def up
add_column :signups, :user_id, :integer, :default => nil
add_index :signups, :user_id
# UPDATE SIGNUPS S JOIN USERS U ON S.EMAIL=U.EMAIL SET S.USER_ID = U.ID
end
def down
drop_column :signups, :user_id
end
end
How do I do a joined update per the comment above with AR? I come from a Sequel ORM background, so Sequel's approach would be:
DB[:signups___s].join(:users___u, :u__id => :s__user_id).update(:s__user_id => :u__id)

def up
add_column :signups, :user_id, :integer, :default => nil
add_index :signups, :user_id
ActiveRecord::Base.connection.execute("UPDATE SIGNUPS S JOIN USERS U ON S.EMAIL=U.EMAIL SET S.USER_ID = U.ID")
end

Related

Has_and_belongs_to same model

I have and User model that will need to 'own' itself. Thats because the only way to a user connect with another is if they have this 'bound'.
So... I created a 'join model':
class CreateUserConnections < ActiveRecord::Migration
def change
create_table :user_connections, id: false do |t|
t.string :token
t.integer :user_a_id, :null => false
t.integer :user_b_id, :null => false
t.timestamps
end
add_index :user_connections, :token, unique: true
add_index :user_connections, [:user_a_id, :user_b_id], unique: true
end
end
and
class UserConnection < ActiveRecord::Base
belongs_to :user
belongs_to :user_a, :class_name => 'User'
belongs_to :user_b, :class_name => 'User'
before_create :generate_token
protected
def generate_token
self.token = loop do
random_token = SecureRandom.urlsafe_base64(nil, false)
break random_token unless UserConnection.exists?(token: random_token)
end
end
end
and then created the relation on my user model:
#unlocked users
has_and_belongs_to_many :users,
:join_table => "user_connections",
:foreign_key => "user_a_id",
:association_foreign_key => "user_b_id"
The problem is that when I create a relation with a user like:
User.find(1).users << User.find(2)
It creates the own relation from User 1 to User 2, but I tought that with the many_to_many relation the ownership relation from user 2 to 1 would be automatic.
What I'm missing here?
Thanx in advance
I should create the reverse realationship by myself.

rails migration copy and remove table

I have user model and user model has_one profile model.
Also I have user.phone and user.profile.phone but I want to remove user.phone and I will use only user.profile.phone.
Before I remove the user.phone,I wanna copy user.phone to user.profile.phone if user.phone is not blank.Then I will remove user.phone
For instance:
user.phone = 123
user.profile.phone = 234
After migration:
user.phone will be removed
user.profile.phone = 123 - 234
What is the appropriate migration for this purpose?
try this
class YourMigration < ActiveRecord::Migration
def self.up
User.find_each do |user|
user.profile.update_attributes(:phone => user.phone) unless user.phone.blank?
end
remove_column :users, :phone
end
def self.down
add_column :users, :phone, :string
end
end
If your database is not very large you can simply do like this:
User.includes(:profile).all.each{ |u| u.profile.phone = u.phone unless u.phone.nil? }
in your console. Or you can write smth like this in your migration:
def change
User.includes(:profile).all.each{ |u| u.profile.phone = u.phone unless u.phone.nil? }
remove_column :users, :phone
end
class YourMigration < ActiveRecord::Migration
def self.up
User.where("phone IS NOT NULL").includes(:profiles).each{ |u| u.profile.phone = u.phone}
remove_column :users, :phone
end
def self.down
add_column :users, :phone, :string
end
end
I prefer not to use Model in migration because it creates unnecessary pain:
Assume many people working on same project and you use model in migration do commit. Other person delete the user model or applies some validation on model and dos the commit. When he or other tries to run the migrations, it may fail because the model you used is not exists or some validation.
So I recommend to use SQL statements in migration.
class SomeMigartion < ActiveRecord::Migration
def self.up
execute('update profiles p inner join users u on p.user_id = u.id set p.phone = u.phone where u.phone is not null')
remove_column :users, :phone
end
def self.down
add_coulmn :users, :phone
end
end

Active Record query

I have two models ForumThread and Post set-up like this:
class ForumThread < ActiveRecord::Cached
has_many :posts
end
class Post < ActiveRecord::Cached
end
class CreateForumThreads < ActiveRecord::Migration
def self.up
create_table :forum_threads do |t|
t.column :thread_name, :text
end
add_index :forum_threads, :thread_name
end
def self.down
drop_table :forum_threads
end
end
class CreatePosts < ActiveRecord::Migration
def self.up
create_table :posts do |t|
t.column :post_body, :text
t.integer :forum_thread_id, :null => false
t.integer :priority
end
end
def self.down
drop_table :posts
end
end
I'd like to create a query that returns all forum threads where there's at least one post in each thread with priority of one. How do I create this query?
I've been considering something like ForumThread.joins(:posts).select(:priority => 1). I'm relatively new to Active Record (and totally new to joins) so any help is appreciated.
ForumThread.joins(:posts).where(:posts => {:priority => 1})
see join with conditions
First of all you should rename thread_id field to forum_thread_id in posts table and add posts_count to forum_threads table.
In Post class add belongs_to :forum_thread, :counter_cache => true
Now you can query ForumThread.where("posts_count > ?", 1).joins(:posts).where("posts.priority = ?", 1) which will return you a collection of posts.

rails generate migration command to insert data into the table

I have a table and I had to add a migration script to add rows in the table.
Please help with the rails generate migration command to insert data into the table.
Thanks,
Ramya.
You can write regular ruby code inside a migration. So you can simply do something like this:
class Foo < ActiveRecord::Migration
def self.up
User.create(:username => "Hello", :role => "Admin")
end
def self.down
User.delete_all(:username => "Hello")
end
end
Just write regular ruby inside your migration same as you would in pry or rails console.
The code helped me is the sql statement as show
In migration file
def up
execute("insert into salary_ranges(salary_range) values('Above 2000');")
end
class AddFieldInUsers < ActiveRecord::Migration
def self.up
add_column :users, :admin, :boolean, :null => false, :default => 0
end
def self.down
remove_column :users
end
end

Rails Beginner Attempting TDD:

I'm new to unit testing and Rails in general. I've decided to build my projects in a TDD environment, but this has left me with some early questions.
I need help building the models to pass this test:
describe User do
it "should add user to team" do
team = Team.create(:name => "Tigers")
akash = User.create(:name => "Akash")
akash.teams << team
akash.memberships.size.should == 1
end
it "should allow buddyup"
john = User.create(:name => "John")
john.buddyup_with(akash)
john.memberships.size.should == 1
end
it "should validate linked buddys"
akash.buddys.should include(john)
end
end
Basically, ALL I want to do right now is pass the tests. Here is what I have so far:
class Team < ActiveRecord::Base
has_and_belongs_to_many :users
attr_accessubke :name
validates :name, :presence = true
:uniqueness => true
end
class User < ActiveRecord::Base
has_and_belongs_to_many: :teams
attr_accessible :name
validates :name, :presence = true
:uniqueness => true
end
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :users
end
end
class CreateTeams < ActiveRecord::Migration
def self.up
create_table :teams do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :teams
end
end
class CreateTeamsUsersJoinTable < ActiveRecord::Migration
def self.up
create_table :teams_users, :id => false do |t|
t.integer :team_id
t.integer :user_id
end
end
def self.down
drop_table :teams_users
end
end
That is all I have so far, and clearly it is nowhere near completion. Could you provide some insight, and perhaps code I should use to complete this? My biggest problem right now is the buddyup_with part. Adding a buddy will add a person to every team you are a member of, think of teams as parts of a development company, and buddys as understudies or something.
Suggestions I would make:
Use before do
# code #
end
to set up your conditions.
Do 1 test per. You have a lot going on there :)
Use Factory Girl.
Try what you have and work from there (Agile approach, even to adding tests).

Resources