Rails: Some seeds don't appear to be saving - ruby-on-rails

It appears some of my seeds are not saving. For starters, I will show a console session so you can see that the 'instructor_id' is indeed being set in the console, but not when I seed.
ruby-1.9.2-p180 :015 > c = Course.find 2
Course Load (1.6ms) SELECT "courses".* FROM "courses" WHERE "courses"."id" = $1 LIMIT 1 [["id", 2]]
=> #<Course id: 2, name: "Microcomputers II Lab", course_code: "CE-420L", instructor_id: nil, school_id: nil, created_at: "2011-06-04 19:40:32", updated_at: "2011-06-04 19:40:32">
ruby-1.9.2-p180 :016 > c.instructor = Instructor.first
Instructor Load (0.6ms) SELECT "instructors".* FROM "instructors" LIMIT 1
=> #<Instructor id: 1, name: "Instructor Name", created_at: "2011-06-04 19:40:32", updated_at: "2011-06-04 19:40:32">
ruby-1.9.2-p180 :017 > c
=> #<Course id: 2, name: "Microcomputers II Lab", course_code: "CE-420L", instructor_id: 1, school_id: nil, created_at: "2011-06-04 19:40:32", updated_at: "2011-06-04 19:40:32">
From looking at the console, you can see that when I call c.instructor = Instructor.first, it is correctly setting my instructor_id.
Now, in the seeds file I have variables. (This is just a snippet)
### Instructors ###
puts "Creating Instructors"
instructor_1 = Instructor.find_or_create_by_name("Instructor Name")
### Courses ###
puts "Creating Courses"
ce420L = Course.find_or_create_by_name("Microcomputers II Lab", :course_code => "CE-420L")
### Add the Instructor to the Course ###
puts "Adding an Instructor to the Courses"
ce420L.instructor = instructor_1
But when I run the seeds using 'rake db:seed', it is correctly creating all of my models, and most of my relationships. But it is not setting the instructor properly.
Thoughts?
EDIT:
Just tried:
ce420 = Course.find_or_initialize_by_name("Microcomputers II")
ce420.instructor_id = instructor_1.id
ce420.save!
And it did not save my instructor.
Here are my models.
class Instructor < ActiveRecord::Base
### ASSOCIATIONS ###
has_many :courses
end
class Course < ActiveRecord::Base
belongs_to :instructor
end

Did you run...
ce420L.save!
... after assigning the instructor?

Much faster to do this:
### Courses ###
puts "Creating Courses belonging to Instructor 1"
ce420L = Course.find_or_initialize_by_name("Microcomputers II Lab") :course_code => "CE-420L")
ce420L.instructor_id = instructor_1.id
ce420L.save
Note the following:
You had an errant comma after your find_or_create on ce420L.
Doing the assignment together with the course creation prevents the system from validating and saving ce420L twice.
You can try assigning the specific ID as I did, i.e. ce420L.instructor_id = ...
If this doesn't work, check your Instructor Model to ensure you don't have any callbacks getting in the way.

Related

Could not find_by an object from database in Rails job

I have created a Ruby on Rails job (extending from ActiveJob::Base) that parses a CSV file and inserts its rows as records (Students) in a database. That is working as expected.
However, when I try to fetch another object from the DB (the Career for each Student, which is part of each CSV row as a pair (career_code, career_name)), I'm getting this error:
undefined method 'find_by' for Career:Class
(I have also tried using Career.where instead).
I find this quite strange, since I'm already saving my Student, which is also an ActiveRecord::Base child class.
Here's the relevant part of my job:
ActiveRecord::Base.transaction do
student_hash.keys.each do |k|
some_student = student_hash[k]
student = Student.new
student.csv_id = some_student.id
student.first_name = some_student.first_name
student.last_name = some_student.last_name
student.file_number = some_student.file_number
# student.career = Career.where(code: some_student.career_code)
student.career = Career.find_by code: some_student.career_code
puts student.save! # Why this works, and the above line doesn't?
end
end
And also, the desired output, as I can see it in the Rails console:
Loading development environment (Rails 4.2.4.rc1)
2.1.3 :001 > Career.where(code: 11)
Career Load (0.5ms) SELECT "careers".* FROM "careers" WHERE "careers"."code" = ? [["code", 11]]
=> #<ActiveRecord::Relation [#<Career id: 4, name: "Informática", created_at: "2015-09-30 22:05:07", updated_at: "2015-09-30 22:05:07", code: 11>]>
2.1.3 :002 > Career.where code: 11
Career Load (0.2ms) SELECT "careers".* FROM "careers" WHERE "careers"."code" = ? [["code", 11]]
=> #<ActiveRecord::Relation [#<Career id: 4, name: "Informática", created_at: "2015-09-30 22:05:07", updated_at: "2015-09-30 22:05:07", code: 11>]>
2.1.3 :003 > Career.find_by code: 11
Career Load (0.4ms) SELECT "careers".* FROM "careers" WHERE "careers"."code" = ? LIMIT 1 [["code", 11]]
=> #<Career id: 4, name: "Informática", created_at: "2015-09-30 22:05:07", updated_at: "2015-09-30 22:05:07", code: 11>
2.1.3 :004 >
Probably this is a really stupid question, but I'm quite a beginner using Rails. Do I need to import some sort of "Context" (this seems unlikely, since Student seems to be properly resolved)? I'm using Rails 4.2.4.rc1 by the way.
Thanks in advance
Any chance at that point in the code Career isn't an AR, but some other class? That would at least explain why the methods don't exist.

Ruby on Rails: weird behavior in new, un-persisted model

I'm at a loss. We have two classes, Sample and Workflow, that have a many-to-many relationship, using has_many, :through.
At Rails Console, I get the following:
[3] pry(main)> s = Sample.find(1)
Sample Load (0.2ms) SELECT `samples`.* FROM `samples` WHERE `samples`.`id` = 1 LIMIT 1
=> #<Sample id: 1, name: "Some sample", experiment_type: "Some type", category_id: nil,
created_at: "2014-01-14 21:24:14", updated_at: "2014-01-14 21:24:14">
[4] pry(main)> wf = Workflow.new
=> #<Workflow id: nil, name: nil, description: nil>
[5] pry(main)> wf.samples.include?(s)
Sample Exists (0.2ms) SELECT 1 AS one FROM `samples` INNER JOIN `sample_workflows` ON
`samples`.`id` = `sample_workflows`.`sample_id` WHERE `sample_workflows`.`workflow_id` IS NULL
AND `samples`.`id` = 1 LIMIT 1
=> true
[6] pry(main)> wf.samples
=> []
[7] pry(main)> wf.samples.include?(s)
=> false
wf is a brand new workflow, should not have any samples attached to it. wf.samples.include? indicates that sample 1 is already linked to the workflow. But if I try to look at the samples, the array comes back blank, and further include? queries return false (as they should). The same thing happens for sample 2, but not for any others I've tried. Is there some way I could have made the workflow link to two samples by default by mistake?

How to show values of a instance with line break in Rails console

I start to using pry in a rails console.
When I get a instance of a Rails model, the values are shown without line breaks like this:
pry(#<Class:0x1022f60e0>):1> first
=> #<Article id: 1, name: "What is Music", content: "Music is an art form in which the medium is sound o...", created_at: "2011-08-24 20:35:29", updated_at: "2011-08-24 20:37:22", published_at: "2011-05-13 23:00:00">
from http://railscasts.com/episodes/280-pry-with-rails?view=asciicast
Is there way to show the values with line breaks like this?
Article
id: 1
name: "What is Music"
content: "Music is an art form in which the medium is sound o..."
created_at: "2011-08-24 20:35:29"
updated_at: "2011-08-24 20:37:22"
published_at: "2011-05-13 23:00:00"
You could call .to_yaml on the model instance! It returns a string that's formatted almost exactly like you're requesting it to be.
Here are some examples of to_yaml output:
http://yaml4r.sourceforge.net/doc/page/examples.htm
I would recommend that you install awesome_print.
Add it to your Gemfile:
group :development do
gem 'awesome_print'
end
And install it with bundle install.
Now use ap to print it in the console:
pry(#<Class:0x1022f60e0>):1> ap first
#<Article:0x1022f60e0> {
:id => 1,
:name => "What is Music"
:content => "Music is an art form in which the medium is sound o..."
:created_at => "2011-08-24 20:35:29"
:updated_at => "2011-08-24 20:37:22"
:published_at => "2011-05-13 23:00:00"
}
I think, the below trick will work for you.
arup#linux-wzza:~/Rails/model_prac> rails c
Loading development environment (Rails 4.1.4)
2.1.2 :001 > Comment.first
Comment Load (0.4ms) SELECT "comments".* FROM "comments" ORDER BY "comments"."id" ASC LIMIT 1
=> #<Comment id: 1, value_old: "I am a good Boy.", value_new: "I am a bad Boy.", created_at: "2014-08-02 17:36:14", updated_at: "2014-08-02 18:21:42">
2.1.2 :002 > y Comment.first
Comment Load (0.4ms) SELECT "comments".* FROM "comments" ORDER BY "comments"."id" ASC LIMIT 1
--- !ruby/object:Comment
attributes:
id: 1
value_old: I am a good Boy.
value_new: I am a bad Boy.
created_at: 2014-08-02 17:36:14.249466000 Z
updated_at: 2014-08-02 18:21:42.511522000 Z
=> nil
2.1.2 :003 >

Active Record has_many generates sql with foreign key IS NULL

I don't expect a model with NULL as foreign key to belong to anything!
I have the following rails app, modelling ants and ant hills (inspired by Jozef).
$ rails -v
Rails 3.2.8
$ rails new ant_hill
$ cd ant_hill
Create the ant hill and ant models. An ant can belong to an ant hill and an ant hill can have many ants.
$ rails generate model AntHill name:string
$ rails generate model Ant name:string ant_hill_id:integer
$ vim app/models/ant.rb
$ cat app/models/ant.rb
class Ant < ActiveRecord::Base
belongs_to :ant_hill
end
$ vim app/models/ant_hill.rb
$ cat app/models/ant_hill.rb
class AntHill < ActiveRecord::Base
has_many :ants
end
$ rake db:migrate
== CreateAntHills: migrating =================================================
-- create_table(:ant_hills)
-> 0.0013s
== CreateAntHills: migrated (0.0016s) ========================================
== CreateAnts: migrating =====================================================
-- create_table(:ants)
-> 0.0035s
== CreateAnts: migrated (0.0037s) ============================================
Run the following code in a console.
$ rails c
Loading development environment (Rails 3.2.8)
Create a couple of ants, persisted, that don't belong to any ant hill.
1.9.2-p290 :001 > Ant.create! name: "August"
=> #<Ant id: 1, name: "August", ant_hill_id: nil, created_at: "2012-09-27 12:01:06", updated_at: "2012-09-27 12:01:06">
1.9.2-p290 :002 > Ant.create! name: "Bertil"
=> #<Ant id: 2, name: "Bertil", ant_hill_id: nil, created_at: "2012-09-27 12:01:13", updated_at: "2012-09-27 12:01:13">
Now instantiate an ant hill, but don't save it just yet.
1.9.2-p290 :003 > ant_hill = AntHill.new name: "Storkullen"
=> #<AntHill id: nil, name: "Storkullen", created_at: nil, updated_at: nil>
I expect this ant hill to not have any ants and it doesn't.
1.9.2-p290 :004 > ant_hill.ants
=> []
I still expect the ant hill to not have any ants but now it has two.
1.9.2-p290 :005 > ant_hill.ants.count
(0.1ms) SELECT COUNT(*) FROM "ants" WHERE "ants"."ant_hill_id" IS NULL
=> 2
Same here, it should never generate a query containing "IS NULL" when dealing with foreign keys. I mean "belongs_to NULL" can't belong to anything, right?
1.9.2-p290 :006 > ant_hill.ants.all
Ant Load (0.4ms) SELECT "ants".* FROM "ants" WHERE "ants"."ant_hill_id" IS NULL
=> [#<Ant id: 1, name: "August", ant_hill_id: nil, created_at: "2012-09-27 12:01:06", updated_at: "2012-09-27 12:01:06">, #<Ant id: 2, name: "Bertil", ant_hill_id: nil, created_at: "2012-09-27 12:01:13", updated_at: "2012-09-27 12:01:13">]
After it is persisted it behaves as expected.
1.9.2-p290 :007 > ant_hill.save!
=> true
1.9.2-p290 :008 > ant_hill.ants.count
(0.4ms) SELECT COUNT(*) FROM "ants" WHERE "ants"."ant_hill_id" = 1
=> 0
1.9.2-p290 :009 > ant_hill.ants.all
Ant Load (0.4ms) SELECT "ants".* FROM "ants" WHERE "ants"."ant_hill_id" = 1
=> []
Any insight? Is this the expected behavior?
While it seems counterintuitive, I think this behavior makes sense given your examples. Take ant_hill.ants.count for example. Count is an ActiveRecord query method that hits the database, and you're essentially asking ActiveRecord to give you all the ants that do not belong to an ant hill. Rails is simply letting you do something you should not be able to do, and not complaining about it. Should this be raising an exception instead? Possibly.
If you really want to know how many ants belong to this ant_hill object, you should be using size. It queries the object when not persisted or when the association is already loaded, and queries the database otherwise.
ant_hill.ants.size
One way you can get around this oddity is to make ant_hill_id a required field by validating its presence.
TL;DR Avoid using ActiveRecord query interface if parent object is not persisted to database.

Ruby on rails: virtual method that modifiyng model attributes with help of << couldn't save that attribute

There is model Ratification with attribute comment (of type text)
def Ratification < ActiveRecord::Base
attr_accessor :add_comment
def add_comment=(text)
self.comment ||= ""
self.comment << "\r\n" + text
end
end
And if I use add_comment= it is ok before I save the object. After save comment changes was dropped.
>> r = Ratification.last
Ratification Load (0.6ms) SELECT * FROM `ratifications` ORDER BY ratifications.id DESC LIMIT 1
=> #<Ratification id: 8, user_id: 686, comment: "dasads", created_at: "2010-06-25 13:16:24", updated_at: "2010-06-25 13:38:36">
>> r.comment
=> "dasads"
>> r.add_comment="text"
=> "text"
>> r.comment
=> "dasads\r\ntext"
>> r.save
SQL (0.7ms) BEGIN
SQL (0.2ms) COMMIT
=> true
>> r.reload
Ratification Load (1.6ms) SELECT * FROM `ratifications` WHERE (`ratifications`.`id` = 8)
=> #<Ratification id: 8, user_id: 686, comment: "dasads", created_at: "2010-06-25 13:16:24", updated_at: "2010-06-25 13:38:36">
>> r.comment
=> "dasads"
Why?!
Rails 2.3.8
Ruby 1.8
Hrrrm...that IS weird, I'm seeing similar behavior from my rails app when I try to do:
#s.name << "test"
and then reload...the original name is getting reset!
HOWEVER, if I do #s.name += "test"
then even after reloading, the new name is saved.
I'm not sure why << is behaving like that, but I usually default to += in all cases, so I've never noticed it before. Does changing to += help you?
Edit: Looking at the API, maybe it's because << modifies the original string, whereas + or += makes a NEW string, that contains the old one? Maybe rails somehow only saves things that it has marked as new (rather than modified?)

Resources