هشام رزق الله
الأعضاء-
المساهمات
1442 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
31
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو هشام رزق الله
-
في العادة يُعتبر إنهاء أحد الخيوط (thread) عادة سيئة سواء كان ذلك في البايثون أو في أي لغة أخرى للأسباب التالية: - سيكون الخيط (thread) مرتبط بعدة موارد حيوية يجب أن يتم إغلاقها بشكل صحيح. - يجب أن يتم أيضا إنهاء بقية الخيوط (threads) التي قام بإنشائها هذا الخيط. لذلك ينصح بأن تتعامل مع هذه المشكلة عن طريق إنشاء تابع الخروج الذي سوف يوقف الخيط (thread) بالطريقة الصحيحة كما في المثال التالي: import threading class StoppableThread(threading.Thread): """Thread class with a stop() method. The thread itself has to check regularly for the stopped() condition.""" def __init__(self): super(StoppableThread, self).__init__() self._stop = threading.Event() def stop(self): self._stop.set() def stopped(self): return self._stop.isSet()في هذا المثال يجب عليك أن تقوم بتشغيل stop حتى يتم إنهاء البرنامج. يذكر أنه لا توجد API رسمي لإغلاق الخيوط (threads). أما لو أردت إغلاق كامل البرنامج فيجب عليك في هذه الحالة جعل الخيط (thread) بحالة daeamon عن طريق Thread.daemon.
-
سأحول شرحها بأبسط ما يمكن، تقوم هذه الرموز بتنفيذ الشيفرة البرمجية بلغة الروبي الموجودة بين هذين الأقواس المعقوفة: <% %> أما هذه فتستخدم لتجنب كسر السطر(line break) بعد التعبير: <% -%> هذه الرموز في الأعلى (<% %> و <% -%>) تُستخدم لأي شيفرة برمجية بلغة الروبي، لكنها لا تخرج أية نتائج. والرموز التالية تُستخدم لطباعة شيء ما إلى ملف erb: <%= %> وفي النهاية تُستخدم هذه الرموز لوضع التعليقات ما بين الأقواس المعقوفة، لكن هذه التعليقات لا يتم إرسالها إلى العميل(على عكس تعليقات HTML): <%# %>المصدر
-
سأحاول تفسير الأمر أكثر ما يمكن. معنى test هو أنه سيقوم بتطبيق العملية الحسابية AND على المعاملين ومن ثم سوف يتأكد من الناتج إذا كان صفرا، لذلك معنى هذه الشفرة أنها ستقوم باختبار ما إذا كانت EAX تساوي صفر أو لا ومن ثم سوف تتم عملية القفز باستخدام je إذا كانت صفر. بالمناسبة يمكنك جعل الشيفرة أفضل وأكثر قابلية للقراءة عن طريق استبدال هذا السطر بالسطر التالي: cmp eax,0 هذا السطر سيقوم بنفس الوظيفة السطر السابق لكنه سيتطلب المزيد من مساحة البايتات.
-
هنالك العديد من الطرق لتحويل حالة الأحرف الكبير إلى أحرف صغيرة، لكن لن تستطيع التخلي عن تكرار أمر الاختبار على جميع الحروف، لأنه لا توجد أية طريقة أخرى لمعرفة حالة الحرف إذا كانت كبيرة أو صغيرة. يمكنك استخدام هذه الطريقة لتحويل الأحرف الكبيرة إلى صغيرة: #include <algorithm> #include <string> std::string data = "Abc"; std::transform(data.begin(), data.end(), data.begin(), ::tolower);أو يمكنك استخدام هذه الطريقة البسيطة لتحويل حالة الأحرف: #include <boost/algorithm/string.hpp> std::string str = "HELLO, WORLD!"; boost::algorithm::to_lower(str);إذا لم ترد استخدام tolower فيمكنك في هذه الحالة استخدام هذه الطريقة، لكن لا أنصحك باستخدامها لأن الأولى أفضل بكثير: char easytolower(char in){ if(in<='Z' && in>='A') return in-('Z'-'z'); return in; } std::transform(data.begin(), data.end(), data.begin(), easytolower);المصدر
-
من الصعب جدا أن تقوم بإغلاق الشيفرة البرمجية المكتوبة بلغة البايثون لأن لغة البايثون من نوع byte-code-compiled interpreted language أي أنها لغة مفسرة وعند يتم ترجمتها ستخرج byte-code، وحتى لو حاولت إغلاقها ببرامج مثل py2exe فإن مخطط التنفيذ معروف وسيتمكن أي مختص في البرمجة من معرفة شيفرة البايثون. في العادة في مثل هذه الحالات يجب أن تسأل نفسك هل يستحق هذا البرنامج أن تقوم بغلق الشيفرة المصدرية الخاصة به ؟ هل يوجد به أي خوارزمية خاصة أو ميزة فريدة يجب أن لا يعرفها أي أحد ؟ إذا كان جوابك على هذه الأسئلة نعم، فأنصحك أن تقوم بكتابة بعض الأجزاء التي تريد غلقها بلغة أخرى مثل لغة السي لتكون كملحق للبرنامج.
-
هنالك العديد من الطرق لحذف العناصر المكررة في المصفوفة وأسهل هذه الطرق استخدام تابع uniq الذي يقوم بإرجاع جميع العناصر بدون تكرار في المصفوفة، ويمكنك استخدامه كما في المثال التالي: array = array.uniq ويمكنك أيضا استخدام العامل الحسابي & لحذف العناصر المكررة من المصفوفة كما في المثال التالي: a = [1,1,2,3] a & a كما يمكنك إنشاء آلية خاصة بك لحذف العناصر المكررة من المصفوفة عن طريق استخدام حلقات التكرار كما في هذا المثال: a = [1, 2, 2, 3] counts = Hash.new(0) a.each { |v| counts[v] += 1 } p counts.select { |v, count| count == 1 }.keys # [1, 3]كما يمكنك أيضا استخدام التابع inject لحذف التكرارات كما في المثال التالي: [1,1,1,2,4,6,3,3].inject({}){ |ele, n| ele[n] = nil; ele }.keys # => [1, 2, 4, 6, 3]المصدر
-
لست خبيرا في الأسمبلي لكن لدي معرفة ببعض أساسيات البرمجة باستخدامها، لذلك قمت بالبحث في عدة منتديات أجنبية عن الحل فوجدت هذه الشيفرة البرمجية: data segment num db -3,1,-5,6,-7,9,'#' p_cnt db 0h n_cnt db 0h data ends code segment assume ds:data,cs:code start: mov ax,data mov ds,ax lea si,num main: cmp num[si],0h jg pos inc si add n_cnt,01h cmp num[si],'#' je exit jmp main pos: add p_cnt,01h inc si cmp num[si],'#' je exit jmp main exit: mov bl,p_cnt mov cl,n_cnt mov ax,4c00h int 21h code ends end startسيقوم هذا البرنامج باختبار كل رقم على حدة وسيضيف +1 إلى p_cnt إذا كان الرقم موجب وسيضيف +1 إلى n_cnt إذا كان الرقم سالب، وبعد ذلك سيقوم بطباعة الناتج على شاشة الحاسوب. ملاحظة: سيتوقف البرنامج عند وصوله إلى رمز # وجدت أمثلة أخرى مثل هذه: MOV AX, DATA MOV DS, AX MOV CL, 05 XOR BL, BL XOR DL, DL LEA SI, SERIES NEXT2: MOV AL, [SI] SHR AL, O1 JNC NEXT1 INC BL JMP NEXT3 NEXT1: INC DL NEXT3: INC SI DEC CL JNZ NEXT2 MOV POS, DL MOV NEG, BL END في العادة ستكون شيفرات اختبار نوع الرقم (سالب أو موجب) مشابهة لهذه: cmp eax, 0 jl isNegative ;or test eax, 0x80000000 jne is_signed ;or test eax, eax js signed ;or test al, al js is_signed ; or test eax, 80h jne is_signedالمصادر 1 2 3
- 2 اجابة
-
- 1
-
هنالك عدة طرق لتحويل الأعداد الصحيحة إلى أعداد من نظام السداسي العشري، فيمكنك على سبيل المثال استخدام دالة to_s لتحويل الرقم بعد تمرير لها رقم 16 للدلالة على أنك تريد سلسلة نصية بها العدد السداسي العشري المقابل للعدد الصحيح الذي تريد تحويل. يمكنك استخدام هذه الدالة كما يلي: 10.to_s(16) #=> "a" ومن الطرق الأخرى أيضا للتحويل يمكنك استخدام الرمز %x لطباعة السلاسل النصية السداسية العشرية فعند إعطاءك رقم ما صحيح فإنه سيقوم بتحويله بشكل تلقائي إلى عدد سداسي العشري كما في المثال التالي: i = 20 "%x" % i #=> "14"المصدر
-
هنالك طرق متعددة لاستدعاء مكتبة/وحدة معينة عن طريق مسارها، ومن أسهل هذه الطرق استدعاء مكتبة imp ومن ثم استخدام دالة load_source لاستدعاء المكتبة/الوحدة المطلوبة كما في المثال التالي: import imp foo = imp.load_source('module.name', '/path/to/file.py') foo.MyClass()ملاحظة: تم ازالت هذه المكتبة في الإصدار 3.4 من البايثون. أما لو كنت تستخدم بايثون 3.3+ فيمكنك في هذه الحالة استخدام دالة SourceFileLoader من مكتبة importlib كما في المثال التالي: from importlib.machinery import SourceFileLoader foo = SourceFileLoader("module.name", "/path/to/file.py").load_module() foo.MyClass()ومن الطرق الأخرى لاستدعاء وحدة/مكتبة يمكنك إضافة مسار المكتبة/الوحدة عن طريق sys.path.append ومن ثم يمكنك استدعاء جميع الوحدات/المكتبات الموجودة في ذلك المسار كما في هذا المثال: import sys # the mock-0.3.1 dir contains testcase.py, testutils.py & mock.py sys.path.append('/foo/bar/mock-0.3.1') from testcase import TestCase from testutils import RunTests from mock import Mock, sentinel, patchالمصدر
-
هنالك العديد من الطرق لتلوين مخرجات في الروبي، فأسهل وأبسط طريقة هي عن طريقة استخدام colorize الذي يمكنك تثبيته عن طريق الأمر التالي: sudo gem install colorize وهذا مثال بسيط على استخدام colorize لتلوين مخرجات الطرفية. كما يمكنك القيام بدالة لتلوين المخرجات حسب رقم اللون كما في المثال التالي: class String # colorization def colorize(color_code) "\e[#{color_code}m#{self}\e[0m" end def red colorize(31) end def green colorize(32) end def yellow colorize(33) end def blue colorize(34) end def pink colorize(35) end def light_blue colorize(36) end endالطريقة في الأعلى تعمل فقط على أنظمة يونكس (لينكس وماك …) ولا تعمل على أنظمة ويندوز. وهذا صنف به العديد من الميزات حيث يمكنك تلوين النص أو جعله أغمق أو أن تضع سطرا أسفله أو أن تجعله مائلا. المصدر
-
في الحقيقة توجد العديد من الطرق لتنزيل الملفات من شبكة الأنترنت، فلو كنت تستخدم البايثون 2 فيمكنك استخدام مكتبة urllib2 التي تأتي بشكل افتراضي مع المكتبات القياسية، وهذا مثال بسيط على استخدامها: import urllib2 response = urllib2.urlopen('http://www.example.com/') html = response.read() ملاحظة: هذه الطريقة لن تعمل في حالة كان هنالك فراغات في الرابط، ولقد تم حل هذه المشكلة في البايثون 3. كما يمكنك استخدام urlretrieve من مكتبة urllib كما في الشكل التالي: import urllib urllib.urlretrieve ("http://www.example.com/files/mp3.mp3", "mp3.mp3") ويمكنك أيضا إنشاء تطبيق بسيط لتحميل الملفات مع شريط التقدم الذي يقوم بحساب نسبة اكتمال تحميل الملف كما في المثال التالي: import urllib2 url = "http://download.thinkbroadband.com/10MB.zip" file_name = url.split('/')[-1] u = urllib2.urlopen(url) f = open(file_name, 'wb') meta = u.info() file_size = int(meta.getheaders("Content-Length")[0]) print "Downloading: %s Bytes: %s" % (file_name, file_size) file_size_dl = 0 block_sz = 8192 while True: buffer = u.read(block_sz) if not buffer: break file_size_dl += len(buffer) f.write(buffer) status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size) status = status + chr(8)*(len(status)+1) print status, f.close()المصدر
-
الفرق بينهم سهل للغاية، فتعتبر require_relative مكملا للتابع المدمج في الروبي require لأنها تسمح لك بتحميل ملف متعلق بملف آخر يحتوي على العبارة require_relative. فعلى سبيل المثال، لو كان لديك أصناف وحدة test في مجلد "test”، وأما البيانات التابعة لها موجودة في مجلد "test/data"، لذلك سوف تستخدم سطر مشابه لهذا في هذه الحالات للاستدعاء: require_relative "data/customer_data_1" أي أن استخدام require_relative هي إحدى الطرق لاستدعاء الوحدات في مجلدات المشروع خاص بك. ويمكن تفسير أن السطر التالي لاستدعاء path عن طريق require_relative: require_relative('path') مشابه للسطر التالي لنفس الاستدعاء لكن عن طريق require: require(File.expand_path('path', File.dirname(__FILE__)))المصدر
-
إذا كان نظام حاسوب صديقك يعمل بنظام لينكس فأغلب توزيعات لينكس مثبت عليها لغة البايثون بشكل افتراضي لذلك يمكنه تشغيل هذا البرنامج (مثالك) بسهولة عن طريق هذا الأمر(نفترض أن ملف البرنامج يدعى file.py): python file.pyأما لو كنت سترسل البرنامج لصديق لك لديه حاسوب يعمل بنظام ويندوز ففي هذه الحالة يجب عليك الاستعانة ببرامج مثل py2exe الذي يقوم بتحويل ملفات البايثون إلى exe حتى يتمكن صديقك من تشغيل برنامجك على نظام تشغيل ويندوز، ومن أشهر البرامج التي تستخدم py2exe برنامج التورنت BitTorrent بالإضافة إلى SpamBayes. ولقد تم في الإصدار py2exe الجديد دعم الإصدار الثالث من البايثون.
-
الفرق أن p a تقوم بنفس وظيفة puts a.inspect، ولفهم الفرق سأقوم بشرح قصير لـ inspect. تقوم inspect بتفقد العبارة قبل الطباعة فإذا كانت من نوع سلسلة نصية فسوف تجعلها بين رمزي " أما لو كانت رقم صحيح أو غيره فإنه ستقوم بطباعته بشكل عادي، بالإضافة إلى ذلك فإنها تضيف إلى نهاية النص أو الرقم سطر جديد. تقوم puts بطباعة جميع النتائج بعد تطبيق to_s إلى الكائن بينما تقوم p بطباعة النتيجة بعد تطبيق inspect إليها. المصدر
-
هنالك العديد من الطرق لإغلاق السكربتات في البايثون، ومن أشهر هذه الطرق استخدام دالة exit من مكتبة sys، والذي يمكنك استخدامها كما في المثال التالي: import sys sys.exit() كما يمكنك استدعاء الدالة فقط من المكتبة حتى تختصر الشيفرة البرمجية التي تقوم بكتابتها كالتالي: from sys import exit exit()ومن الطرق الأخرى المشهورة لإغلاق السكربت استخدام هذه العبارة: raise SystemExitومن أسهل وأبسط الطرق لإغلاق سكربت بايثون هي عن طريق استخدام الدالة المدمجة quit() والتي لا تحتاج إلى استدعاء أية مكتبات أو وحدات أخرى، مثال على استخدام هذه الدالة: #do stuff if this == that: quit()المصدر
-
أفضل حل بالنسبة لي هو هذا الحل: def file_len(fname): with open(fname) as f: for i, l in enumerate(f): pass return i + 1 فإنك لن تحصل على حل أفضل منه، وعلى أية حال لن تتمكن من معرفة عدد الأسطر في ملف ما دون قراءة كامل الملف، ومن ثم حساب عدد الأسطر عن طريق حساب عدد تكرار \n ومن ثم طباعة النتيجة كما في المثال السابق. وكما قلت سابقا لا توجد أية طريقة لمعرفة هذه الأسطر دون قراءة كامل الملف، لأن أفضل حلول ستكون دائما مرتبطة بقراءة ذلك الملف، وأفضل ما يمكنك فعله هو التأكد أنك لا تقوم باستخدام الذاكرة بصورة غير ضرورية والتي قد حاولنا حلها في المثال السابق. المصدر
-
يحمل المتغير __File__ المسار النسبي الذي تم إنشائه وخزنه (لكنه لن يتغير أبدأ أثناء تشغيل البرنامج) عندما تم تحميل الملف إلى ذاكرة الحاسوب، وهذا معناه أنه لو قمت بتغيير المجلد الحالي أثناء تشغيل البرنامج عن طريق Dir.chdir في أي مكان في تطبيقك فلن تحصل على نتيجة مغايرة للتي حصلت عليها في البداية: puts __FILE__ Dir.chdir '../../' puts __FILE__ سوف تحصل في هذه الحالة على اسم الملف ولكنك لن تحصل على مساره الكامل ولحل هذه المشكلة سوف نستخدم تابع expand_path على الشكل التالي: $MY_FILE_PATH = File.expand_path(File.dirname(__FILE__)) # open class and do some stuff that changes directory puts $MY_FILE_PATHوالآن سوف تحصل على مسار الملف بالكامل ويمكنك تغيير المسار كما تريد عن طريق Dir.chdir كما في المثال السابق. المصدر
-
هنالك عدة طرق لدمج مصفوفتين مع بعض في الروبي، فيمكنك الاستعانة بتابع concat الذي سيقوم بسَلسَلة المصفوفتين كما في المثال التالي: a1.concat a2 a1 + a2 # creates a new array, as does a1 += a2 أو يمكنك الدمج باستخدام تابعي push و unshift كما في المثال التالي: a1.push(*a2) # note the asterisk a2.unshift(*a1) # note the asterisk, and that a2 is the receiver يذكر أنه عند استخدام unshift في المثال أعلاه أصبح a2 هو مُستقبِل المصفوفة الأولى. ويمكنك أيضا لصق المصفوفة الأولى مع المصفوفة الثانية بمساعدة التوابع length و insert كما في المثال التالي: a1[a1.length, 0] = a2 a1[a1.length..0] = a2 a1.insert(a1.length, *a2) والطريقة الأخيرة هي الحاق المصفوفة الأولى بالمصفوفة الثانية عن طريق flatten! الذي سيقوم بإنشاء مصفوفة جديدة: (a1 << a2).flatten! # a call to #flatten instead would return a new arrayالمصدر
-
يعتبر Dir.foreach خيار جيد لتكرار الأوامر على الملفات، لكن يجب أن تعرف أن Dir.foreach و Dir.entries سيقومون دائما بإظهار . و .. (المجلد الحالي والمجلد الأب)، وأنت في العادة لا تريد العمل عليها، لذلك تستطيع التخلص منهم بسهولة عن طريق شيفرة برمجية مشابه لهذه: Dir.foreach('/path/to/dir') do |item| next if item == '.' or item == '..' # do work on real items end Dir.foreach و Dir.entries يقومان بإظهار جميع العناصر في المجلد، سواء أن كانت هذه العناصر مخفية أو غير مخفية، وهذا في العادة ما تريده لكن إذا لم ترد ذلك، فيمكنك القيام بعملية تجاوز للملفات والمجلدات المخفية. كما يمكنك استخدام Dir.glob الذي يوفر إمكانية اختيار ملفات ذات امتداد معين كما في المثال التالي: Dir.glob('/path/to/dir/*.rb') do |rb_file| # do work on files ending in .rb in the desired directory endالمصدر
-
يقوم system بتنفيذ أمر النظام الذي سوف تقوم بتمريره عن طريق سلسلة نصية إلى هذا التابع كما في المثال التالي: >> system("date") Wed Sep 4 22:03:44 CEST 2013 => true إذا تم تنفيذ الأمر بدون مشاكل فسيقوم بإرجاع true كما في المثال أعلاه. أما رموز Backticks (``) فهي تقوم بتنفيذ أوامر النظام وتقوم بإرجاع الناتج، أي إذا قمت بوضع الأمر بين رموز Backticks في متغير فسيحمل ذلك المتغير ناتج الأمر كما في المثال التالي: >> `date` => Wed Sep 4 22:22:51 CEST 2013 أما بالنسبة إلى %x() فهي تعمل بنفس عمل backticks ويمكن استخدامها بطرق متعددة مثل %x(date) و %x{date} و %x-date-. وإذا قمت باستخدام exec فسيقوم هذا التابع بإلغاء هذه العملية -process- (يتم إيقاف سكربت روبي) ليقوم بتنفيذ أمر النظام. المصدر
-
هذه الملفات تحتوي على Bytecode والذي يقوم مفسر البايثون بترجمته من ملف المصدر، ومن ثم يتم تنفيذه من قبل الآلة الافتراضية للبايثون (Python's virtual machine). وثائق البايثون الرسمية تُفسر الأمر كالتالي: أي أن عن طريق ملفات bytecode يمكن تشغيل برامج البايثون مباشرة وبشكل أسرع دون الاضطرار إلى إنشاء ملف تنفيذي للبرنامج. المصدر
-
الطريقة التي قمت بها صحيحة وليس بها أي مشكل في التعامل معها، لكن بما أنك أردت طريقة أخرى فيمكنك في هذه الحالة استخدام self. فسيقوم self بالعودة إلى اسم الصنف أي self هي Truck في مثالك أي أننا بدل أن نكتب اسم الصنف Truck قمنا بكتابة self بشكل عام، ولتفهم أكثر ألق نظرة على هذا المثال: class Foo def self.some_class_method puts self end def some_instance_method self.class.some_class_method end end print "Class method: " Foo.some_class_method print "Instance method: " Foo.new.some_instance_methodحسنا والآن عند تشغيل هذا البرنامج سيظهر لنا التالي: Class method: Foo Instance method: Fooحيث قمنا في المرة الأولى باستدعاء اسم التابع من الصنف وفي المرة الثانية قمنا باستدعاء اسم التابع من المثيل. المصدر
-
يمكنك استخدام العدد الذي تريد من المؤشرات في برنامجك (حسب قدرات حاسوبك)، فمستوى واحد أو إثنين هو الأكثر شيوعا، وثلاثة مستويات فهو أمر نادر أما العدد لا نهائي من المؤشرات فهو شيء شائع نوعا ما. العدد اللانهائي من المؤشرات يتم تحقيقه بمساعدة struct وليس عن طريق الإعلان المباشر والذي هو مستحيل، كما في المثال التالي (مثال بسيط على Struct): struct list { struct list *next; ... };أي بشكل نظري يمكنك إنشاء أي عدد من المستويات التي تريدها لكن بشكل عملي لا يمكنك استهلاك حجم الذاكرة بشكل لا نهائي، لأنه ستكون هنالك حدود لموارد الحاسوب. المصدر
-
هنالك عدة طريق للقيام بذلك، فيمكنك استخدام وحدة Pathname (فهي حسب التوثيق الرسمي تعمل على ويندوز بدون مشاكل) لاستخراج اسم الملف من مسار كما في المثال التالي: irb(main):007:0> require 'pathname' irb(main):007:0> File.new('/opt/local/bin/ruby').basename => #<Pathname:ruby> وإذا كنت تعرف الامتداد فيمكنك استخدام File.basename مع ذكر اسم الامتداد حتى يتم إرجاع اسم الملف بدون الامتداد، لأن File.basename تقوم بإرجاع آخر جزء من اسم الملف في المسار والذي سيكون مفصولا بواسطة "/” كما في المثال التالي: File.basename("/home/gumby/work/ruby.rb") #=> "ruby.rb" File.basename("/home/gumby/work/ruby.rb", ".rb") #=> "ruby" كما يمكنك أيضا وضع نجمة * في مكان الامتداد لحذف جميع الامتدادات كما في المثال التالي: File.basename("C:\\projects\\win.dll", ".*") #=> "win"المصدر
-
هنالك عدة طرق لوضع وقت نسبي، فمثلا إذا كنت تستخدم ريلز 3 أو 4 يمكنك استخدام تابع time_ago_in_words والذي سيقوم بحساب الوقت المنقضي منذ إنشاء الملف، على سبيل المثال يُمكنك كتابة شيء مشابه لهذا إذا كنت في العرض (view): <%= time_ago_in_words(Date.today - 1) %>أما لو كنت في المتحكم فيجب عليك في هذه الحالة استدعاء DateHelper من ActionView ومن ثم استخدام تابع time_ago_in_words كما في المثال التالي: include ActionView::Helpers::DateHelper def index @date_ago = time_ago_in_words(Date.today - 1) end ملاحظة: المتحكمات لا تقوم باستدعاء وحدة ActionView::Helpers::DateHelper بشكل افتراضي لذلك يجب استدعائها يدويًا كما في المثال. يمكنك أيضًا انشاء دالتك الخاص لحساب الوقت كما في هذا المثال: module PrettyDate def to_pretty a = (Time.now-self).to_i case a when 0 then 'just now' when 1 then 'a second ago' when 2..59 then a.to_s+' seconds ago' when 60..119 then 'a minute ago' #120 = 2 minutes when 120..3540 then (a/60).to_i.to_s+' minutes ago' when 3541..7100 then 'an hour ago' # 3600 = 1 hour when 7101..82800 then ((a+99)/3600).to_i.to_s+' hours ago' when 82801..172000 then 'a day ago' # 86400 = 1 day when 172001..518400 then ((a+800)/(60*60*24)).to_i.to_s+' days ago' when 518400..1036800 then 'a week ago' else ((a+180000)/(60*60*24*7)).to_i.to_s+' weeks ago' end end end Time.send :include, PrettyDateالمصدر