Loading data in a Rails migration - ruby-on-rails

I created number of migrations starting with a definition for a Posts table.
class CreatePosts < ActiveRecord::Migration
def self.up
create_table :posts do |t|
t.column "title", :string, :limit => 100, :default => "", :null => false
t.column "content", :text, :null => false
t.column "author", :string, :limit => 100, :default => 0, :null => false
t.column "category", :string, :limit => 20, :default => "", :null => false
t.column "status", :string, :limit => 20, :default => "", :null => false
t.timestamps
end
end
def self.down
drop_table :posts
end
end
And another one for a Users table in which I load some data for a default user after creating the table.
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.column "username", :string, :limit => 25, :default => "", :null => false
t.column "hashed_password", :string, :limit => 40, :default => "", :null => false
t.column "first_name", :string, :limit => 25, :default => "", :null => false
t.column "last_name", :string, :limit => 40, :default => "", :null => false
t.column "email", :string, :limit => 50, :default => "", :null => false
t.column "display_name", :string, :limit => 25, :default => "", :null => false
t.column "user_level", :integer, :limit => 3, :default => 0, :null => false
t.timestamps
end
user = User.create(:username => 'bopeep',
:hashed_password => 'bopeep',
:first_name => 'Bo',
:last_name => 'Peep',
:email => 'bo#peep.com',
:display_name => 'Little Bo Peep',
:user_level => 9)
end
def self.down
drop_table :users
end
end
Next I created a migration to alter the Posts table to rename the table to blog_posts. Here I also wanted to load a default blog post entry.
class AlterPosts < ActiveRecord::Migration
def self.up
rename_table :posts, :blog_posts
change_column :blog_posts, :author, :integer, :default => 0, :null => false
rename_column :blog_posts, :author, :author_id
add_index :blog_posts, :author_id
bopeep = User.find_by_username 'bopeep'
BlogPost.create(:title => 'test', :content => 'test', :author_id => bopeep.id, :category => 'test', :status => 'ok')
end
def self.down
remove_index :blog_posts, :author_id
rename_table :blog_posts, :posts
rename_column :posts, :author_id, :author
change_column :posts, :author, :string, :limit => 100, :default => 0, :null => false
end
end
But this generates an error:
uninitialized constant AlterPosts::BlogPost
How should I have loaded the default BlogPost instead of "BlogPost.create"?

Separate your rename_table and your change/rename column migrations into another migration file.
I don't think the rename is committed until after the entire block goes through... and so therefore blog_posts does not exist yet.

Related

undefined method `to_sym' for {:limit=>30, :string=>"Hint: ", :null=>false}:Hash

Why is it showing this error when i try to run rake db:migrate:
undefined method `to_sym' for {:limit=>30, :string=>"Hint: ", :null=>false}:Hash
Code:
def up
create_table :users do |t|
t.string "email", :limit => 50, :string => "Forgot password!", :null => false
t.column "password", :limit => 30, :string => "Hint: ", :null => false
:default
t.timestamps
end
end
this line may need to change..
t.column "password", :limit => 30, :string => "Hint: ", :null => false
by
t.string "password", :limit => 30, :string => "Hint: ", :null => false

two belongs_to same model assign id using name

I am new to RoR and am working on creating a database. Each host has two system admin. I am trying to associate the name given while creating a host with their respective system admin. How would I go about doing that?
If a user inputs the name of the system admin then how can I get the id using that name and insert that id into primary_sadmin_id field ?
Systemadmin.rb
class Systemadmin < ActiveRecord::Base
attr_accessible :id, :email, :location, :name, :netid, :priphone, :secphone
has_many :primary_sysadmin, :class_name => 'Host', :foreign_key => 'primary_sadmin_id'
has_many :seconday_sysadmin, :class_name => 'Host', :foreign_key => 'seconary_sadmin_id'
end
host.rb
class Host < ActiveRecord::Base
attr_accessible :iogroup, :ip, :location, :name, :opsystem, :primary_sadmin_id, :purpose, :secondary_sadmin_id, :host_type
belongs_to :primary_sadmin, :class_name => 'Systemadmin', :foreign_key => 'primary_sadmin_id'
belongs_to :secondary_sadmin, :class_name => 'Systemadmin', :foreign_key => 'secondary_sadmin_id'
end
host_controller.rb
def create
#host = Host.new(params[:host])
#host.primary_sadmin_id = Systemadmin.find_by_name(:sa_name1)
#host.secondary_sadmin_id = Systemadmin.find_by_name(:sa_name2)
respond_to do |format|
if #host.save
format.html { redirect_to #host, notice: 'Host was successfully created.' }
format.json { render json: #host, status: :created, location: #host }
else
format.html { render action: "new" }
format.json { render json: #host.errors, status: :unprocessable_entity }
end
end
end
schema.rb
create_table "hosts", :force => true do |t|
t.string "name"
t.integer "ip", :precision => 38, :scale => 0
t.string "location"
t.string "host_type"
t.string "opsystem"
t.string "iogroup"
t.integer "primary_sadmin_id", :precision => 38, :scale => 0
t.integer "secondary_sadmin_id", :precision => 38, :scale => 0
t.string "purpose"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "systemadmins", :force => true do |t|
t.string "name"
t.string "netid"
t.integer "priphone", :precision => 38, :scale => 0
t.integer "secphone", :precision => 38, :scale => 0
t.string "email"
t.string "location"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
Solved it using find_or_create_by_name.
class Host 'Systemadmin', :foreign_key => 'primary_sadmin_id'
belongs_to :secondary_sadmin, :class_name => 'Systemadmin', :foreign_key => 'secondary_sadmin_id'
has_many :database, :class_name => 'Host'
def sa_name1
primary_sadmin.try(:sa_name1)
end
def sa_name1=(sa_name1)
self.primary_sadmin = Systemadmin.find_or_create_by_name(sa_name1) if sa_name1.present?
end
def sa_name2
secondary_sadmin.try(:sa_name2)
end
def sa_name2=(sa_name2)
self.secondary_sadmin = Systemadmin.find_or_create_by_name(sa_name2) if sa_name2.present?
end
end

Thinking Sphinx: indexing error

ANSWERED:
set_primary_key "QTLID" in the model to tell model that pirmary ID is not ID
I am getting this error when I rake:ts index
Cannot automatically map attribute sphinx_internal_id in QtlTable to an
equivalent Sphinx type (integer, float, boolean, datetime, string as ordinal).
You could try to explicitly convert the column's value in your define_index
block:
has "CAST(column AS INT)", :type => :integer, :as => :column
I can't figure out how to fix this.
Here is my model (note I did not setup this database so don't jump on me for terrible conventions):
class QtlTable < ActiveRecord::Base
...
define_index do
indexes :QTLID
has :QTLName
end
end
Here is what schema looks like for qtl_table:
create_table "qtl_table", :primary_key => "QTLID", :force => true do |t|
t.string "QTLName", :limit => 60, :default => "", :null => false
t.string "Parent_1", :limit => 60, :default => "", :null => false
t.string "Parent_2", :limit => 60, :default => "", :null => false
t.string "Heritability", :limit => 60, :default => ""
t.text "Population_size", :limit => 16777215
t.string "Number_plants_bulked", :limit => 10
t.text "Pop_high_score", :limit => 16777215
t.text "Pop_low_score", :limit => 16777215
t.string "Loci_tested", :limit => 10, :default => ""
t.string "Intervals_associated", :limit => 10, :default => ""
t.string "Interval_length", :limit => 6, :default => ""
t.string "Interval_LOD_score", :limit => 12, :default => ""
t.string "Interval_P_value", :limit => 6, :default => ""
t.string "Interval_R2", :limit => 6, :default => ""
t.string "Genotypic_R2", :limit => 6, :default => ""
t.text "R2_Definition", :limit => 16777215
t.string "Percent_variation_explained", :limit => 6, :default => ""
t.string "First_entered", :limit => 60, :default => "", :null => false
t.string "Last_update", :limit => 60, :default => ""
t.string "TraitName", :limit => 100, :default => ""
t.binary "in_new", :limit => 1
end
add_index "qtl_table", ["QTLName"], :name => "QTLName_index"
add_index "qtl_table", ["TraitName"], :name => "TraitName_index"
ANSWERED:
set_primary_key "QTLID" in the model to tell model that pirmary ID is not ID
set_primary_key "QTLID" in the model to tell model that pirmary ID is not ID

with_scope raising "MySQL::Error Unkown column" error in RoR 2.3.11

Given this model in legacy code, with RoR 2.3.11:
class Assignment < ActiveRecord::Base
belongs_to :source_person
belongs_to :destination_person
belongs_to :laptop
def self.setScope(places_ids)
find_include = [:laptop => {:owner => {:performs => {:place => :ancestor_dependencies}}}]
find_conditions = ["place_dependencies.ancestor_id = (?)", places_ids]
scope = { :find => { :conditions => find_conditions, :include => find_include } }
Assignment.with_scope(scope) do
yield
end
end
end
Whenever it reaches the Assignment.with_scope statement, I get the following exception:
Assignment Delete all (0.0ms) Mysql::Error: Unknown column 'place_dependencies.ancestor_id' in 'where clause': DELETE FROM `assignments` WHERE (`id` IN (17)) AND (place_dependencies.ancestor_id = (1))
My schema looks like this:
create_table "assignments", :force => true do |t|
t.date "created_at"
t.date "date_assigned"
t.time "time_assigned"
t.integer "source_person_id"
t.integer "destination_person_id"
t.integer "laptop_id"
t.text "comment"
end
add_index "assignments", ["destination_person_id"], :name => "assignments_destination_person_id_fk"
add_index "assignments", ["laptop_id"], :name => "assignments_laptop_id_fk"
add_index "assignments", ["source_person_id"], :name => "assignments_source_person_id_fk
create_table "place_dependencies", :force => true do |t|
t.integer "descendant_id"
t.integer "ancestor_id"
end
add_index "place_dependencies", ["ancestor_id"], :name => "place_dependencies_ancestor_id_fk"
add_index "place_dependencies", ["descendant_id"], :name => "place_dependencies_descendant_id_fk"
I have almost the same code across multiple models, but everything works fine there. Could you give me a hint, on how to tackle this issue?
After doing the following it works:
def self.setScope(places_ids)
find_include = {
:laptop => {
:owner => {
:performs => {
:place => :ancestor_dependencies}
}
}
}
find_conditions = {"place_dependencies.ancestor_id" => places_ids}
Assignment.all :joins => find_include, :conditions => find_conditions
yield
end
This answer needs review from a more experienced Ruby on Rails developer.

counter cache doesn't update but I can save to the parent and the child

I added a counter cache but can't get it to update. But I can update the parent - the Blog Post model by adding a new blog post - and I can update the child - Comments model - by adding a new comment. The counter cache is supposed to keep track of the total number of comments per blog post by auto-updating the blog_posts.comments_count field. I'll outline some of the steps I went through and hopefully someone will notice something I did wrong. The schema dump is at the end.
I have a Blog Post model:
class Post < ActiveRecord::Base
set_table_name("blog_posts")
belongs_to :author, :class_name => "User", :foreign_key => 'author_id'
has_many :comments, :class_name => "Comment",
:foreign_key => 'post_id', :order => "created_at desc", :dependent => :destroy
has_many :categorizations
has_many :categories, :through => :categorizations
named_scope :recent, :order => "created_at desc", :limit => 5
end
and a Comments model with a counter_cache set to the post model:
class Comment < ActiveRecord::Base
belongs_to :post, :class_name => "Post", :foreign_key => "post_id", :counter_cache => true
belongs_to :author, :class_name => "User", :foreign_key => "author_id"
end
I created a migration to add the counter_cache column to the blog_posts table:
class AddCommentCounter < ActiveRecord::Migration
def self.up
add_column :blog_posts, :comments_count, :integer, :limit => 4, :default => 0, :null => false
Post.find(:all).each do |post|
current_count = post.comments.size
post.update_attribute(:comments_count, current_count)
end
end
def self.down
remove_column :blog_posts, :comments_count
end
end
But the migration fails to update the blog posts with the current_count. It's always zero.
I opened up the Rails console to try to update_attribute manually:
Loading development environment (Rails 2.3.2)
>> p = Post.find 1
p = Post.find 1
=> #<Post id: 1, title: "test", content: "test", author_id: 1, status: "ok", created_at: "2009-05-21 19:27:14", updated_at: "2009-05-24 07:02:35", comments_count: 0>
>> p.comments
p.comments
=> [#<Comment id: 5, post_id: 1, author_id: 1, content: "Fifth Comment", status: "ok", created_at: "2009-05-24 07:08:56", updated_at: "2009-05-24 07:08:56">, #<Comment id: 4, post_id: 1, author_id: 1, content: "Fourth Comment", status: "ok", created_at: "2009-05-24 07:05:32", updated_at: "2009-05-24 07:05:32">, #<Comment id: 3, post_id: 1, author_id: 1, content: "Third Comment", status: "ok", created_at: "2009-05-24 06:34:59", updated_at: "2009-05-24 06:34:59">, #<Comment id: 2, post_id: 1, author_id: 1, content: "Second Comment", status: "ok", created_at: "2009-05-24 05:20:43", updated_at: "2009-05-24 05:20:43">, #<Comment id: 1, post_id: 1, author_id: 1, content: "First Comment", status: "ok", created_at: "2009-05-21 19:27:14", updated_at: "2009-05-21 19:27:14">]
>> p.comments.size
p.comments.size
=> 5
>> p.comments_count
p.comments_count
=> 0
>> p.update_attribute(:comments_count, 5)
p.update_attribute(:comments_count, 5)
=> true
>> p.comments_count
p.comments_count
=> 5
>> p.save
p.save
=> true
But when I look in the database comments_count = 0.
Any ideas would be more than joyously appreciated.
My schema.db looks like this:
ActiveRecord::Schema.define(:version => 20090524055907) do
create_table "blog_posts", :force => true do |t|
t.string "title", :limit => 100, :default => "", :null => false
t.text "content", :null => false
t.integer "author_id", :default => 0, :null => false
t.string "status", :limit => 20, :default => "", :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "comments_count", :default => 0, :null => false
end
add_index "blog_posts", ["author_id"], :name => "index_blog_posts_on_author_id"
create_table "categories", :force => true do |t|
t.string "name", :limit => 50, :default => "", :null => false
t.string "short_name", :limit => 30, :default => "", :null => false
t.string "description", :default => "", :null => false
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "categories_posts", :force => true do |t|
t.integer "category_id", :null => false
t.integer "post_id", :null => false
end
add_index "categories_posts", ["category_id"], :name => "index_categories_posts_on_category_id"
add_index "categories_posts", ["post_id"], :name => "index_categories_posts_on_post_id"
create_table "comments", :force => true do |t|
t.integer "post_id", :default => 0, :null => false
t.integer "author_id", :default => 0, :null => false
t.text "content", :null => false
t.string "status", :limit => 25, :default => "", :null => false
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "sessions", :force => true do |t|
t.string "session_id", :default => "", :null => false
t.text "data"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
create_table "users", :force => true do |t|
t.string "username", :limit => 25, :default => "", :null => false
t.string "hashed_password", :limit => 40, :default => "", :null => false
t.string "first_name", :limit => 25, :default => "", :null => false
t.string "last_name", :limit => 40, :default => "", :null => false
t.string "email", :limit => 50, :default => "", :null => false
t.string "display_name", :limit => 25, :default => "", :null => false
t.integer "user_level", :limit => 3, :default => 0, :null => false
t.datetime "created_at"
t.datetime "updated_at"
end
end
Take a look at the updated code from railscasts episode 23 on counter_cache.
The counter attributes are attr_readonly. Perhaps update-counters is what you need to use in place of update attributes in your migration?

Resources