القضبان: مرشح محدد في ملف lib المطلوب في البيئة. RB يختفي من Filter_Chain في بيئة الإنتاج. لماذا ا؟
-
03-07-2019 - |
سؤال
في تطبيق Rails الخاص بي ، لدي ملف في Lib ، من بين أشياء أخرى ، يقوم بإعداد مرشح يعمل على جميع وحدات التحكم.
عند تشغيل بيئة التطوير ، كل شيء يعمل بشكل جيد. ومع ذلك ، في إطار الإنتاج ، يختفي المرشح. الشيء المضحك هو ، من خلال فحص filter_chain
, ، لاحظت بقاء المرشحات الأخرى ، على سبيل المثال. تلك المحددة في المكونات الإضافية ، أو في وقت لاحق في فئة وحدة التحكم المحددة.
لقد اختبرت هذا مع كل من Rails Edge و V2.3.0.
تحديث الاختبار:
لقد اختبرت الآن مع القضبان القديمة ووجدت أن المشكلة تتواجد إلى v2.1.0 ، ولكن ليس في v2.0.5 ، لقد شطرت عليها ووجدت 986aec5 القضبان تلتزم أن تكون مذنبا.
لقد عزلت السلوك إلى حالة الاختبار الصغيرة التالية:
# app/controllers/foo_controller.rb
class FooController < ApplicationController
def index
render :text => 'not filtered'
end
end
# lib/foobar.rb
ActionController::Base.class_eval do
before_filter :foobar
def foobar
render :text => 'hi from foobar filter'
end
end
# config/environment.rb (at end of file)
require 'foobar'
إليك الإخراج الذي أحصل عليه عند الركض تحت تطوير بيئة:
$ script/server &
$ curl localhost:3000/foo
> hi from foobar filter
وهنا هو الإخراج ل إنتاج بيئة:
$ script/server -e production &
$ curl localhost:3000/foo
> not filtered
كما ألمح من قبل ، فإنه يعمل بشكل جيد لأي بيئة عندما أفعل نفس الشيء عبر البرنامج المساعد. كل ما أحتاجه هو وضع ما هو تحت lib/foobar.rb
في البرنامج المساعد init.rb
ملف.
لذا ، بطريقة ما لديّ بالفعل حل بديل ، لكنني أود أن أفهم ما يجري وما الذي يجعل المرشح يضيع عندما يكون في الإنتاج.
إنني أخمِّع أنه شيء ما بطرق مختلفة تتعامل معها القضبان في البيئات المختلفة ، لكنني بحاجة إلى الحفر بشكل أعمق.
تحديث
في الواقع ، لقد ضاقت الآن إلى خط التكوين التالي:
config.cache_classes = false
إذا ، في production.rb
, config.cache_classes
يتغير من true
إلى false
, ، تطبيق الاختبار يعمل بشكل صحيح.
ما زلت أتساءل لماذا تسبب إعادة تحميل الفصل مثل هذا الشيء.
المحلول
فريدريك تشيونغ على قائمة القضبان كان الاجابة:
لأن Cache_Classes يفعل أكثر من مجرد ذلك. الطريقة التي تعمل قبل عمل المرشحات ، إذا كانت Foo <bar ، فسيتم توريث تلك المرشحات المحددة في الشريط في تلك المرحلة
في وضع التطوير ، يبدأ التطبيق ، مطلوب ملفك ، والمرشح الذي تمت إضافته إلى ActionController :: base. في وقت لاحق يأتي الطلب الأول ، يتم تحميل وحدة التحكم ويرث ذلك التصفية.
عندما تكون Cache_Classes صحيحة ، يتم تحميل جميع فئات التطبيق الخاصة بك في وقت مبكر. يحدث هذا قبل الحاجة إلى ملفك ، لذلك جميع وحدات التحكم الخاصة بك موجودة بالفعل عند تشغيل هذا الملف وبالتالي لا يكون له أي تأثير. يمكنك حل هذا من خلال طلب هذا الملف من مُهيئ (ضمان تشغيله قبل تحميل فئات التطبيق) ، ولكن في الحقيقة لماذا لا تضع هذا في التطبيق.
فريد
كانت حالتي الحقيقية في الواقع أكثر مشاركة ، وهذه هي الطريقة التي وجدتها لحل المشكلة:
config.after_initialize do
require 'foobar'
end
ال after_initialize
يتم تشغيل الكتلة بعد تهيئة الإطار ولكن قبل تحميل ملفات التطبيق ، وبالتالي ، سوف يؤثر ActionPack::Base
بعد تحميله ، ولكن قبل أن تكون وحدات تحكم التطبيق.
أعتقد أن هذه هي الطريقة الآمنة عمومًا للتعامل مع كل التحميل المسبق الذي يستمر في الإنتاج.
نصائح أخرى
Drop a ruby script in
RAILS_ROOT\config\initializers
that contains
require "foobar.rb"
This invokes the before_filter for me.