To_SQL Not Working on Update_Attributes or .Save

to_sql not working on update_attributes or .save

These methods both return a boolean. You can't invoke to_sql on a boolean.

Rails: save doesn't update record if called twice?

Rails Models are 'Dirty' by default, meaning that attribute setting functions, attribute=(), mark the attribute as changed and tell Rails to update this attribute on the next save. This info is stored on the model, NOT in the database. On var.save, Rails only updates attributes it knows to have changed. Rails does not check the database for a discrepancy if it thinks nothing has changed (this would be incredibly slow in a production environment).

You can use var.reload to reload attributes from the database into the corresponding object.

EDIT: To clarify the comments being made above, you should be using MyModel.last not MyModel.first in your test code. If you have more than one row in your database, MyModel.first will not refer to the most recently saved object, and therefore var2 and var will refer to completely different objects.

How to update attributes without validation

USE update_attribute instead of update_attributes

Updates a single attribute and saves the record without going through the normal validation procedure.

if a.update_attribute('state', a.state)

Note:- 'update_attribute' update only one attribute at a time from the code given in question i think it will work for you.

Django: save() vs update() to update the database?

There are several key differences.

update is used on a queryset, so it is possible to update multiple objects at once.

As @FallenAngel pointed out, there are differences in how custom save() method triggers, but it is also important to keep in mind signals and ModelManagers. I have build a small testing app to show some valuable differencies. I am using Python 2.7.5, Django==1.7.7 and SQLite, note that the final SQLs may vary on different versions of Django and different database engines.

Ok, here's the example code.

models.py:

from __future__ import print_function
from django.db import models
from django.db.models import signals
from django.db.models.signals import pre_save, post_save
from django.dispatch import receiver

__author__ = 'sobolevn'

class CustomManager(models.Manager):
def get_queryset(self):
super_query = super(models.Manager, self).get_queryset()
print('Manager is called', super_query)
return super_query

class ExtraObject(models.Model):
name = models.CharField(max_length=30)

def __unicode__(self):
return self.name

class TestModel(models.Model):

name = models.CharField(max_length=30)
key = models.ForeignKey('ExtraObject')
many = models.ManyToManyField('ExtraObject', related_name='extras')

objects = CustomManager()

def save(self, *args, **kwargs):
print('save() is called.')
super(TestModel, self).save(*args, **kwargs)

def __unicode__(self):
# Never do such things (access by foreing key) in real life,
# because it hits the database.
return u'{} {} {}'.format(self.name, self.key.name, self.many.count())

@receiver(pre_save, sender=TestModel)
@receiver(post_save, sender=TestModel)
def reicever(*args, **kwargs):
print('signal dispatched')

views.py:

def index(request):
if request and request.method == 'GET':

from models import ExtraObject, TestModel

# Create exmple data if table is empty:
if TestModel.objects.count() == 0:
for i in range(15):
extra = ExtraObject.objects.create(name=str(i))
test = TestModel.objects.create(key=extra, name='test_%d' % i)
test.many.add(test)
print test

to_edit = TestModel.objects.get(id=1)
to_edit.name = 'edited_test'
to_edit.key = ExtraObject.objects.create(name='new_for')
to_edit.save()

new_key = ExtraObject.objects.create(name='new_for_update')
to_update = TestModel.objects.filter(id=2).update(name='updated_name', key=new_key)
# return any kind of HttpResponse

That resuled in these SQL queries:

# to_edit = TestModel.objects.get(id=1):
QUERY = u'SELECT "main_testmodel"."id", "main_testmodel"."name", "main_testmodel"."key_id"
FROM "main_testmodel"
WHERE "main_testmodel"."id" = %s LIMIT 21'
- PARAMS = (u'1',)

# to_edit.save():
QUERY = u'UPDATE "main_testmodel" SET "name" = %s, "key_id" = %s
WHERE "main_testmodel"."id" = %s'
- PARAMS = (u"'edited_test'", u'2', u'1')

# to_update = TestModel.objects.filter(id=2).update(name='updated_name', key=new_key):
QUERY = u'UPDATE "main_testmodel" SET "name" = %s, "key_id" = %s
WHERE "main_testmodel"."id" = %s'
- PARAMS = (u"'updated_name'", u'3', u'2')

We have just one query for update() and two for save().

Next, lets talk about overriding save() method. It is called only once for save() method obviously. It is worth mentioning, that .objects.create() also calls save() method.

But update() does not call save() on models. And if no save() method is called for update(), so the signals are not triggered either. Output:

Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

# TestModel.objects.get(id=1):
Manager is called [<TestModel: edited_test new_for 0>]
Manager is called [<TestModel: edited_test new_for 0>]
save() is called.
signal dispatched
signal dispatched

# to_update = TestModel.objects.filter(id=2).update(name='updated_name', key=new_key):
Manager is called [<TestModel: edited_test new_for 0>]

As you can see save() triggers Manager's get_queryset() twice. When update() only once.

Resolution. If you need to "silently" update your values, without save() been called - use update. Usecases: last_seen user's field. When you need to update your model properly use save().

Rails 4: .save does not update updated_at for existing records?

As you can see in your log, there is no UPDATE SQL query that is executed. Rails is not updating your record at all. This is because .save actually saves the record only if changes were made.

There is the method .touch (Documentation) that you can call in order to update the updated_at field without having to do changes to your record:

1.9.3p489 :005 > Intervention.first.touch
Intervention Load (12.9ms) SELECT "interventions".* FROM "interventions" LIMIT 1
SQL (20.5ms) UPDATE "interventions" SET "updated_at" = '2014-06-18 16:34:03.924648' WHERE "interventions"."id" = 1
=> true

Here we see the UPDATE SQL query.

How to update value of a Model's attribute

here is the solution

item = Item.find(1)
item.popularity = 1
item.save

When do I use save!, create! and update_attributes! in Rails?

Generally you want to use the non-bang versions in your controllers. This allows logic like this:

def update
@model = Model.find params[:id]
if @model.update_attributes params[:model] #returns true of false
# handle success
else
# handle failure
end
end

I find myself using the bang versions a lot in tests when I want to make sure I know if something doesn't validate, and isn't saved. I've definitely wasted time debugging tests that were failing because of changed model validations, which would be obvious if I used the bang versions.

e.g.

it "should do something" do
m = Model.create! :foo => 'bar' # will raise an error on validation failure
m.should do_something
end

In terms of not having invalid data in the database, you should be handling this with ActiveRecord validations (e.g. validates_presence_of :user_id), or defining your own validate method in the model. (http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html) This should prevent saves from occurring if your data isn't valid. If you're really paranoid you can add some constraints to your database. Check the ActiveRecord::Migration docs for how to set up unique indexes and other database constraints in your migrations.

Also in my experience you want to avoid using any custom save or create method whenever possible. If you re-implement functionality included in ActiveRecord you end up paying a price down the road. http://matthewpaulmoore.com/post/5190436725/ruby-on-rails-code-quality-checklist has more to say on this.

django save() refuses to update an existing record

I would advise to update the querset in bulk, with .update(…) [Django-doc]:

from django.db.models import F

@database_sync_to_async
def increment_unread(room_id):
RoomOccupier.objects.filter(room_id=room_id).update(
unread_count=F('unread_count')+1
)
return True

id attribute not updating in sqlite

Rails won't let you update the id attribute easily. You could execute the following SQL though, and it should work. (Also, when you use the update_attributes(...) method, you don't need to call .save afterward).

sql = "update people set id=5 where id=4"
ActiveRecord::Base.connection.execute(sql)


Related Topics



Leave a reply



Submit