Rails query not returning updated record - ruby-on-rails-3

Rails is not returning the updated version of a record.
I have two methods in a model, submit_job(sig, label, jobtype) for submitting a job to a db that will get processed on the backend, and then poll_result(id) which will poll that submitted job every second to see when it completes, and then return the results from the completed job to the user.
My issue is that the poll_result(id) method is never getting the updated record.
def self.poll_result(id)
change = false
Workbench.where("id = ?", id).each do |sig|
if sig.resultsready.to_i == 1
change = true
end
end
return change
end
All this does is comeback with the results from my original insert over and over, as I can see when I have it print out the results of the record it is accessing. I am looking directly at the database and can see that it is calling the right ID, and that the record has been updated. resultsready is set to 1 in the database, the loop should end and it should return back, but it just gets stuck in an infinite loop.
My assumption is that it is somehow getting an old/stale record that is being cached somehow, but I cannot for the life of me figure out how to force it to get the new record.
Thank You,
-Dennis

Using the Workbench.connection.clear_query_cache fixed the issue! To be specific, I added it at the controller level, right before calling Workbench.poll_result(id)

Related

How can i improve performances when using django queryset?

I'm trying to make a news feed. Each time the page is called, server must send multiple items. One item contain a post, number of likes, number of comments, number of comment children, comments data, comment children data etc.
My problem is, each time my page is called, it takes more than 5 secondes to be loaded. I've already implemented a caching system. But it's still slow.
posts = Posts.objects.filter(page="feed").order_by('-likes')[:'10'].cache()
posts = PostsSerializer(post,many=True)
hasPosted = Posts.objects.filter(page="feed",author="me").cache()
hasPosted = PostsSerializer(hasPosted,many=True)
for post in post.data:
commentsNum = Comments.objects.filter(parent=posts["id"]).cache(ops=['count'])
post["comments"] = len(commentsNum)
comments = Comments.objects.filter(parent=posts["id"]).order_by('-likes')[:'10'].cache()
liked = Likes.objects.filter(post_id=posts["id"],author="me").cache()
comments = CommentsSerializer(comments,many=True)
commentsObj[posts["id"]] = {}
for comment in comments.data:
children = CommentChildren.objects.filter(parent=comment["id"]).order_by('date')[:'10'].cache()
numChildren = CommentChildren.objects.filter(parent=comment["id"]).cache(ops=['count'])
posts["comments"] = posts["comments"] + len(numChildren)
children = CommentChildrenSerializer(children,many=True)
liked = Likes.objects.filter(post_id=comment["id"],author="me").cache()
for child in children.data:
if child["parent"] == comment["id"]:
liked = Liked.objects.filter(post_id=child["id"],author="me").cache()
I'm trying to find a simple method to fetch all these data quicker and without unnecessary database hit. I need to reduce the loading time from 5 secs to less than 1 if possible.
Any suggestion ?
Add the number of children as a integer on the comment field that gets updated every time a comment is added or removed. That way, you won't have to query for that value. You can do this using signals.
Add an ArrayField(if you're using postgres) or something similar on your Profile model that stores all the primary keys of Liked posts. Instead of querying the Likes model, you would be able to do this:
profile = Profile.objects.get(name='me')
liked = True if comment_pk in profile.liked_posts else False
Use select_related to CommentChildren instead of making an extra query for it.
Implementing these 3 items will get rid of all the db queries being executed in the "comment in comments.data" forloop which is probably taking up the majority of the processing time.
If you're interested, check out django-debug-toolbar which enables you to see what queries are being executed on every page.

Can't retrieve db Model getId() anymore in activejdbc 1.4.12

I was using activejdbc 1.4.9 and the following sample code was running just fine
Client client = new Client();
client.save();
Assert.assertNotNull(client.getId());
Since I upgraded to 1.4.12, client.getId() is always returning null when save is inserting a new record. i.e. id is not getting refreshed.
Did anyone notice this as well? Do I have to do anything different using this version to get the newly created id?
I cannot confirm this with the version 1.4.12. For instance, I wrote this example: https://github.com/javalite/simple-example/blob/new_id. Check out code in the Main.java. As you can see, the code is identical to yours, but on line 21, it prints out a real value of the new ID.
If you can put together a simple example that replicates your issue, I will take a look.
EDIT:
Now that you provided more info in comments below, the problem is with you setting the ID to empty string: "". Because the ID is not null anymore, the method save() uses update rather than insert. The update then uses the value of ID to update an "existing" record, and, as a result does not do anything. Messing with ID value is possible but not advised. Please see this for more information: http://javalite.io/surrogate_primary_keys

Update more record in one query with Active Record in Rails

Is there a better way to update more record in one query with different values in Ruby on Rails? I solved using CASE in SQL, but is there any Active Record solution for that?
Basically I save a new sort order when a new list arrive back from a jquery ajax post.
#List of product ids in sorted order. Get from jqueryui sortable plugin.
#product_ids = [3,1,2,4,7,6,5]
# Simple solution which generate a loads of queries. Working but slow.
#product_ids.each_with_index do |id, index|
# Product.where(id: id).update_all(sort_order: index+1)
#end
##CASE syntax example:
##Product.where(id: product_ids).update_all("sort_order = CASE id WHEN 539 THEN 1 WHEN 540 THEN 2 WHEN 542 THEN 3 END")
case_string = "sort_order = CASE id "
product_ids.each_with_index do |id, index|
case_string += "WHEN #{id} THEN #{index+1} "
end
case_string += "END"
Product.where(id: product_ids).update_all(case_string)
This solution works fast and only one query, but I create a query string like in php. :) What would be your suggestion?
You should check out the acts_as_list gem. It does everything you need and it uses 1-3 queries behind the scenes. Its a perfect match to use with jquery sortable plugin. It relies on incrementing/decrementing the position (sort_order) field directly in SQL.
This won't be a good solution for you, if your UI/UX relies on saving the order manually by the user (user sorts out the things and then clicks update/save). However I strongly discourage this kind of interface, unless there is a specific reason (for example you cannot have intermediate state in database between old and new order, because something else depends on that order).
If thats not the case, then by all means just do an asynchronous update after user moves one element (and acts_as_list will be great to help you accomplish that).
Check out:
https://github.com/swanandp/acts_as_list/blob/master/lib/acts_as_list/active_record/acts/list.rb#L324
# This has the effect of moving all the higher items down one.
def increment_positions_on_higher_items
return unless in_list?
acts_as_list_class.unscoped.where(
"#{scope_condition} AND #{position_column} < #{send(position_column).to_i}"
).update_all(
"#{position_column} = (#{position_column} + 1)"
)
end

Rails 3 after_save old value

How do you work with the old values of a record being updated?
For instance in the following code block how would I run a query using the previous winner_id field after I determine that it has indeed changed?
if self.winner_id_changed?
old_value = self.changed_attributes
User.find(old_value)
#do stuff with the old winner....
end
An example output of self.changed_attributes would be:
{"winner_id"=>6}
Do I really have to convert this to a string and parse out the value in order to perform a query on it? old_value[:winner_id] doesn't seem to do anything.
Use where instead of find, and the following inject method on changes to generate the desired hash:
if self.winner_id_changed?
old_value = self.changes.inject({}) { |h, (k,v)| h[k] = v.first }
old_user = User.where(old_value)
#do stuff with the old user....
end
You can also use ActiveRecord dirty methods such as:
self.winner_id_was
to get specific attribute's old value. Full documentation may be found here.

Create Ransack object without querying DB

I'd like to be able to create a Ransack::Search object to be passed into a search_form_for, but the initial creation of the search object queries the database, wich I don't want.
I want to show an initial blank form with Ransack::Search options to search, without calling the database.
How can I do that ?
thanks,
regards
Arel relations (ie. queries) are lazily-executed on first reference to the results, so you should find that you can create a search object and pass it to the form, without it calling the db, so long as you don't reference the .result method anywhere.
e.g.
// in your controller
my_query = MyModelClass.where{ id.gt(0) }
#q = my_query.search( params[:q] )
// in your view
search_form_for( #q, (...other options...) )
Any of these will trigger the db query to be actually performed:
- #q.results.each do |result|
- for result in #q.results
- #q.results.count
- #q.results.to_a
- #q.results.size
// ....etc
But so long as you only use the search object for your form, it should not get executed.
Of course, if you're testing this from the console, make sure that you put ;nil at the end of the line, otherwise the console will print the last thing evaluated, which will cause the query to be run!