Reputation: 286
I have 2 models, suppose model1 and model2. model1 has many model2. model2 belongs to model1. Save model1 and model2 at the same time.
class Model1 < ActiveRecord::Base
has_many :model2s
end
class Model2 < ActiveRecord::Base
belongs_to :model1
end
def create
@mod1 = Model1.new(model1_params)
id = Model1.last.id + 1
@mod2 = Model2.new(model1_id: id)
if @mod1.save && @mod2.save
redirect root_path
else
render 'edit'
end
end
That solution is ok until I delete the last record of the model1. How can I get the last record of model1 before it created.
Upvotes: 3
Views: 5513
Reputation: 206
The most rails way to do this would be like this:
def create
@mod1 = Model1.new(model1_params)
@mod1.model2.build({args if you have them}) # this will only work if you have the relationship set up
if @mod1.save
# @mod1 is now saved along with model 2 who now has its ID
# @mod1.id returns id, Model2.last returns model2 ID, Model2.last.model1_id returns Model1 ID
#you can now delete model 1 if you wanted to, just make sure you don't have dependent destroy on in the model1.
redirect root_path
else
render 'edit'
end
end
Hope it helps!
Upvotes: 3
Reputation: 1322
If your Model1 and Model2 subclass ActiveRecord::Base
, then there is no need to set the id manually, in fact it's an anti-pattern.
Rails uses ActiveRecord::Base
to model a schema-backed class. Suppose you have a database table called model1s
. When you create a Model1 class like this
class Model1 < ActiveRecord::Base
end
Rails knows that the corresponding database table is models1
(infers it from the name) and automatically generates an id once you save a new Model1 record. The id is usually an auto-incremented integer. This of course depends on the underlying database engine (MySQL, Postgresql, SQLite, ...)
So, in your example, you could just do
success = false
@mod1 = Model1.new(model1_params)
if @mod1.save
@mod2 = Model2.new(model1_id: model1.id)
success = true if @mod2.save
end
success ? redirect_to(root_path) : render('edit')
Some more tips. The model1_id
attribute of Model2 looks like it's a foreign key. You should look into leveraging has_many/has_one/belongs_to associations to accomplish what you want in a more Rails idiomatic way
class Model1 < ActiveRecord::Base
has_one :model2
end
class Model2 < ActiveRecord::Base
belongs_to :model1
end
# Then you can do (one of the many options)
@mod1 = Model1.create(params)
@mod1.model2.create
It's useful to check the Rails guides on ActiveRecord.
I assumed you're using ActiveRecord, since you're using the .last
and .save
methods. I hope my instinct is correct.
Upvotes: 1
Reputation: 286
It is not possible to get the id of record that haven't create. The optimal answer for the solution is save the @mod1 first. And get the id of its id.
def create
@mod1 = Model1.new(model1_params)
if @mod1.save && Model2.create(model1_id: @mod1.id)
# @mod1 is now saved to the database. So @mod1.id will return id.
redirect root_path
else
render 'edit'
end
end
Upvotes: 0