I have two classes: Schedule and Interaction and they look the following:
class Schedule < ActiveRecord::Base
has_many :interactions
end
class Interaction < ActiveRecord::Base
attr_accessible :schedule_id
has_one :schedule
end
The migrations look like this:
class CreateSchedules < ActiveRecord::Migration
def change
create_table :schedules do |t|
t.timestamps
end
end
end
class CreateInteractions < ActiveRecord::Migration
def change
create_table :interactions do |t|
t.integer :schedule_id
t.timestamps
end
end
end
When I do this:
irb(main):003:0> interaction_high_1 = Interaction.create()
irb(main):003:0> interaction_high_2 = Interaction.create()
irb(main):003:0> interaction_high_3 = Interaction.create()
irb(main):003:0> interaction_high_4 = Interaction.create()
irb(main):003:0> interaction_high_5 = Interaction.create()
irb(main):003:0> schedule1 = Schedule.create(:name => "high1").interactions << interaction_high_1, interaction_high_2, interaction_high_3, interaction_high_4, interaction_high_5
only Interaction_high_1 gets the designated schedule_id and for the rest it's just nul
Can anybody tell me why this is and how I might fix it?
Thanks for an answer!!
You are creating the Interactions without associating them to a Schedule. Just appending them later won't do what you need. Do it like this instead:
schedule1 = Schedule.create(:name => "high1")
1...5.times do
schedule1.interactions.create
end
Also, change the :has_one in the Interaction model to a :belongs_to.
Related
I would like to know how we can scope a Post with his association table ?
I explain what I want to do it will be more clear. I actually have a scaffold :ranch, and a scaffold :staff. And when I create a new Staff, I can choose to associated it with many ranches. So I have an other table to reference this association :ranch_staff.
So if I want to scope the staff to display only which are associated with the actual #ranch, how can I do that ?
Something like this should do the trick:
migration:
class Init < ActiveRecord::Migration
def change
create_table :ranches do |t|
t.string "name"
end
create_table :staffs do |t|
t.string "name"
end
create_table :ranches_staffs, id: false do |t|
t.belongs_to :ranch
t.belongs_to :staff
end
end
end
app/models/staff.rb:
class Staff < ActiveRecord::Base
has_and_belongs_to_many :ranches
end
app/models/ranch.rb:
class Ranch < ActiveRecord::Base
has_and_belongs_to_many :staffs
end
run in rails console:
staff1 = Staff.create(name: "staff1")
staff2 = Staff.create(name: "staff2")
staff3 = Staff.create(name: "staff3")
staff4 = Staff.create(name: "staff4")
ranch1 = Ranch.create(name: "ranch1")
ranch2 = Ranch.create(name: "ranch1")
staff1.ranches << ranch1
staff2.ranches << ranch1
staff3.ranches << ranch2
staff4.ranches << ranch2
Now you can access ranch1's staff by
ranch1.staffs
=> #<ActiveRecord::Associations::CollectionProxy [#<Staff id: 1, name: "staff1">, #<Staff id: 2, name: "staff2">]>
See association.
My models are:
class CarBrand < ActiveRecord::Base
has_many :car_models
end
class CarModel < ActiveRecord::Base
belongs_to :car_brand
end
and my migrations are
class CreateCarBrands < ActiveRecord::Migration
def up
create_table :car_brands do |t|
t.string "brand", :limit => 20
t.timestamps null: false
end
end
def down
drop_table :car_brands
end
end
class CreateCarModels < ActiveRecord::Migration
def up
create_table :car_models do |t|
t.references :car_brand
t.string "model", :limit => 20
t.timestamps null: false
end
add_index :car_models, :car_brand_id
end
def down
drop_table :car_models
end
end
and i want to get car models according to specific car brand, in database i have both records, but when i type in console it gives error
somecar = CarBrand.where(:brand => 'Toyota')
somecar.car_models
so it doesn't returns me models of toyota, but i have them in database!!!
somecar = CarBrand.where(:brand => 'Toyota') returns an active record relation #<ActiveRecord::Relation [#<..... the main point is that it is a collection. You have to iterate over each item in the collection.
some_cars = CarBrand.where(:brand => 'Toyota')
some_cars.each do |car| puts car.car_model end
or on the first item some_cars.first.car_model
Notice I changed some_car to some_cars, the name of the variable does matter but it is easier to see that it is a collection. Notice I called .car_model (and NOT car_models) on each item, that really is important.
Try like that:-
somecar = CarBrand.where(:brand => 'Toyota')
somecar.first.car_models
As CarBrand.where(:brand => 'Toyota') returns an array.
OR
Try like that:-
somecar = CarBrand.find_by brand: 'Toyota'
somecar.car_models
CarBrand.find_by brand: 'Toyota' will fetch first matching record.
Here are my migrations:
class CreateTests < ActiveRecord::Migration
def change
create_table :tests do |t|
t.string :value
t.timestamps
end
end
end
class CreateQuestions < ActiveRecord::Migration
def change
create_table :questions do |t|
t.string :title
t.timestamps
end
end
end
class CreateQuestionsTests < ActiveRecord::Migration
def change
create_table :questions_tests do |t|
t.integer :test_id
t.integer :question_id
t.timestamps
end
end
end
Now in the rails console I created a test object and a question object
test = Test.create(value: "10")
question = Question.create(title: "blablabla")
If now I do test.questions.create(question_id: question.id) I get the following error:
ActiveRecord::UnknownAttributeError: unknown attribute: question_id
How is that?
If you are using has_and_belongs_to_many relationship, you must to have relation table without id and stamps
class CreateQuestionsTests < ActiveRecord::Migration
def change
create_table :questions_tests, :id => false do |t|
t.integer :test_id
t.integer :question_id
end
end
end
I guess that you want to do a Rich association here, if so you should declare relations in your models like this :
Test.rb
class Test < ActiveRecord::Base
has_many :questions_tests
has_many :questions, :through => :questions_tests # here you tell rails that your Test model has many questions if you go through questions_tests
end
Question.rb
class Question < ActiveRecord::Base
has_many :questions_tests
has_many :tests, :through => :questions_tests # here you tell rails that your Question model has many tests if you go through questions_tests
end
QuestionTest.rb
class QuestionTest < ActiveRecord::Base
belongs_to :test
belongs_to :question
end
with this you can traverse the associations table (questions_tests) directly like you want : test.questions.create(question_id: question.id), and you have also this possibility :
test = Test.create(value: "10")
question = Question.create(title: "blablabla")
test.questions_tests << question # or question.questions_tests << test
In one model, I have this:
class Game < ActiveRecord::Base
has_one :turn
attr_accessor :turn
attr_accessible :turn
default_scope :include => :turn
def Game.new_game
turn = Turn.create count: 1, phase: 'upkeep', player: 1
game = Game.create turn: turn
game
end
end
class Turn < ActiveRecord::Base
belongs_to :game
end
Later, in a controller, I have this:
respond_with Game.find(params[:id])
But for some reason, the returned game has a turn_id that is nil and no associated turn object.
Why isn't the association being saved properly, or not returning properly with find()?
In my migration, I think I've setup the association correctly:
create_table :games do |t|
t.timestamps
end
def change
create_table :turns do |t|
t.string :phase
t.integer :count
t.references :game
t.timestamps
end
end
You seemed to have got messed up on associations
This is what i Think as per the understanding of scenario.
The associations should be like
class Game < ActiveRecord::Base
has_one :turn
#.....
end
class Turn < ActiveRecord::Base
belongs_to :game
#.....
end
and migrations like
create_table :games do |t|
#add some columns
t.timestamps
end
create_table :turns do |t|
t.references :game
#add some columns
t.timestamps
end
now to add new game and turn
game = Game.create
turn = game.turn.create count: 1, phase: 'upkeep', player: 1
game.tun.create will automatically create a turn record with game_id = game.id and other supplied args.
problem with your migration is game is referring turn which instead should be opposite .
Find more on associations here
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
http://guides.rubyonrails.org/association_basics.html
Something is inverted.
Since Turn has the belongs_to statement, Turn should contain game_id, and not the other way around.
So you can't access a Game turn_id because the field does not exists. It will be always nil and if ou remove the has_one statement it will raise an exception.
Okay so what I have is a table that keeps track of history on a "person", this logs the person(User), the handler(User), the status before(JobApplicationStatus), the status after(JobApplicationStatus).
Now in my head this translates down to a table of such:
**JobApplicationHistory**
id (int)
status_before_id (int)
status_after_id (int)
user_id (int)
handler_id (int)
I tried to make a migation, that sorta worked, but it's not working right.
As I would like to use something like:
user = User.find(1)
handler = User.find(1)
status_before = JobApplicationStatus.find(1)
status_after = JobApplicationStatus.find(2)
history = JobApplicationHistory.new()
history.user = user
history.handler = handler
history.status_before = status_before
history.status_after = status_after
history.save
Here is my migration
class CreateUserApplicationHistories < ActiveRecord::Migration
def self.up
create_table :user_application_histories do |t|
t.integer :user_id # goes to User
t.references :job # goes to Job
t.integer :handler_id # goes to User
t.integer :status_from_id # goes to JobApplicationStatus
t.integer :status_to_id # goes to JobApplicationStatus
t.timestamps
end
add_index("user_application_histories", "job_id")
add_index("user_application_histories", "handler_id")
add_index("user_application_histories", "user_id")
add_index("user_application_histories", "status_from_id")
add_index("user_application_histories", "status_to_id")
end
def self.down
drop_table :user_application_histories
end
end
And my model, which i think makes it fail
class UserApplicationHistory < ActiveRecord::Base
belongs_to :status_from_id, :class_name => "JobApplicationStatus"
belongs_to :status_to_id, :class_name => "JobApplicationStatus"
belongs_to :user_id, :class_name => "User"
belongs_to :handler_id, :class_name => "User"
end
You right, your model should look like this for user and handler:
belongs_to :user
belongs_to :handler, :class_name => "User"
To help you with JobApplicationStatus I would need to know how this table looks like