استعمال ريلز لإنشاء تطبيقات ذات واجهة برمجية فقط

من موسوعة حسوب

في هذا الدليل ستتعلم:

  • ما تقدمه ريلز للتطبيقات ذات الواجهة البرمجية فقط.
  • كيفية ضبط ريلز للبدء دون أي ميزات للمتصفح.
  • كيفية تحديد البرامج الوسيطة (middleware) التي تريد تضمينها.
  • كيفية تحديد الوحدات لاستخدامها في وحدة التحكم الخاصة بك.

ما الذي يعنيه «تطبيق ذو واجهة برمجية فقط»؟

تقليديًا، عندما قال الناس أنهم استخدموا ريلز كـ "واجهة برمجية"، فقد كان يعني توفير واجهة برمجية يمكن الوصول إليها برمجيًا جنبًا إلى جنب مع تطبيق الويب الخاص بهم. على سبيل المثال، يوفر GitHub واجهة برمجية يمكنك استخدامها من العملاء المخصصين.

مع ظهور إطارات العمل من جانب العميل، يستخدم المزيد من المطورين ريلز لإنشاء واجهة خلفية مشتركة بين تطبيقات الويب والتطبيقات المحلية الأخرى.

على سبيل المثال، يستخدم Twitter واجهة برمجة التطبيقات العامة في تطبيق الويب الخاص به، والذي أنشئت كموقع ثابت يستهلك موارد JSON.

بدلًا من استخدام ريلز لإنشاء لغة HTML تتواصل مع الخادم من خلال النماذج والروابط، يعالج العديد من المطورين تطبيقات الويب الخاصة بهم على أنها مجرد عميل واجهة برمجة تطبيقات تُسلَّم بتنسيق HTML مع JavaScript ويستهلك واجهة برمجة تطبيقات JSON.

يغطي هذا الدليل بناء تطبيق ريلز يخدم موارد JSON إلى عميل واجهة برمجة التطبيقات، بما في ذلك أطر عمل العميل.

لماذا تستخدم ريلز لواجهة برمجة تطبيقات JSON؟

السؤال الأول الذي يفكر فيه الكثير من الأشخاص عند التفكير في إنشاء واجهة برمجة تطبيقات JSON باستخدام ريلز هو: "أليس استخدام ريلز لاستخراج بعض البيانات المكتوبة بصيغة JSON أمر مبالغ فيه بشدة؟ ألا يجب فقط أن أستخدم شيئًا مثل Sinatra؟".

لواجهة برمجة تطبيقات بسيطة للغاية، قد يكون هذا صحيحًا. ومع ذلك، فحتى في تطبيقات HTML الضخمة، فإن معظم شيفرة التطبيق تقع خارج طبقة الواجهة.

السبب في أن معظم الناس يستخدمون ريلز هو أنه يوفر مجموعة من الافتراضات التي تسمح للمطورين بتسريع وتيرة العمل، دون الحاجة إلى اتخاذ الكثير من القرارات التافهة.

لنلقِ نظرة على بعض الأشياء غير التقليدية التي توفرها ريلز والتي لا تزال سارية على تطبيقات واجهة برمجة التطبيقات.

التعامل عند طبقة البرمجيات الوسيطة (middleware layer):

  • إعادة التحميل: تدعم تطبيقات ريلز إعادة التحميل الشفاف (transparent reloading). هذا يعمل حتى إذا أصبح التطبيق الخاص بك كبيرًا، وإعادة تشغيل الخادم لكل طلب تصبح عملية غير قابل للتطبيق.
  • وضع التطوير: تأتي تطبيقات ريلز مع الافتراضات الذكية للتطوير، مما يجعل التطوير مسليًا دون المساس بأداء وقت الإنتاج.
  • وضع الاختبار: يشبه وضع التطوير.
  • التسجيل: تسجل تطبيقات ريلز كل طلب، مع مستوى من التفصيل والإسهاب المناسب للوضع الحالي. تتضمن سجلات ريلز قيد التطوير معلومات حول بيئة الطلب واستعلامات قاعدة البيانات ومعلومات الأداء الأساسية.
  • الأمن: يكتشف ريلز هجمات انتحال IP ويعطلها ويتعامل مع توقيعات التشفير بطريقة حذرة من حدوث هجوم التوقيت. لا تعرف ما هو هجوم انتحال IP أو هجوم التوقيت؟ حسنًا، ألق نظرة على الروابط.
  • تحليل المعامل: هل تريد تحديد المعاملات على أنها JSON بدلًا من أنها سلسلة مشفرة لعناوين URL؟ ليس هناك أى مشكلة. ستعمل ريلز على فك شيفرة JSON وجعلها متوفرة في params. هل ترغب في استخدام المعاملات المتداخلة لعناوين URL المتداخلة؟ هذا يعمل أيضًا.
  • طلبات GET المشروطة: يعالج ريلز طلبات GET المشروطة (ETag و Last-Modified)، وتعالج ترويسات الطلب، وتعيد ترويسات الرد المناسب ورمز الحالة. كل ما عليك القيام به هو استخدام ?stale الذي يتحقق من وحدة التحكم، وسيتولى ريلز جميع تفاصيل HTTP نيابة عنك.
  • طلبات HEAD: ستحول ريلز طلبات HEAD إلى GET، وتعيد الترويسات فقط إلى المخرج. هذا يجعل HEAD يعمل بشكل موثوق في جميع واجهات برمجة التطبيقات ريلز.

على الرغم من أنه يمكنك بناء هذه البرامج من خلال البرامج الوسيطة من Rack (أي Rack middleware) الموجودة حاليًا، توضح هذه القائمة أن حزمة برامج ريلز الوسيطة الافتراضية توفر الكثير من القيم، حتى إذا كنت "تولد محتوى بصيغة JSON فقط".

التعامل عند طبقة Action Pack:

  • توجيه الموارد: إذا كنت تنشئ واجهة برمجة تطبيقات JSON RESTful (أي RESTful JSON API)، فستحتاج إلى استخدام جهاز توجيه ريلز. تعني التعيينات النظيفة والتقليدية من HTTP إلى وحدات التحكم عدم الحاجة إلى قضاء بعض الوقت في التفكير في كيفية تصميم واجهة برمجة التطبيقات الخاصة بك من حيث طلبات HTTP.
  • إنشاء عنوان URL: الجانب الآخر للتوجيه هو إنشاء عنوان URL. تتضمن واجهة برمجة التطبيقات الجيدة المستندة إلى HTTP عناوين URL (راجع واجهة برمجة تطبيقات GitHub Gist على سبيل المثال).
  • ردود الترويسة وإعادة التوجيه: إن head، :no_content و redirect_to و user_url(current_user)‎ تأتي في متناول اليدين. بالتأكيد، يمكنك إضافة ترويسات للرد يدويًا، ولكن لماذا؟
  • التخزين المؤقت: يوفر ريلز آلية تخزين الصفحة، وتخزين الإجراء، وتخزين الجزئيات. يكون التخزين المؤقت للشيفرة مفيدًا بشكل خاص عند إنشاء كائن JSON متداخل.
  • الاستيثاق الأساسي (Basic Authentication)والاستيثاق عبر قيم مشفرة مختصرة (Digest Authentication) والاستيثاق عبر الرموز (Token Authentication): تأتي ريلز مع دعم متميز لثلاثة أنواع من استيثاق HTTP المشار إليها.
  • أدوات قياس: يحتوي ريلز على واجهة برمجة تطبيقات لأدوات قياس (instrumentation API) تعمل على استدعاء معالجات مسجلة لمجموعة متنوعة من الأحداث مثل معالجة الإجراءات، وإرسال ملف أو بيانات، وإعادة توجيه، و استعلامات قاعدة البيانات. تأتي حمولة كل حدث مع المعلومات ذات الصلة (لحدث معالجة الإجراءات، تتضمن الحمولة وحدة التحكم، والإجراء، والمعاملات، وتنسيق الطلب، وطريقة الطلب والمسار الكامل للطلب).
  • المولدات: غالبا ما تكون مفيدة لتوليد مورد والحصول على النموذج الخاص بك، ووحدة التحكم، وحزم اختبار، والمسارات التي أُنشئت لك في أمر واحد لمزيد من التغيير والتبديل. تشبه التهجيرات وغيرها.
  • الإضافات: تأتي العديد من مكتبات التي توفرها جهة ثالثة مع دعم ريلز الذي يقلل أو يقضي على تكلفة إعداد ولصق المكتبة وإطار الويب. يتضمن ذلك أشياءً مثل إلغاء المولدات الافتراضية وإضافة مهام Rake واحترام اختيارات ريلز (مثل التسجيل وذاكرة التخزين المؤقت الخلفي).

وبطبيعة الحال، فإن عملية إقلاع ريلز تجمع جميع المكونات المسجلة. على سبيل المثال، عملية إقلاع ريلز هي العملية التي تستخدم الملف config/database.yml الخاص بك عند ضبط Active Record.

الإصدار المختصر: قد لا تكون قد فكرت في أي أجزاءٍ من ريلز لا تزال قابلة للتطبيق حتى إذا قمت بإزالة طبقة الواجهة، ولكن الإجابة تبين أنها أكثر من ذلك.

الضبط الأساسي

إذا كنت بصدد إنشاء تطبيق ريلز سيكون خادم واجهة برمجية في المقام الأول، فيمكنك البدء بمجموعة فرعية أكثر تحديدًا من ريلز وإضافة ميزات حسب الحاجة.

إنشاء تطبيق جديد

يمكنك إنشاء تطبيق ريلز جديد ليعمل كواجهة برمجية بالشكل التالي:

$ rails new my_api --api

هذا سينجز لك ثلاثة أمور أساسية هي:

  • ضبط التطبيق الخاص بك لتبدأ بمجموعة محدودة من البرامج الوسيطة أكثر من المعتاد. وبالتحديد، لن تتضمن أي برامج وسيطة مفيدة بشكل أساسي لتطبيقات المتصفح (مثل دعم ملفات تعريف الارتباط) بشكل افتراضي.
  • جعل المتحكم ApplicationController يرث من ActionController::API بدلًا من ActionController::Base. كما هو الحال مع البرامج الوسيطة، سيؤدي هذا إلى إهمال أي وحدات تحكم في الإجراء تعمل على توفير وظائف تستخدم بشكل رئيسي من قبل تطبيقات المتصفح.
  • ضبط المولدات لتخطي إنشاء الواجهات والمساعدات والممتلكات عند إنشاء مورد جديد.

تغيير تطبيق موجود

إذا كنت تريد أن تحول تطبيقًا موجودًا إلى تطبيق واجهة برمجة التطبيقات، فاطلع على الخطوات التالية.

في الملف config/application.rb، أضف السطر التالي في أعلى تعريف الصنف Application:

config.api_only = true

في الملف config/environments/development.rb، اضبط config.debug_exception_response_format لتهيئة التنسيق المستخدم في الإستجابة عند حدوث أخطاء في وضع التطوير. لتصيير صفحة HTML تحتوي على معلومات تصحيح الأخطاء، استخدم القيمة :default.

config.debug_exception_response_format = :default

لتصيير معلومات تنقيح الأخطاء التي تحتفظ بتنسيق الاستجابة، استخدم القيمة :api.

config.debug_exception_response_format = :api

بشكل افتراضي، يُضبَط config.debug_exception_response_format إلى القيمة :api، عندما يُضبَط config.api_only إلى القيمة true. أخيرًا، داخل app/controllers/application_controller.rb، بدلًا من:

class ApplicationController < ActionController::Base
end

افعل:

class ApplicationController < ActionController::API
end

اختيار البرامج الوسيطة

يأتي تطبيق الواجهة البرمجية مع التطبيقات الوسيطة التالية افتراضيًا:

  • Rack::Sendfile
  • ActionDispatch::Static
  • ActionDispatch::Executor
  • ActiveSupport::Cache::Strategy::LocalCache::Middleware
  • Rack::Runtime
  • ActionDispatch::RequestId
  • ActionDispatch::RemoteIp
  • Rails::Rack::Logger
  • ActionDispatch::ShowExceptions
  • ActionDispatch::DebugExceptions
  • ActionDispatch::Reloader
  • ActionDispatch::Callbacks
  • ActiveRecord::Migration::CheckPending
  • Rack::Head
  • Rack::ConditionalGet
  • Rack::ETag

انظر قسم البرامج الوسيطة الداخلية من دليل ريلز مع Rack لمزيد من المعلومات عنها.

قد تضيف إضافات الأخرى، بما في ذلك Active Record، برامج وسيطة إضافية. بشكل عام، تكون هذه البرامج الوسيطة ملزمة لنوع التطبيق الذي تبنيه، ولها معنى في تطبيق ريلز المخصص للعمل كواجهة برمجية فقط.

يمكنك الحصول على قائمة بجميع البرامج الوسيطة في تطبيقك عبر تنفيذ الأمر التالي:

$ rails middleware

استخدام التخزين المؤقت للبرامج الوسيطة

بشكل افتراضي، سيضيف ريلز وسيطًا يوفر مخزنًا مؤقتًا يستند إلى ضبط التطبيق الخاص بك (ذاكرة التخزين المؤقت بشكل افتراضي). هذا يعني أن ذاكرة التخزين المؤقت لطلبات HTTP المضمنة ستعتمد عليه.

على سبيل المثال، باستخدام التابع stale?‎:

def show
  @post = Post.find(params[:id])
 
  if stale?(last_modified: @post.updated_at)
    render json: @post
  end
end

سيوازن استدعاء التابع stale?‎ الترويسة If-Modified-Since في الطلب مع ‎@post.updated_at. إذا كانت الترويسة أحدث من التعديل الأخير، يعيد هذا الإجراء الاستجابة "304 Not Modified" (غير مُعدَّل). بخلاف ذلك، سيصيِّر الاستجابة ويُضمِّن الترويسة Last-Modified فيها. عادةً، تستخدم هذه الآلية على أساس كل عميل. تتيح لنا الوسيطة مشاركة آلية التخزين المؤقت هذه عبر العملاء. يمكننا تمكين التخزين المؤقت عبر العميل في استدعاء إلى stale?‎:

def show
  @post = Post.find(params[:id])
 
  if stale?(last_modified: @post.updated_at, public: true)
    render json: @post
  end
end

وهذا يعني أن ذاكرة وسيطة التخزين المؤقت تخزن القيمة Last-Modified لعنوان URL في ذاكرة التخزين المؤقت لريلز، وتضيف الترويسة If-Modified-Since إلى أي طلبات واردة لاحقة لنفس عنوان URL.

فكر في ذلك كتخزين مؤقت للصفحة باستخدام دلالات HTTP.

استخدام Rack::Sendfile

عند استخدام التابع send_file داخل وحدة تحكم ريلز، يعين الترويسة X-Sendfile. يكون Rack::Sendfile مسؤولة عن إرسال الملف بالفعل.

إذا كان خادم الواجهة الأمامية يدعم إرسال الملفات المتسارعة (accelerated file sending)، سيلغي Rack::Sendfile تحميل الملف الفعلي الذي يرسل العمل إلى الخادم الأمامي.

يمكنك ضبط اسم الترويسة التي يستخدمها خادم الواجهة الأمامية لهذا الغرض باستخدام config.action_dispatch.x_sendfile_header في ملف ضبط البيئة المناسبة.

يمكنك معرفة المزيد حول كيفية استخدام Rack::Sendfile مع front-ends الشائعة في توثيق Rack::Sendfile.

في ما يلي بعض القيم لهذه الترويسة لبعض الخوادم الشائعة بمجرد تهيئة هذه الخوادم لدعم إرسال الملفات بسرعة:

# Apache and lighttpd
config.action_dispatch.x_sendfile_header = "X-Sendfile"
 
# Nginx
config.action_dispatch.x_sendfile_header = "X-Accel-Redirect"

تأكد من ضبط الخادم الخاص بك لدعم هذه الخيارات باتباع الإرشادات الموجودة في توثيق Rack::Sendfile.

استخدام ActionDispatch::Request

سوف يأخذ ActionDispatch::Request.params المعاملات من العميل بتنسيق JSON ويتيحها في وحدة التحكم داخل params.

لاستخدام هذا، سيحتاج العميل إلى تقديم طلب باستخدام معاملات JSON-encoded وتحديد نوع المحتوى على أنه application/json.

إليك مثال في jQuery:

jQuery.ajax({
  type: 'POST',
  url: '/people',
  dataType: 'json',
  contentType: 'application/json',
  data: JSON.stringify({ person: { firstName: "Yehuda", lastName: "Katz" } }),
  success: function(json) { }
});

سيطلع ActionDispatch::Request على نوع المحتوى وستكون المعاملات الخاصة بك:

{ :person => { :firstName => "Yehuda", :lastName => "Katz" } }

البرامج الوسيطة الأخرى

يحتوي ريلز على عدد من البرامج الوسيطة الأخرى التي قد ترغب في استخدامها في تطبيق ذي واجهة برمجية، خاصة إذا كان أحد عملاء واجهة برمجة التطبيقات هو المتصفح نفسه:

  • Rack::MethodOverride
  • ActionDispatch::Cookies
  • ActionDispatch::Flash
  • لإدارة الجلسة:
    • ActionDispatch::Session::CacheStore
    • ActionDispatch::Session::CookieStore
    • ActionDispatch::Session::MemCacheStore

يمكن إضافة أي من هذه البرامج الوسيطة عبر:

config.middleware.use Rack::MethodOverride

إزالة البرامج الوسيطة

إذا كنت لا ترغب في استخدام برامج وسيطة ضُمنت افتراضيًا في مجموعة البرامج الوسيطة للواجهة البرمجية فقط، فيمكنك إزالتها باستخدام:

config.middleware.delete ::Rack::Sendfile

ضع في اعتبارك أن إزالة هذه الوسيطة ستزيل الدعم لميزات معينة في وحدة التحكم بالعمل.

اختيار وحدات التحكم

يأتي تطبيق الواجهة البرمجية (باستخدام ActionController::API) مع وحدات التحكم التالية بشكل افتراضي:

  • ActionController::UrlFor: يتيح استعمال المساعد url_for والمساعدين الذين يشبهونه.
  • ActionController::Redirecting: يقدم الدعم redirect_to.
  • AbstractController::Rendering و ActionController::ApiRendering: الدعم الأساسي للتصيير.
  • ActionController::Renderers::All: يدعم render :json ورفقائه.
  • ActionController::ConditionalGet: يدعم stale?‎.
  • ActionController::BasicImplicitRender: يتأكد من عرض استجابة فارغ، إذا لم يكن هناك استجابة صريحة.
  • ActionController::StrongParameters: دعم المعاملات للقائمة البيضاء بالاشتراك مع تعيين كتلة نموذج فعال.
  • ActionController::ForceSSL: يدعم force_ssl.
  • ActionController::DataStreaming: يدعم send_file و send_data.
  • AbstractController::Callbacks: يدعم before_action و المساعدين المشابهين.
  • ActionController::Rescue: يدعم rescue_from.
  • ActionController::Instrumentation: يدعم خطافات الأجهزة المحددة من قبل وحدة التحكم في الإجراء (انظر دليل أدوات Active Support لمزيد من المعلومات حول هذا الأمر).
  • ActionController::ParamsWrapper: يغلف جدول Hash من المعاملات في جدول Hash متشعب، بحيث لا تضطر إلى تحديد عناصر الجذر لإرسال طلبات POST على سبيل المثال.
  • ActionController::Head: يدعم إعادة الإستجابة بدون محتوى، بل مع ترويسات فقط.

قد تضيف الإضافات الأخرى وحدات إضافية. يمكنك الحصول على قائمة بجميع الوحدات المضمّنة في ActionController::API في وحدة التحكم في ريلز:

$ bin/rails c
>> ActionController::API.ancestors - ActionController::Metal.ancestors
=> [ActionController::API,
    ActiveRecord::Railties::ControllerRuntime,
    ActionDispatch::Routing::RouteSet::MountedHelpers,
    ActionController::ParamsWrapper,
    ... ,
    AbstractController::Rendering,
    ActionView::ViewPaths]

إضافة وحدات أخرى

تعرف جميع وحدات التحكّم في الإجراءات كل شيء حول الوحدات التابعة لها، لذا لك الحرية المطلقة لإدراج أي وحدات في وحدات التحكم لديك، وستُضمَّن جميع الاعتمادات وتُضبَط أيضًا.

بعض الوحدات الشائعة التي قد ترغب في إضافتها هي:

  • AbstractController::Translation: دعم المحلية l و t توابع التحويل (translation methods).
  • دعم استيثاق HTTP الأساسية أو عبر القيمة المشفرة المختصرة (digest) أو الرمز المميز:
    • ActionController::HttpAuthentication::Basic::ControllerMethods
    • ActionController::HttpAuthentication::Digest::ControllerMethods
    • ActionController::HttpAuthentication::Token::ControllerMethods
  • ActionView::Layouts: دعم للتخطيطات عند التصيير.
  • ActionController::MimeResponds: دعم respond_to.
  • ActionController::Cookies: تدعم الكعكات (cookies)، والتي تتضمن دعم ملفات تعريف الارتباط الموقعة والمشفرة. هذا يتطلب ملفات تعريف الارتباط الوسيطة.

أفضل مكان لإضافة وحدة هو في ApplicationController الخاص بك، ولكن يمكنك أيضًا إضافة وحدات إلى وحدات التحكم الفردية.

مصادر