12.3.3 scaling issue of the status feed
4458 단어 status
1. it has a line of code:
following_ids = user.following_ids
this will fetch all the followed users of this user,
but what we need to just if user_id is included in this set.
SQL already optimized things like this, check inclusion in a set of another table.
2. the original way will pull out all the microposts and stick them into an array.
although they are paginated in the view, but in the memory, there is still an array holding all these data.
what we need is it honestly pull out 30 elements at a time.
so we will solve the two problems in this chapter.
1. the solution to both problems involves converting the feed from a class method to a scope
scope is a rails method for restricting database selects based on certain conditions.
for example, to arrange for a method to select all admins, we can add a scope:
scope :admin, where(:admin => true)
then
User.admin
will return all admin users.
2. I know you will ask what's the difference of using scope and class method:
when using independently, they are the same, both pull all admin users from database.
but when using in chains, it will be different:
User.admin.paginate(:page => 1)
this will only pull 30 admins from the database at a time.
so the database did some optimization here, the paginate will happen in the database level.
cool, isn't.
this will make a very bid differences for big site.
3. now it is time to change the from_users_followed_by method using scope:
scope :from_users_followed_by, lambda { |user| followed_by(user) }
note, this scope need to take an argument, so we have to use lambda, a anonymous function.
and the method is a little complicated, so we put it into a method, followed_by(user.)
def self.followed_by(user)
following_ids = user.following_ids
where("user_id in (#{following_ids}) or user_id = :user_id", {:user => user})
end
but this only make sure the database don't pull all micropost, but it still pull out all followed users.
we should think of a way to replace
following_ids = user.following_ids
we need to use sql text here:
following_ids = %(select followed_id from relationships where follower_id = :user_id)
so the new method is:
def self.followed_by(user)
following_ids = %(SELECT followed_id FROM relationships
WHERE follower_id = :user_id)
where("user_id IN (#{following_ids}) OR user_id = :user_id",
{ :user_id => user })
end
so the final sql being passed to database is:
SELECT * FROM microposts
WHERE user_id IN (SELECT followed_id FROM relationships
WHERE follower_id = 1)
OR user_id = 1
the database will be more efficient when executing this.
when Micropost.from_users_followed_by(user), it will still return all micropost.
but when chained with paginate or other things, it will be much different.
Micropost.from_users_followed_by(user).paginate(:page => 1)
it will not get all followed users, it just get enough to get the first 30 micropost
4. a way to construct a string: %(.........)
%(fjdkfjdlsjlfdsfjdlsfjlds
fjdsfjdslfdjs)
this is a way to construct string, you can think of it the same as double quotes.
the use case of %() to construct a string is:
a. when you want to show a multiline string.
b. when you want to have ""or "#{jfldjs}"inside a string.
>> puts %(The variable "foo"is equal to "#{foo}".)
all "in this string will be just display, no need to escape,
without %(), it will have to be:
>> "The variable\"foo\"is equal to\"#{foo}\"."
this is not very readable.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Status Codes그래서 status code(상태코드)라는걸 알 필요가 있다. 응답의 상태 코드가 200이라고 나와 있다. 위키피디아에서 상태 코드 200이 뭘 의미 하는지 응답으로 200을 받으면 구글 크롬이 계정 생성이 성공적이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.