Rails: How to check if "update_attributes" is going to fail?
Asked Answered
O

5

10

To check if buyer.save is going to fail I use buyer.valid?:

def create
  @buyer = Buyer.new(params[:buyer])
  if @buyer.valid?
    my_update_database_method
    @buyer.save
  else
    ...
  end
end

How could I check if update_attributes is going to fail ?

def update 
  @buyer = Buyer.find(params[:id])
  if <what should be here?>
    my_update_database_method
    @buyer.update_attributes(params[:buyer])
  else
    ...
  end
end
Owens answered 17/1, 2011 at 13:12 Comment(0)
F
14

it returns false if it was not done, same with save. save! will throw exceptions if you like that better. I'm not sure if there is update_attributes!, but it would be logical.

just do

if @foo.update_attributes(params)
  # life is good
else
  # something is wrong
end

http://apidock.com/rails/ActiveRecord/Base/update_attributes

Edit

Then you want this method you have to write. If you want to pre check params sanitation.

def params_are_sanitary?
  # return true if and only if all our checks are met
  # else return false
end

Edit 2

Alternatively, depending on your constraints

if Foo.new(params).valid? # Only works on Creates, not Updates
  @foo.update_attributes(params)
else
  # it won't be valid.
end
Forestay answered 17/1, 2011 at 13:19 Comment(6)
The main point that you are missing is that I want to execute my_update_database_method before calling to update_attributes, and my_update_database_method should be called only if update_attributes will succeed.Owens
What function does it serve? You must have save working, which updates the database.Forestay
I have never encountered a situation where I had to do that. You have my sympathies.Forestay
I cannot call update_attributes directly because it will cause some database constraints violations. I must first change some database values, and I do that by calling my_update_database_method. But, in case update_attributes will fail (because of Rails validation), I don't want to call my_update_database_method (i.e. don't want to change any database values).Owens
Sounds like you should rethink your database design sooner rather than later. This would be like if I had the constraint of fueling my car, only by walking to the gas station and bringing gas back home to my car. Would that method work? Yes. Is it painful? Yes.Forestay
You are right. I changed the design a little, and now it looks better :)Owens
N
1

The method update_attributes returns false if object is invalid. So just use this construction

def update
  if @buyer.update_attributes(param[:buyer])
    my_update_database_method
  else
    ...
  end
end

If your my_update_database_method has to be call only before update_attributes, then you shoud use merge way, probably like this:

def update
  @buyer = Buyer.find(params[:id])
  @buyer.merge(params[:buyer])
  if @buyer.valid?
    my_update_database_method
    @buyer.save
  else
    ...
  end
end
Norword answered 17/1, 2011 at 14:6 Comment(1)
That's right but it does not give you @buyer.errors .can you help with that . ThanksSunder
M
1

This may not be the best answer, but it seems to answer your question.

def self.validate_before_update(buyer)#parameters AKA Buyer.validate_before_update(params[:buyer])
# creates temporary buyer which will be filled with parameters
# the temporary buyer is then check to see if valid, if valid returns fail.
      temp_buyer = Buyer.new
# populate temporary buyer object with data from parameters
      temp_buyer.name = buyer["name"]
# fill other required parameters with valid data
      temp_buyer.description = "filler desc"
      temp_buyer.id = 999999 
# if the temp_buyer is not valid with the provided parameters, validation fails
    if  temp_buyer.valid? == false
        temp_buyer.errors.full_messages.each do |msg|
          logger.info msg
        end        
# Return false or temp_buyer.errors depending on your need.
        return false
    end

return true

end

Mediant answered 27/8, 2011 at 3:40 Comment(0)
C
1

you'd better check it in your model through a before_save

before_save :ensure_is_valid
private 
def ensure_is_valid
  if self.valid?
  else
  end
end
Chronopher answered 20/11, 2012 at 2:16 Comment(0)
Q
0

I've run into the same scenario - needed to know if record is valid and do some actions before update save. I've found out that there is assign_attributes(attributes) method which update method uses before save. So nowadays it's likely correct to do:

def update
  @buyer = Buyer.find(params[:id])
  @buyer.assign_attributes(params[:buyer])
  if @buyer.valid?
    my_update_database_method
    @buyer.save
  else
    ...
  end
end
Quiteria answered 20/8, 2020 at 10:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.