문제

저는 페이지 캐싱을 사용하여 정적 HTML 출력을 저장하는 Rails 앱을 개발 중입니다.캐싱이 잘 작동합니다.하지만 캐시를 만료시키는 데 문제가 있습니다.

내 문제는 부분적으로 내 컨트롤러에서 캐시가 만료되지 않기 때문이라고 생각합니다.이에 필요한 모든 작업은 모델 내에서 처리됩니다.이것이 가능한 것처럼 보이지만, 제가 찾은 모델 기반 캐시 만료에 대한 모든 참조는 오래되었거나 작동하지 않는 것 같습니다.

내 Environment.rb 파일에서 전화를 걸고 있습니다.

config.load_paths += %W( #{RAILS_ROOT}/app/sweepers )

그리고 /sweepers 폴더에 LinkSweeper 파일이 있습니다.

class LinkSweeper < ActionController::Caching::Sweeper
  observe Link

  def after_update(link)
    clear_links_cache(link)
  end

  def clear_links_cache(link)
  # expire_page :controller => 'links', :action => 'show', :md5 => link.md5
    expire_page '/l/'+ link.md5 + '.html'
  end
end

그래서 ... 모델을 업데이트할 때 캐시된 페이지가 삭제되지 않는 이유는 무엇인가요? (프로세스:스크립트/콘솔을 사용하여 데이터베이스에서 항목을 선택하고 저장하지만 해당 페이지는 캐시에서 삭제되지 않습니다. 또한 일반적으로 스위퍼를 호출하는 Link 모델의 특정 메서드도 호출합니다.둘 다 작동하지 않습니다.

중요한 경우 캐시된 파일은 링크 테이블의 키 값에 대한 md5 해시입니다.캐시된 페이지는 /l/45ed4aade64d427...99919cba2bd90f.html과 같은 형식으로 저장됩니다.

본질적으로 스위퍼가 실제로 링크를 관찰하지 않는 것처럼 보입니다.나도 읽었다(여기) 단순히 스위퍼를 Environment.rb의 config.active_record.observers에 추가하는 것이 가능할 수도 있지만 그렇게 하지 않는 것 같았습니다. (그리고 Environment.rb에 있는 app/sweepers의 load_path가 제거되었는지 확실하지 않았습니다. 저것).

도움이 되었습니까?

해결책

메모 : 사용할 수 있습니다 cache_sweeper ApplicationController에서.

class ApplicationController < ActionController::Base
  cache_sweeper :my_sweeper
end

class MySweeper < ActionController::Caching::Sweeper
  observe MyModel

  def after_update(my_model)
    expire_page(...)
  end
end

다른 팁

그래서 나는 무엇이 효과가 있고 무엇이 효과가 없는지보기 위해 여러 가지 다른 접근법을 시도했습니다.

다시, 상황을 요약하기 위해 : 내 목표는 객체가 업데이트 될 때 캐시 된 페이지를 만료하지만 컨트롤러 동작에 의존하지 않고 만료하는 것입니다. 기존 스위퍼는 컨트롤러의 라인을 사용하여 스위퍼에게 작동해야한다고 알려줍니다. 이 경우 모델 내에서 업데이트가 발생하므로 컨트롤러에서 줄을 사용할 수 없습니다. 데이터베이스 객체와의 주요 상호 작용이 컨트롤러를 통해서라고 가정하므로 일반 스위퍼 튜토리얼이 작동하지 않습니다.

이 글을 읽을 때 내 코드를 강화하는 방법이 보이면 댓글을 달고 알려주십시오.

먼저, 당신이 이것에 갇혀 있고 도움이 필요한 경우에도 효과가있는 것들을 살펴 보겠습니다.

내가 시도한 모든 것 중에서, 실제로 작동하는 것처럼 보이는 유일한 것은 모델의 관찰자에서 후 _update 명령을 선언하는 것이 었습니다. 그 명령에서, 나는 expire_page action에 대해 명시 적 명령을 사용했으며, lours.rb에서 선언 된 경로를 포함시켰다.

그래서. 이것은 작동합니다 :

config/lours.rb에서 :

map.link 'l/:md5.:format',  :controller => 'links', :action => 'show'

app/models/link_observer.rb에서 :

def after_update(link)
  ActionController::Base.expire_page(app.link_path(:md5 => link.md5))
end

"MD5"는 내 앱에만 해당됩니다. ID 또는 다른 고유 식별자를 사용하고 싶을 수도 있습니다.

또한 ActionController :: Base ... 라인이 업데이트를 수행하는 모델의 메소드에서 라인을 선언하는 것을 발견했습니다. 즉, Link.rb 내에서 실제로 데이터베이스를 업데이트하는 메소드에서 전체 라인을 쌓으면 효과가있었습니다. 그러나 앞으로 다른 방법으로 해당 페이지 캐시를 만료하고 싶을 수도 있기 때문에 오히려 관찰자로 추출 할 것입니다.

이제, 당신이 이것에 대해 인터넷 검색을 할 경우를 대비하여 효과가없는 것들을 살펴 보겠습니다.

"eppire_page (...)"호출 link_observer.rb 내의 후 _update (link) 메소드 내에서 "undefined method`eppire_page '"오류를 반환하여 작동하지 않았습니다.

스위퍼 파일 생성 그것은 모델이 작동하지 않았다는 것을 관찰했습니다. 나는 어떤 오류 코드를 찾을 수 없었지만, 그것이해야 할 일이 있다는 것을 알지 못하는 것 같았습니다. 이것은 환경에서 "config.load_paths += %w ( #{rails_root}/app/sweespers)" "를 명시 적으로 호출 한 후에 왔습니다. 내가 그 코드에서 무언가를 뚱뚱한 날에 대비 한 경우를 대비하여 여기에 다음과 같습니다.

class LinkSweeper < ActionController::Caching::Sweeper
  observe Link

  def after_update(link)
    clear_links_cache(link)
  end

  def clear_links_cache(link)
    # DID NOT WORK    expire_page :controller => 'links', :action => 'show', :md5 => link.md5
    # DID NOT WORK    expire_page '/l/'+ link.md5 + '.html'
    # DID NOT WORK    ActionController::Base.expire_page(app.link_path(:md5 => link.md5))
  end
end

위의 예에는 디렉토리 /앱 /스위퍼에 link_sweeper.rb 파일이 있습니다. 또한 앱/모델 디렉토리에 link_sweeper.rb를 넣고 config.active_record.observers 명령으로 호출하려고 시도했습니다.

config.active_record.observers = :link_observer, :link_sweeper

그러나 그것은 작동하지 않았습니다.

그래서 예. 이러한 방법 중 하나가 작동 할 가능성이 높으며 코드에서 무언가를 엉망으로 만들 수 있습니다. 그러나 나는 책으로 모든 것을했다고 생각합니다.

궁극적으로 요약 : 스위퍼를 사용하여 페이지 캐싱이 만료되는 대신 모델의 관찰자에 콜백을 설정하려고합니다. Base.expire_Page 메소드에 대한 명시적인 경로를 사용하려고합니다.

def after_update(<model>) # where <model> is the name of the model you're observing
  ActionController::Base.expire_page(app.<model>_path(:id => <model>.id)) # where <model> is the name of the model you're observing
end

바라건대 이것은 다른 사람이 길을 따라가는 데 도움이 될 것입니다. 다시 한 번, 내가 일하지 않는 코드의 어느 곳에서나 다른 일을 해야하는 경우 알려 주시면 알려주십시오. 내 작업 코드에 더 단단 할 수있는 내용이 있으면 알려주십시오.

나는 조각 캐싱을 시도 할 때 같은 문제를 겪고있었습니다 (레일 3). 스위퍼를 관찰 할 수 없었기 때문에 위에서 설명한대로 AR 관찰자로 만들기 위해 솔루션을 해결했습니다. ApplicationController.new.expire_fragment(...).

나는 이것을 작동시켰다. 내 설정에서 유일한 약간의 차이점은 스위퍼가 레일 엔진의 일부라는 것입니다. 이는 약간의 차이를 설명합니다 (환경의로드 경로에 추가하는 대신 엔진의 Init에 필요한 스위퍼 파일을로드하십시오 .RB 등).

따라서 스위퍼는 엔진의 init.rb에 다음과 같이로드됩니다.

require File.join(File.dirname(__FILE__), 'app', 'sweepers', cached_category_count_sweeper')

캐시를 "청소"하기 때문에 스위퍼라고 불렀지 만 모델의 관찰자 일 뿐이라고 생각합니다.

class CachedCategoryCountSweeper < ActiveRecord::Observer
  observe CategoryFeature

  def before_save(cf)
    expire_cache(cf.category_id_was) if cf.category_id_changed?
  end

  def after_save(cf)
    expire_cache(cf.category_id)
  end

  def after_destroy(cf)
    expire_cache(cf.category_id)
  end

  def expire_cache(c)
    ApplicationController.expire_page("/categories/#{c}/counts.xml") if !c.nil?
  end
end

솔직히, 나는 경로를 하드 코딩하는 것을 좋아하지 않지만 다음을 추가하려고 시도했습니다.

include ActionController:UrlWriter

그런 다음 경로 방법을 사용하지만 개발에서만 효과가있었습니다. 제작 서버가 상대 URL 루트 (가상 호스트 대신)를 사용하고 내부 메소드 "Page_Cache_Path"가 일관되게 파일 경로를 잘못 이해하여 만료되지 않기 때문에 제작 분야에서는 작동하지 않았습니다.

이것은 관찰자이므로 환경에 추가했습니다 .rb :

config.active_record.observers = :cached_category_count_sweeper

마지막으로 캐시를 사용하는 컨트롤러가 만료되지 않으며 모델 관찰자를 통해 수행됩니다) :

class CachedCategoryCountsController < ApplicationController
  caches_page :index

  # GET /cached_category_counts.xml
  def index
    ...
  end
end

어쨌든, 이것이 도움이되기를 바랍니다.

안드레스 몬타 노

추가하는 방식으로 작동하게 만들 수 있었습니다.

ActionController::Base.expire_page(app.link_path(:md5 => @link.md5))

데이터베이스를 업데이트하는 모델 자체의 메서드에 연결됩니다. 하지만 이것은 다소 해킹된 느낌이 듭니다. 일반 스위퍼 설정에서는 왜 작동하지 않는지 설명할 수 있는 사람이 있는지, 그리고 이를 처리하는 더 우아한 방법이 있는지 알고 싶습니다.

해당 코드 조각(내 앱에 삽입한 사용자 정의는 제외)은 다음에서 나왔습니다. ruby-forum.com의 이 게시물.

나는이 주제에 대해 여기에 약간 썼다 : 레일 캐시 스위퍼 혼동. 당신의 의견을 듣고 싶습니다.

@moiristo와 @zoogiezork의 답변을 바탕으로, 나는 이것이 효과가 있다고 생각합니다 (테스트되지 않은).

class LinkSweeper < ActiveRecord::Observer
  include ActionController::Caching::Pages
  # or if you want to expire fragments
  #include ActionController::Caching::Fragments

  observe Link

  def after_update(link)
    expire_page( ... )
    #expire_fragment( ... )
  end
end
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top