Counter_Cache Has_Many_Through SQL Optimisation, Reduce Number of SQL Queries

counter_cache has_many_through sql optimisation, reduce number of sql queries

As far as I know you can't use counter_cache with through associations, that's why you should manually increment it.

For example (untested):

class MeetingUser < ActiveRecord::Base

...

after_create { |record|
Meeting.increment_counter(:users_count, record.meeting.id)
}

after_destroy { |record|
Meeting.decrement_counter(:users_count, record.meeting.id)
}

end

Rails: best way to turn these requests into a counter_cache

Assuming impression counts are for Publication, and impression count is to be grouped by each day.

You could create PublicationImpression model to serve as a counter for the impression of each Publication per day.

class CreatePublicationImpressions < ActiveRecord::Migration
def self.up
create_table :publication_impressions, :id => false do |t|
t.integer :impressions, :default => 0
t.datetime :date
t.references :publication

t.timestamps
end
end

def self.down
drop_table :publication_impressions
end
end

rails 3.1, how to calculate answers number using foreign key?

First of all I'm guessing that Quiz should read:

class Quiz < ActiveRecord::Base
belongs_to :page
has_many :answers
end

If so you can add these lines to your FinalExam model:

has_many :quizzes, :through => :pages
has_many :answers, :through => :quizzes

Allowing you to then call

FinalExam.first.answer.count

(Note: if you're on a version of Rails < 3.1, you'll need this plugin)

The drawback to this approach is that it becomes slow with a lot of data. In this case, you'd want to set up a counter cache in the FinalExam that updates every time an answer is added. It'd a little more complicated because of the many-layered relationships you have; see this post for more info:

counter_cache has_many_through sql optimisation, reduce number of sql queries

ActiveRecord has_many :through duplicating counter caches on mass assignment

So far my research has told me this is probably a bug. Here are some github issues already filed for this problem:

https://github.com/rails/rails/issues/3903

https://github.com/rails/rails/issues/3085

Apparently there is an undocumented automatic counter cache caused by has_many :through relations. So if Teacher.has_many :students, :through => :classrooms then teacher.students << student collection assignments already look for and increment teacher.students_count if that column exists.

If you add Classroom.belongs_to :teacher, :counter_cache => :students_count then an additional callback is triggered when the Classroom model is created, and the column gets incremented twice.

Effective work around: rename the counter cache columns to something else. Student#teacherz_count and Teacher#studentz_count were effective at allowing my test case to pass.

https://github.com/carlzulauf/test_app/commit/707a33f948d5d55a8aa942e825841fdd8a7e7705

I haven't yet been able to find where the problem lies in the ActiveRecord code base, so I won't accept my own answer for a while in case someone knows why has_many :through works this way and where the offending code lives.

Update

I believe I found the offending line of code. Commenting out this line resolves the problem:

https://github.com/rails/rails/blob/889e8bee82ea4f75adb6de5badad512d2c615b7f/activerecord/lib/active_record/associations/has_many_through_association.rb#L53

I can't seem to get edge rails up and running so I can't submit a pull for this bug yet. If someone else is able, please do.

Finding the offending line allowed me to craft a more effective monkey patch in my test app that resolves the issue without renaming any columns.

https://github.com/carlzulauf/test_app/commit/3c421b035bd032b91ff60e3d74b957651c37c7fa

Backslashes being added into my cookie in Python

As explained by others, the backslashes are escaping double quote characters you insert into the cookie value. The (hidden) mechanism in action here is the SimpleCookie class. The BaseCookie.output() method returns a string representation suitable to be sent as HTTP headers. It will insert escape characters (backslashes) before double quote characters and before backslash characters.

The

print cookie

statement activates BaseCookie.output().

On each trip your string makes through the cookie's output() method, backslashes are multiplied (starting with the 1st pair of quotes).

>>> c1=Cookie.SimpleCookie()
>>> c1['name']='A:0'
>>> print c1
Set-Cookie: name="A:0"
>>> c1['name']=r'"A:0"'
>>> print c1
Set-Cookie: name="\"A:0\""
>>> c1['name']=r'"\"A:0\""'
>>> print c1
Set-Cookie: name="\"\\\"A:0\\\"\""
>>>

ActiveRecord Query: select record where has at least one in a has many relationship

I would just use a counter cache column. This gives you a database column in questions which counts the number of answers attached to it. As a bonus, it's probably faster to run this query.

Here's a Railscasts video that describes how to create one: http://railscasts.com/episodes/23-counter-cache-column

Then your query becomes:

Question.where("answers_count > 0")

You could even be fancy and define this as a scope:

class Question < ActiveRecord::Base
has_many :answers
scope :answered, where("answers_count > 0")
end

It seems like a simple solution, but simple is good.



Related Topics



Leave a reply



Submit