الفرق بين المراجعتين ل"Ruby/Marshal"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
(أنشأ الصفحة ب'يُطلق الخطأ <code>LocalJumpError</code> عندما لا تتمكن روبي من الإعادة (yield) كما هو مطلوب. يحدث هذا مثلا،...')
 
 
(6 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
يُطلق الخطأ <code>LocalJumpError</code> عندما لا تتمكن روبي من الإعادة (yield) كما هو مطلوب.
+
<noinclude>{{DISPLAYTITLE:الوحدة <code>Marshal</code> في روبي}}</noinclude>
 +
تحوّل المكتبة <code>Marshal</code> مجموعات من كائنات روبي إلى مجرى من البايتات (byte stream)، مما يسمح بتخزينها خارج البرنامج النصي النشط حاليًا. يمكن بعد ذلك قراءة تلك البيانات وإعادة إنشاء الكائنات الأصلية أنشئت منها.  
  
يحدث هذا مثلا، عند محاولة الإعادة (yield) في غياب أي كتلة برمجية.<syntaxhighlight lang="ruby">
+
تحتوي البيانات المرصوفة (Marshaled data) على أرقام الإصدار الرئيسية والثانوية مخزنةً مع معلومات الكائن. في الاستخدام العادي، تُحمّل فقط البيانات التي لها نفس رقم الإصدار الرئيسي، ورقم الإصدار الثانوي المساوي أو الأقل منه. وفي حال ضبط قيمة الراية "<code>verbose</code>" (عادةً باستخادم ‎<code>-d</code> أو ‎<code>-v</code> أو <code>‎-w</code> أو ‎<code>-verbose</code>) يجب أن تتطابق الأرقام الرئيسية والثانوية تمامًا. إصدارات <code>Marshal</code> مستقلة عن إصدار روبي المستخدم. يمكنك استخلاص رقم الإصدار عن طريق قراءة أول بايتين من البيانات المرصوفة.<syntaxhighlight lang="ruby">
def call_block
+
str = Marshal.dump("thing")
   yield 42
+
RUBY_VERSION  #=> "1.9.0"
 +
str[0].ord    #=> 4
 +
str[1].ord    #=> 8
 +
</syntaxhighlight>لا يمكن تفريغ بعض الكائنات: في حال محاولة تفريغ كائنات تتضمن ارتباطات (bindings) أو إجراءات (procedure) أو توابع، أو كائنات <code>[[Ruby/IO|IO]]</code>، أو كائنات أحادية (singleton)، فسيطلق الخطأ <code>[[Ruby/TypeError|TypeError]]</code>.
 +
 
 +
إن كنت تريد تسلسلًا (serialization) مخصصًا (مثل إذا كنت تريد إجراء التسلسل وفق تنسيق معين)، أو إذا كان الصنف يحوي كائنات غير قابلة للتسلسل، فيمكنك إعداد قواعد التسلسل الخاصة بك.
 +
 
 +
هناك طريقتان للقيام بذلك، يمكن للكائنات أن تعرّف إما <code>marshal_dump</code> و <code>marshal_load</code> أو ‎<code>_dump</code> و ‎<code>_load</code>. يملك <code>marshal_dump</code> أولويةً على ‎<code>_dump</code> في حال تعريف كليهما. قد يُنتج <code>marshal_dump</code> سلاسل نصية أصغر.
 +
==تحسُّبات أمنية==
 +
يمكن للتابع <code>[[Ruby/Marshal/load|load]]</code> فك تسلسل (deserialize) أي صنف مُحمّل في عمليات روبي تقريبًا. في العديد من الحالات، يمكن أن يؤدي ذلك إلى تنفيذ التعليمات البرمجية عن بُعد إن حُملت البيانات المرصوفة (Marshal data) من مصدر غير موثوق به.
 +
 
 +
نتيجة لذلك، التابع <code>[[Ruby/Marshal/load|load]]::</code> ليس مناسبًا ليكون تنسيقَ تسلسلٍ عامٍّ، ويجب ألا يتم تبديد (unmarshal) البيانات المُدخلة من قبل المستخدم أو غيرها من البيانات غير الموثوقة.
 +
 
 +
إذا كنت تريد فك تسلسل (deserialize) البيانات غير الموثوقة، فاستخدم JSON أو تنسيق تسلسل آخر لا يمكنه أن يحمّل إلا الأنواع "البدائية" البسيطة، مثل [[Ruby/String|السلاسل النصية]] و<nowiki/>[[Ruby/Array|المصفوفات]] و<nowiki/>[[Ruby/Hash|جداول Hash]] وما إلى ذلك. لا تسمح أبدًا لمدخلات المستخدم أن تحدد أنواعًا عشوائيةً لفك التسلسل.
 +
==التابع <code>marshal_dump</code> والتابع <code>marshal_load</code>==
 +
عند تفريغ (dumping) كائن، سيتم استدعاء التابع <code>marshal_dump</code>. يجب أن يعيد التابع <code>marshal_dump</code> نتيجةً تحتوي على المعلومات الضرورية للتابع <code>marshal_load</code> لإعادة إنشاء الكائن. النتيجة يمكن أن تكون أي كائن.
 +
 
 +
عند تحميل كائن تم تفريغه باستخدام <code>marshal_dump</code>، يتم أولاً تحديد الكائن، ثم يُستدعَى التابع <code>marshal_load</code> وتُمرّر إليه النتيجة المُعادة من التابع <code>marshal_dump</code>. يجب أن يعيد التابع <code>marshal_load</code> إنشاء الكائن انطلاقًا من المعلومات المُتضمنة في النتيجة.
 +
 
 +
اطلع على المثال التالي:<syntaxhighlight lang="ruby">
 +
class MyObj
 +
  def initialize name, version, data
 +
    @name    = name
 +
    @version = version
 +
    @data    = data
 +
  end
 +
 
 +
  def marshal_dump
 +
    [@name, @version]
 +
  end
 +
 
 +
  def marshal_load array
 +
    @name, @version = array
 +
   end
 
end
 
end
call_block
 
</syntaxhighlight>تطلق الشيفرة أعلاه استثناء:<syntaxhighlight lang="ruby">
 
LocalJumpError: no block given (yield)
 
  
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
==التابع <code>‎_dump</code> والتابع <code>‎_load</code>==
 +
استخدم التابعين ‎<code>_dump</code> و <code>‎_load</code> عندما تريد تحديد الكائن الذي تود استعادته بنفسك.
 +
 +
عند تفريغ كائن، يُستدعى التابع ‎<code>_dump</code> مع تمرير عدد صحيح إليه يشير إلى العمق الأقصى للكائنات التى ستُفرّغ (القيمة ‎ <code>-‎‎1</code>تعني يجب عليك تعطيل التحقق من العمق). يجب أن يعيد التابع ‎ <code>_dump</code>سلسلةً نصيةً تحتوي على المعلومات الضرورية لإعادة إنشاء الكائن.
 +
 +
يأخذ الصنف <code>method_load</code> سلسلةً نصيةً ويستخدمها لإعادة كائن من نفس الصنف.
 +
 +
إليك المثال التالي:<syntaxhighlight lang="ruby">
 +
class MyObj
 +
  def initialize name, version, data
 +
    @name    = name
 +
    @version = version
 +
    @data    = data
 +
  end
 +
 +
  def _dump level
 +
    [@name, @version].join ':'
 +
  end
 +
 +
  def self._load args
 +
    new(*args.split(':'))
 +
  end
 +
end
 +
</syntaxhighlight>لما كان التابع <code>[[Ruby/Marshal/dump|dump]]</code> يعيد سلسلة نصية، يمكنك جعل التابع <code>have_dump</code>  يعيد سلسلة مرصوفة ‎‏ (Marshal string)،
 +
 +
== الثوابت ==
 +
 +
=== <code>MAJOR_VERSION</code> ===
 +
يمثِّل الإصدار الرئيسي.
 +
 +
=== <code>MINOR_VERSION</code> ===
 +
يمثِّل الإصدار الثانوي.
  
==توابع الكائن العامة (Public Instance Methods)==
+
==توابع الصنف العامة (Public Class Methods)==
=== [[Ruby/LocalJumpError/exit value|التابع exit_value]]===
+
===[[Ruby/Marshal/dump| <code>dump</code>]]===
يعيد التابع <code>exit_value</code> قيمة الخروج المرتبطة بالاستثناء <code>[[Ruby/LocalJumpError|LocalJumpError]]</code>.
+
يُسلسل (Serializes) الكائن المعطى وجميع الكائنات المنحدرة منه (descendant objects). في حال تمرير كائن من النوع <code>[[Ruby/IO|IO]]</code>، فستُكتب البيانات المُسَلسلة فيه، وإلا فستُعاد البياناتكسلسلة نصية.
=== [[Ruby/LocalJumpError/reason|التابع reason]]===
+
===[[Ruby/Marshal/load| <code>load</code>]]===
يعيد التابع <code>reason</code> سبب إنهاء الكتلة البرمجية: ‎ <code>:break</code>أو <code>‎:redo</code> أو <code>‎:retry</code> أو <code>‎:next</code> أو ‎ <code>:return</code> أو ‎<code>:noreason</code> .
+
يعيد نتيجة تحويل البيانات المُسلسلة (serialized) في المصدر إلى كائن روبي (ربما مع كائنات ثانوية [subordinate objects] مرتبطة به).
 +
===[[Ruby/Marshal/restore| <code>restore</code>]]===
 +
يعيد نتيجة تحويل البيانات المُسلسلة (serialized) في المصدر إلى كائن روبي (ربما مع كائنات ثانوية [subordinate objects] مرتبطة به).
 
==مصادر<span> </span>==
 
==مصادر<span> </span>==
*[http://ruby-doc.org/core-2.5.1/LocalJumpError.html قسم الصنف Marshal في توثيق روبي الرسمي.]
+
*[http://ruby-doc.org/core-2.5.1/Marshal.html قسم الوحدة Marshal في توثيق روبي الرسمي.]
<noinclude>{{DISPLAYTITLE: صفحة الصنف <code>Marshal</code> في روبي}}</noinclude>
 
 
[[تصنيف: Ruby]]
 
[[تصنيف: Ruby]]
[[تصنيف: Marshal]]
+
[[تصنيف: Ruby Module]]
 +
[[تصنيف: Ruby Marshal]]

المراجعة الحالية بتاريخ 18:21، 6 فبراير 2019

تحوّل المكتبة Marshal مجموعات من كائنات روبي إلى مجرى من البايتات (byte stream)، مما يسمح بتخزينها خارج البرنامج النصي النشط حاليًا. يمكن بعد ذلك قراءة تلك البيانات وإعادة إنشاء الكائنات الأصلية أنشئت منها.

تحتوي البيانات المرصوفة (Marshaled data) على أرقام الإصدار الرئيسية والثانوية مخزنةً مع معلومات الكائن. في الاستخدام العادي، تُحمّل فقط البيانات التي لها نفس رقم الإصدار الرئيسي، ورقم الإصدار الثانوي المساوي أو الأقل منه. وفي حال ضبط قيمة الراية "verbose" (عادةً باستخادم ‎-d أو ‎-v أو ‎-w أو ‎-verbose) يجب أن تتطابق الأرقام الرئيسية والثانوية تمامًا. إصدارات Marshal مستقلة عن إصدار روبي المستخدم. يمكنك استخلاص رقم الإصدار عن طريق قراءة أول بايتين من البيانات المرصوفة.

str = Marshal.dump("thing")
RUBY_VERSION   #=> "1.9.0"
str[0].ord     #=> 4
str[1].ord     #=> 8

لا يمكن تفريغ بعض الكائنات: في حال محاولة تفريغ كائنات تتضمن ارتباطات (bindings) أو إجراءات (procedure) أو توابع، أو كائنات IO، أو كائنات أحادية (singleton)، فسيطلق الخطأ TypeError.

إن كنت تريد تسلسلًا (serialization) مخصصًا (مثل إذا كنت تريد إجراء التسلسل وفق تنسيق معين)، أو إذا كان الصنف يحوي كائنات غير قابلة للتسلسل، فيمكنك إعداد قواعد التسلسل الخاصة بك.

هناك طريقتان للقيام بذلك، يمكن للكائنات أن تعرّف إما marshal_dump و marshal_load أو ‎_dump و ‎_load. يملك marshal_dump أولويةً على ‎_dump في حال تعريف كليهما. قد يُنتج marshal_dump سلاسل نصية أصغر.

تحسُّبات أمنية

يمكن للتابع load فك تسلسل (deserialize) أي صنف مُحمّل في عمليات روبي تقريبًا. في العديد من الحالات، يمكن أن يؤدي ذلك إلى تنفيذ التعليمات البرمجية عن بُعد إن حُملت البيانات المرصوفة (Marshal data) من مصدر غير موثوق به.

نتيجة لذلك، التابع load:: ليس مناسبًا ليكون تنسيقَ تسلسلٍ عامٍّ، ويجب ألا يتم تبديد (unmarshal) البيانات المُدخلة من قبل المستخدم أو غيرها من البيانات غير الموثوقة.

إذا كنت تريد فك تسلسل (deserialize) البيانات غير الموثوقة، فاستخدم JSON أو تنسيق تسلسل آخر لا يمكنه أن يحمّل إلا الأنواع "البدائية" البسيطة، مثل السلاسل النصية والمصفوفات وجداول Hash وما إلى ذلك. لا تسمح أبدًا لمدخلات المستخدم أن تحدد أنواعًا عشوائيةً لفك التسلسل.

التابع marshal_dump والتابع marshal_load

عند تفريغ (dumping) كائن، سيتم استدعاء التابع marshal_dump. يجب أن يعيد التابع marshal_dump نتيجةً تحتوي على المعلومات الضرورية للتابع marshal_load لإعادة إنشاء الكائن. النتيجة يمكن أن تكون أي كائن.

عند تحميل كائن تم تفريغه باستخدام marshal_dump، يتم أولاً تحديد الكائن، ثم يُستدعَى التابع marshal_load وتُمرّر إليه النتيجة المُعادة من التابع marshal_dump. يجب أن يعيد التابع marshal_load إنشاء الكائن انطلاقًا من المعلومات المُتضمنة في النتيجة.

اطلع على المثال التالي:

class MyObj
  def initialize name, version, data
    @name    = name
    @version = version
    @data    = data
  end

  def marshal_dump
    [@name, @version]
  end

  def marshal_load array
    @name, @version = array
  end
end

التابع ‎_dump والتابع ‎_load

استخدم التابعين ‎_dump و ‎_load عندما تريد تحديد الكائن الذي تود استعادته بنفسك.

عند تفريغ كائن، يُستدعى التابع ‎_dump مع تمرير عدد صحيح إليه يشير إلى العمق الأقصى للكائنات التى ستُفرّغ (القيمة ‎ -‎‎1تعني يجب عليك تعطيل التحقق من العمق). يجب أن يعيد التابع ‎ _dumpسلسلةً نصيةً تحتوي على المعلومات الضرورية لإعادة إنشاء الكائن.

يأخذ الصنف method_load سلسلةً نصيةً ويستخدمها لإعادة كائن من نفس الصنف.

إليك المثال التالي:

class MyObj
  def initialize name, version, data
    @name    = name
    @version = version
    @data    = data
  end

  def _dump level
    [@name, @version].join ':'
  end

  def self._load args
    new(*args.split(':'))
  end
end

لما كان التابع dump يعيد سلسلة نصية، يمكنك جعل التابع have_dump يعيد سلسلة مرصوفة ‎‏ (Marshal string)،

الثوابت

MAJOR_VERSION

يمثِّل الإصدار الرئيسي.

MINOR_VERSION

يمثِّل الإصدار الثانوي.

توابع الصنف العامة (Public Class Methods)

dump

يُسلسل (Serializes) الكائن المعطى وجميع الكائنات المنحدرة منه (descendant objects). في حال تمرير كائن من النوع IO، فستُكتب البيانات المُسَلسلة فيه، وإلا فستُعاد البياناتكسلسلة نصية.

load

يعيد نتيجة تحويل البيانات المُسلسلة (serialized) في المصدر إلى كائن روبي (ربما مع كائنات ثانوية [subordinate objects] مرتبطة به).

restore

يعيد نتيجة تحويل البيانات المُسلسلة (serialized) في المصدر إلى كائن روبي (ربما مع كائنات ثانوية [subordinate objects] مرتبطة به).

مصادر