Nyein
Nyein

Reputation: 286

How to get the id of the newly created record in rails way?

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

Answers (3)

theBrezilien
theBrezilien

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

gkats
gkats

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

Nyein
Nyein

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

Related Questions