استعمال ريلز لإنشاء تطبيقات ذات واجهة برمجية فقط
في هذا الدليل ستتعلم:
- ما تقدمه ريلز للتطبيقات ذات الواجهة البرمجية فقط.
- كيفية ضبط ريلز للبدء دون أي ميزات للمتصفح.
- كيفية تحديد البرامج الوسيطة (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
الخاص بك، ولكن يمكنك أيضًا إضافة وحدات إلى وحدات التحكم الفردية.