ምዕራፍ 9 የላቀ መግቢያ

ምዕራፍ 8 ላይ የበለጸገው መሰረታዊ የመግቢያ ስርዓት ሙሉ በሙሉ የሚሰራ ነው፤ ነገር ግን አብዛኛዎቹ ዘመናዊ ድረጣቢያዎች ተጠቃሚዎች ጣቢያቸውን ጎብኝተው አሳሻቸውን ለጊዜው ቢዘጓቸውም እንኳ፤ የነበሩበትን ጣቢያ እንደገና ተመልሰው ሲጎበኙ አሳሹ ተጠቃሚዎቹን ማስታወስ የሚችል አንድ “የመዘከር” ችሎታን በአሳሹ ላይ ያካትታሉ፡፡ በዚህ ምዕራፍ ውስጥ ይህንን ባህሪ ለመተግበር ቛሚ ብስኩቶችን እንጠቀማለን፡፡ ተጠቃሚዎች ልክ ሲገቡ መለያቸውን በራስሰር በማስታወስ ስራችንን እንጀምራለን(ክፍል 9.1)፤ ይህም እንደ ቢትባኬት እና ጊትሃብ በመሳሰሉ ጣቢያዎች ላይ ጥቅም ላይ የዋለ አንድ የተለመደ ቅድ ነው፡፡ ከዚያ በመቀጠልም አንድ የ“ዘክረኝ” አመልካችሳጥንን በመጠቀም ተጠቃሚዎች በምርጫቸው መለያቸው በአሳሹ ላይ እንዲቆይ የሚፈልጉ ከሆነ፣ አሳሹ መለያቸውን እንዲያዘካክራቸው የሚያደርግ አንድ ችሎታን እናክላለን፤ ይህም እንደ ትዊተር እና ፌስቡክ በመሳሰሉ ጣቢያዎች ላይ ጥቅም ላይ የዋለ አንድ የተለመደ ቅድ ነው፡፡

ምዕራፍ 8 ላይ የተሰራው የድሩ የመግቢያ ስርዓት ራሱን ችሎ የሚሰራ እና ሙሉ በሙሉ የተሟላ ስለሆነ፣ የማሳያ አፕልኬሽኑ ዋና አካል “ዘክረኝ” ሳይጨመርበትም በጥሩ ሁኔታ ይሰራል፤ ስለዚህ ካስፈለገ በቀጥታ ወደ ምዕራፍ 10 ከዚያም ካስፈለገ ወደ ምዕራፍ 13 ዘላችሁ ማለፍ ትችላላችሁ፡፡ በሌላ በኩል ደግሞ የ“ዘክረኝ” ባህሪን እንዴት ተግባራዊ ማድረግ እንደሚቻል መማሩ ራሱ፣ እጅግ አስተማሪ እና ቀጥለን ለምንመለከታቸው ማለት ለመለያ ግባሬ (ምዕራፍ 11) እና ለመሕለፈቃል ዳግመጅማሬ (ምዕራፍ 12) ስራ ላይ በጣም አስፈላጊ የሆነ አንድ መሰረትን ያስቀምጣል። ከዚህ በላይም ውጤቱ አንድ የላቀ የኮምፒዩተር አስማት ምሳሌ ይሆናል፤ በቢሊዮን በሚቆጠሩ የድሮች የመግቢያ ቅጽ ላይ “ዘክረኝ (remember me)” የሚለውን ጽሑፍ አይታችኋል፣ አሁን ደግሞ እናንተ ይህንን አጋጣሚ በመጠቀም ይህንኑ ገጸባህሪ በድራችሁ ላይ እንዴት አድርጋችሁ እንደምትሰሩ ለመማር እድሉን ይሰጣችኋል።

9.1 ዘክረኝ

በዚህ ክፍል ውስጥ ተጠቃሚዎቻችን በድራችን ውስጥ ከገቡ በኋላ አሳሻቸውን ዘግተው እንደገና ተመልሰው አሳሻቸውን ቢከፍቱም እንኳ፣ በድራችን ውስጥ ከድሮውም እንደገቡ የሚዘክር አንድ ችሎታን በአፕልኬሽናችን ላይ እናክላለን፡፡ ይህ የ “ዘክረኝ” ባህሪ በራስሰር ይከናወናል፤ እናም የድሩ ተጠቃሚዎች እራሳቸው ሆን ብለው ከድሩ እስካልወጡ ድረስ በራስሰር እንደገቡ ይቆያሉ፡፡ ለወደፊቱ እንደምናየው፣ ከዚህ የሚገኘው ፋብሪካ የ “ዘክረኝ” ን አማራጫዊ የአመልካችሳጥን ባህሪን በአፕልኬሽኑ ላይ ለማከል ቀላል ያደርገዋል (ክፍል 9.2)፡፡

ከመቀጠላችሁ በፊት እንደተለመደው፣ አንድ ርእስ ቅርንጫፍ እንድትፈጥሩ ምክሬን ከወዲሁ እለግሳለሁ፡-

$ git checkout -b የላቀ-መግቢያ

9.1.1 ዝክረ ይስሙላ እና ፈጪ

ክፍል 8.2 ውስጥ፣ የተጠቃሚ-መታወቂያን ለማከማቸት የሬይልስን የ‘ክፍለጊዜ (session) ዘዴን ተጠቅመን ነበር፤ ነገር ግን ተጠቃሚው የሚጠቀምበትን አሳሽ በሚዘጋበት ጊዜ መረጃው ይጠፋል፡፡ በዚህ ክፍል ውስጥ ብስኩቶች (cookies) የተባለውን ዘዴ በመጠቀም፣ ቋሚ ብስኩቶችን ለመፍጠር አንድ ተስማሚ ዝክረ ይስሙላን በማመንጨት እና እነዚህን ይስሙላወች ለሚያረጋግጥ አንድ ጥብቅ ዝክረ ፈጪን (remember digest) አብረን በማከል የመጀመሪያውን ሂደት እናከውናለን።

ክፍል 8.2.1 ላይ የ‘ክፍለጊዜ (session) ዘዴን በመጠቀም ክፍለጊዜወች ላይ መረጃ ማከማቸቱ በራስሰር ጥብቅ እንደሆነ ተመልክተናል፤ የ‘ብስኩቶች (cookies) ዘዴን ተጠቅሞ የብስኩቶችን መረጃ ብስኩቶች ላይ ማከማቸት ግን ከዚያ ለየት ይላል። በተለይም ቋሚ ብስኩቶች ለክፍለጊዜ ጠላፋ የተጋለጡ ናቸው፤ በዚህ ምክንያትም አንድ አጥቂ የተሰረቀ ብስኩቶችን በመጠቀም እንደ ጤነኛ ተጠቃሚ ሁኖ ሊገባ ይችላል፡፡ አጥቂወች ብስኩቶችን ሊሰረቁባቸው የሚችሉትበት አራቱ ዋና መንገዶች እነዚህ ናቸው፡- (1) ጥብቅ ባልሆነ አውታረመረቦች በኩል እያለፉ ያሉ ብስኩቶችን ለማግኘት አንድ “ፓኬት ስኒፈር” የተባለ ፕሮግራምን መጠቀም፣1 (2) ዝክረ ይስሙላውን የያዘ አንድ ውሂበጎታ ከተጠለፈ፣ (3) ድር ሰበር ስክሪፕትን (ድ.ሰ.ስ) በመጠቀም እና (4) ባለቤቱ ከተጠቀመ በኋላ ሳይወጣ ረስቶት የሄደ፣ አንድ የመሳርያ አካላዊ መዳረሻን ማግኘት ናቸው፡፡

የመጀመሪያውን ችግር ለመከላከል ማለት የአውታረመረብ ውሂብን፣ ፓኬት ስኒፈር የተባለውን ፕሮግራም ተጠቅመው ከሚያጠቁ አጥቂወች ለመከላከል ጥብቅ የመሰኪያወች ንጣፍ የተባለውን ሶፍትዌር በክፍል 7.5 ውስጥ በመጠቀም ሙሉውን ጣቢያ ተከላክለናል። ሁለተኛውን ችግር ለመከላከ ደግሞ፣ በክፍል 6.32 ላይ ከጥሬው መሕለፈቃል ይልቅ መሕለፈቃሉን ፈጪተን፣ ፍጪውን መሕለፈቃል ውሂበጎታው ውስጥ እንዳከማቸን ሁሉ፤ አሁንም ይስሙላውን እራሱን፣ እንዳለ አንድ ውሂበጎታ ውስጥ ከማከማቸት ይልቅ፣ ይስሙላውን በመፍጨት፣ የተፈጨውን ይስሙላ አንድ ውሂበጎታ ውስጥ በማከማቸት ይህንን ችግር እንከላከላለን፡፡ ሶስተኛውን ችግር ደግሞ ሬይልስ ራሱ በትይታ ዝግጁገጽታ ውስጥ የገባን ማንኛውንም የስክሪፕት ይዘት በመዝለል በራስሰር ይከላከልልናል። በመጨረሻም፣ ተጠቃሚ ገብቶ የረሳውን መሳርያ (ለምሳሌ ኮምፒተር) የሚያጠቁ አጥቂወችን ለመከላከል መሳርያውን ብረት የሚያለብስ መንገድ ባይኖርም፣ አንድ ተጠቃሚ ዘግቶ ሲወጣ አሳሹ ላይ ያሉ ይስሙላወችን በመለወጥ እና በአሳሹ ላይ የምናከማቸውን ማንኛውም ሚስጥራዊ መረጃ የዲጅታል ፊርማ እንዲኖረው አስፈላጊውን ጥንቃቄ በማድረግ አራተኛው ችግር ላይ የሚደርሰውን አበሳ መቀነስ እንችላለን።

(ይህ አሁንም ጊዜያዊ ክፍለጊዜወችን ለክፍለጊዜ ዳግመጫወታ ጥቃቶች ያጋልጣል፤ ይህም በክፍል 8.2.1 ላይ እንደተመለከተው፣ ግራም ነፈሰ ቀኝ አሳሹ ልክ ሲዘጋ ስለጠፉ ብዙም የሚያሳስብ አይደለም፡፡ የክፍለጊዜ ብስኩቶችን ለመስረቅ ብቸኛው ቀሪ ዘዴ፣ መሳሪያውን (ለምሳሌ ኮምፕዩተሩን) በአካል በመዳረስ ሲሆን፤ እናም እዚህ ሁኔታ ላይ አጥቂው ቀድሞውኑ የገባ ስለሚሆን ይህ አንድ ረቀቅ ያለ (የጠርዝ ጉዳይ (Edge Case)) ይሆናል፡፡ የሆነ ሆኖ፣ እንደ ዲቫይስ ያሉ እጅግ የላቁ የማረጋገጫ ስርዓቶች በተናጥል ጊዜው ሊያበቃ የሚችል አንድ የክፍለጊዜ ይስሙላን በመጠቀም ይህንን ሁኔታ ያስተናግዳሉ (መታወቂያውን ብቻ የሚጠቀመው የአሁኑ ዘዴ ግን መታወቂያው የማይለዋወጥ ስለሆነ፣ ክፍለጊዜዎች ጊዜያቸው እንዲቃጠል አይፈቅድልንም)፡፡ አፕልኬሽኑ አንድ የክፍለጊዜ ይስሙላን እንዲጠቀም ማዘመኑ እንደ መልመጃ (ክፍል 9.3.2.1) ይሆናችሁ ዘንድ ለናንተ የተተወ ሲሆን፣ መፍትሄው ደግሞ በአፕ ማጣቀሻ ስር ባለው የ‘ክፍለጊዜ-ይስሙላ (session-token) ቅርንጫፍ ላይ ይገኛል፡፡

እነዚህን የንድፍ እና የጥበቃ ጉዳዮች በግምት ውስጥ በማስገባት፣ ቋሚ ክፍለጊዜወችን ለመፍጠር ያስቀመጥነው እቅድ እንደሚከተለው ይቀርባል:-

  1. ለዝክረ ይስሙላ መጠቀሚያ የሚሆን አንድ የነሲብ ፍጪ ሃረግን መፍጠር፣
  2. ይስሙላው የሚቃጠልበትን ቀን ራቅ አድርጎ አሳሹ ውስጥ በሚገኙት ብስኩቶች ውስጥ ማስቀመጥ፣
  3. የተከተፈውን ይስሙላ በውሂበጎታው ውስጥ ማስቀመጥ፣
  4. የተመሰጠረውን የተጠቃሚ-መታወቂያ በአሳሹ ብስኩቶች ላይ ማስቀመጥ እና
  5. አንድ ብስኩት የአንድ ተጠቃሚ-መታወቂያን ሲያቀርብ፣ የቀረበውን መታወቂያ በመጠቀም ተጠቃሚውን ከውሂበጎታው መፈለግ እና የዝክረ ይስሙላ ብስኩቱ ውሂበጎታ ውስጥ ካለው ተጓዳኝ ክትፍ ይስሙላ ጋር መዛመዱን ማረጋገጥ ይሆናል፡፡

አምስተኛው ሂደት፣ አንድ ተጠቃሚን ወደ ጣቢያችን ለማስገባት ከምንጠቀምበት ሂደት ጋር ምን ያህል ተመሳሳይ እንደሆነ ልብ በሉ፤ ማለት ተጠቃሚውን በኤመልእክት አድራሻው ፈልገን ከምናመጣበት እና ከዚያ (የ‘አረጋግጥ (authenticate) ዘዴን በመጠቀም) የተረከበው መሕለፈቃል ከመሕለፈቃል ፈጪው ጋር የሚዛመድ መሆኑን (ዝርዝር 8.7) ለማወቅ የሰራንበት ጋር ማለት ነው። በዚህም ምክንያት ትግበራችን ከ‘ጥብቅ_መሕለፈቃል_አለው (has_secure_password) ጋር ትይዩ የሆነ ገጽታዎችን ይይዛል።

ምስል 9.1 እንደሚታየው፣ አስፈላጊውን የ‘ዝክረ_ፈጪ (zkre_fech) ባሕሪ በተጠቃሚ ቅርጸቱ ውስጥ በማከል እንጀምራለን።

user_model_remember_digest
ምስል 9.1: አንድ የ‘ዝክረ_ፈጪ (zkre_fech) ባሕሪ የታከለበት የተጠቃሚ ቅርጸት፡፡

ምስል 9.1 ላይ የተመለከተውን የውሂብ ቅድ ወደ አፕልኬሽናችን ለማከል አንድ ፍልሰትን እናመነጫለን:-

$ rails generate migration add_zkre_fech_to_teteqamis zkre_fech:string

(ይህንን ክፍል 6.3.1 ውስጥ ካለው የመሕለፈቃል ፈጪ ፍልሰት ጋር ስታነጻጽሩ።) ልክ እንዳለፉት ፍልሰቶች ሁሉ፣ ፍልሰቱ ተጠቃሚዎች (teteqamis) ሰንጠረዥ ላይ ለውጥ የሚደረግ መሆኑን ሬይልስን ለመንገር መጨረሻው _ወደ_ተጠቃሚዎች (_to_teteqamis) የሆነ የፍልሰት ስምን ተጠቅመናል፡፡ የ‘ባሕሪ ስም ዝክረ_ፈጪ (zkre_fech) ፣ የውሂብ ዓይነት ደግሞ ሃረግ (string) ብለን ስላካተትን፣ ሬይልስ በዝርዝር 9.1 ላይ የሚታየውን አንድ ነባሪ ፍልሰት አመንጪቶልናል።

ዝርዝር 9.1: ለዝክረ ፈጪው የመነጨ አንድ ፍልሰት። db/migrate/[ማህተመሰዓት]_add_zkre_fech_to_teteqamis.rb
class AddZkreFechToTeteqamis < ActiveRecord::Migration[6.0]
  def change
    add_column :teteqamis, :zkre_fech, :string
  end
end

ተጠቃሚዎችን ከውሂበጎታው ፈልጎ ለማውጣት ዝክረ ፈጪውን ስለማንጠቀም፣ በ‘ዝክረ_ፈጪ (zkre_fech) አምድ ላይ አንድ የመረጃ-ጠቋሚ ማድረግ አያስፈልገንም፤ ስለሆነም፣ ከዚህ በላይ የመነጨውን ነባሪውን ፍልሰት ልክ እንዳለው ልንጠቀምበት እንችላለን:-

$ rails db:migrate

አሁን አንድ ዝክረ ይስሙላን ለመስራት የትኛውን መንገድ መጠቀም እንዳለብን መወሰን አለብን። በጣም ብዙ እና ስራውን በአንድ ዓይነት መልኩ ሊሰሩ የሚችሉ አማራጮች አሉ፤ እንዳውም ማንኛውም ረዥም የነሲብ ሃረግን ተጠቅሞ ይህንን ስራ መስራትም ይቻላል፡፡ በሩቢ መደበኛ ቤተኮድ ላይ የሚገኘው የ‘አስተማማኝ-ዘፈቀደ (SecureRandom) ክፍለክፍል፣ የ‘ዓአሃአ_ደህንነቱየተጠበቀ_መሰረተ64 (urlsafe_base64) ዘዴ የሚፈለገውን መስፈርት ያሟላል።3 ይህ ዘዴ በአንድ ጥሪ ከ A–Z፣ a–z፣ 0–9፣ “-” እና በ “_” ሆሄወች የተዘጋጀ፣ እርዝመቱ 22 የሆነ አንድ የነሲብ ሃረግን ይመልሳል (በድምሩ 64 አማራጮች ስለሚያስገኝ “መሰረተ64 (base64)” ተብሎ ይጠራል)፡፡ አንድ መደበኛ የሆነ የመሰረተ64 ሃረግ እንደሚከተለው ሁኖ ይታያል:-

$ rails console
>> SecureRandom.urlsafe_base64
=> "brl_446-8bqHv87AQzUj_Q"

ሁለት ተጠቃሚዎች የተለያየ መሕለፈቃል እንዲኖራቸው ቢመረጥም፣4 አንድ ዓይነት መሕለፈቃል ቢኖራቸው ምንም ችግር አያመጣም፤ ዝክረ ይስሙላወችም ይህንን የተጠቃሚዎች የመሕለፈቃል ልዩ መሆን አይጠብቁም።5 ከዚህ በላይ ባለው ያየነውን የመሰረተ64 ሃረግን በተመለከተ፣ እያንዳንዱ 22 ሆሄወች አሁን ካሉበት የተለዩ ለመሆን \( 64^{22} \) የተለያዩ አማራጮች አሏቸው፡፡ ስለዚህ ሁለት አንድ ዓይነት የሆኑ ዝክረ ይስሙላወች አንድ ዓይነት የመሆናቸው እድል እጅግ አነስተኛ ነው \( 1/64^{22} = 2^{-132} \approx 10^{-40} \)፡፡6 (ከ‘ዓአሃአ_ደህንነቱየተጠበቀ_መሰረተ64 (urlsafe_base64) በሚለው ስሙ እንደተመለከተው) በዓ.አ.ሃ.አ ላይ ጥብቅ እንዲሆን ተደርጎ የተሰሩትን መሰረተ64 ሃረጎችን በመጠቀም፣ የመለያ ግባሬ እና የመሕለፈቃል ዳግመጅማሬ አገናኞችን ለመስራት፣ በምዕራፍ 12 ውስጥ ይህንኑ የይስሙላ ማመንጪያ እንጠቀማለን።

የተጠቃሚዎችን መለያ የማስታሱ ሂደት፣ አንድ የሚዘክር ይስሙላን መፍጠርን እና የተፈጨውን ዝክረ ይስሙላ በውሂበጎታው ውስጥ ማስቀመጥን ያሳትፋል፡፡ ከዚህ በፊት በእቃ ፈተና ላይ ለመጠቀም ብለን አንድ የ‘ፈጪ (fech) ዘዴን በይነናል (ዝርዝር 8.25)። እናም ከላይ የተዘረዘረውን ውይይት ጥቅም ላይ ለማዋል ማለት አንድ አዲስ ይስሙላን ለመፍጠር አንድ አዲስ_ይስሙላ (adis_ysmula) የተባለ ዘዴን እንፈጥራለን። ልክ እንደ ፈጪ‘ው (fech) ዘዴ የአዲስ ይስሙላ ዘዴውም የተጠቃሚ ቁስን አይፈልግም፤ ስለሆነም ዘዴውን የክፍል ዘዴ እናደርገዋለን።7 ውጤቱም በዝርዝር 9.2 ላይ የተጠቃሚ ቅርጸት ውስጥ ይታያል፡፡

ዝርዝር 9.2: አንድ ይስሙላወችን የሚያመነጪ ዘዴን ማከል። app/models/teteqami.rb
class Teteqami < ApplicationRecord
  before_save { emelekt.downcase! }
  validates :sim,  presence: true, length: { maximum: 50 }
  BQU_YE_EMELEKT_MEDEBEGNA_HISABEHEREG =/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :emelekt, presence: true, length: { maximum: 255 },
                    format: { with: BQU_YE_EMELEKT_MEDEBEGNA_HISABEHEREG },
                    uniqueness: true
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }

  # ለተሰጠው ሃረግ አንድ የተከተፈ ፍጪን ይመልሳል።
  def Teteqami.fech(hereg)
    waga = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(hereg, cost: waga)
  end

  # አንድ ነሲብ ይስሙላን ይመልሳል።
  def Teteqami.adis_ysmula
    SecureRandom.urlsafe_base64
  end
end

ይህንን ተግባር ላይ ለማዋል እቅዳችን፣ የተጠቃሚውን ዝክረ ይስሙላ ከተጠቃሚው ጋር የሚያዛምድ እና የተዛመደውን ዝክረ ፈጪ በውሂበጎታው ውስጥ የሚያስቀምጥ አንድ ተጠቃሚ.ዘክር (teteqami.zekr) የተባለ ዘዴን መስራት ነው። በዝርዝር 9.1 ላይ በተደረገው የፍልሰት ትእዛዝ ምክንያት፣ የተጠቃሚ ቅርጸቱ አንድ የ‘ዝክረ_ፈጪ (zkre_fech) ባሕሪ ሲኖረው፤ የ‘ዝክረ_ይስሙላ (zkre_ysmula) ባሕሪ ግን እስካሁን የለውም፡፡ ይዞታቸውን በውሂበጎታው ውስጥ ሳናከማች በ‘ተጠቃሚ.ዝክረ_ይስሙላ (teteqami.zkre_ysmula) ዘዴ በኩል ይስሙላወችን የምናገኝበት አንድ መንገድ ያስፈልገናል (ተጠቃሚ.ዝክረ_ይስሙላ (teteqami.zkre_ysmula) በብስኩቶቹ ውስጥ ይስሙላወችን ለማከማቸት ያገለግለናል)፡፡ ይህንን ተማሳሳይ ችግር ካሁን በፊት በክፍል 6.3 ውስጥ አንድ ጥብቅ መሕለፈቃልን ስንሰራ፣ አንድ መሕለፈቃል (password) የተባለ ምናባዊ ባሕሪን ውሂበጎታ ላይ ካለው ከ‘መሕለፈቃል_ፈጪ (password_digest) ባሕሪ ጋር እንዲጣመር በማድረግ ፈተነዋል። የ‘መሕለፈቃል (password) ባሕሪው ጥብቅ_መሕለፈቃል_አለው (has_secure_password) በተባለው ዘዴ በራስሰር የተፈጠረ ሲሆን፣ የ‘ዝክረ_ይስሙላ (zkre_ysmula) ባሕሪውን ለመፍጠር ግን እራሳችን ኮዱን መጻፍ ይኖርብናል። ይህንን አሰራር ተግባራዊ ለማድረግ በክፍል 4.4.5 ላይ ቀደም ብለን እንዳየነው፣ ተደራሽ ባሕሪን ለመፍጠር አንድ የ‘ባሕሪ_መዳረሻ‘ን (attr_accessor) መጠቀም ይሆናል፡፡

class Teteqami < ApplicationRecord
  attr_accessor :zkre_ysmula
  .
  .
  .
  def zekr
    self.zkre_ysmula = ...
    update_attribute(:zkre_fech, ...)
  end
end

በ‘ዘክር (zekr) ዘዴ ውስጥ ያለውን የመጀመሪያ መስመር የአመዳደቡን ቅርጽ አስተውሉ፡፡ ሩቢ በቁስ ውስጥ የተደረጉ ምደባወች ራሥ (self) የተባለ ቁልፈቃል ከሌላቸው፣ ልክ እንደ አንድ የሰፈር ተለዋዋጪ አድርጎ ይቆጥራቸዋል፤ ዝክረ_ይስሙላ (zkre_ysmula) የተባለውን ተለዋዋጪ ያለ ራሥ (self) ቁልፈቃል ብንተወው፣ በአሁኑ ጊዜ የማንፈልገውን ዝክረ_ይስሙላ (zkre_ysmula) የተባለ የሰፈር ተለዋዋጪን ይሰጠን ነበር፤ የ‘ራሥ (self) ቁልፈቃልን መጠቀሙ ግን ምደባው የተጠቃሚውን የ‘ዝክረ_ይስሙላ (zkre_ysmula) ባሕሪን እንደሚያዘጋጅ የተሟላ እርግጠኝነትን ይሰጠናል። (በዝርዝር 6.32 ውስጥ ያለው የ‘ከማስቀመጥ_በፊት (before_save) መልሰጥሪ፣ ከ‘ኤመልእክት (emelekt) ይልቅ ለምን ራሥ.ኤመልእክትን (self.emelekt) እንደተጠቀመ እዚህ ላይ ተገንዝባችሁ ይሆናል።) ይህ በእንዲህ እንዳለ፣ ሁለተኛው የ‘ዘክር (zekr) መስመር ዝክረ ፈጪን ለማዘመን የ‘ባሕሪ_አዘምን (update_attribute) ዘዴን ይጠቀማል። (ክፍል 6.1.5 ላይ እንደተብራራው፣ ይህ ዘዴ ማስረገጫውን ዘሎ ያልፋል፣ እዚህ ላይ ይሄ ማስረገጫ አለመኖሩ በጣም አስፈላጊ ነው፤ ምክንያቱም የተጠቃሚውን መሕለፈቃልም ሆነ የመሕለፈቃል ማረጋገጫውን የመድረስ መንገዱ ስለለለን ነው፡፡)

እነዚህን ከግምት ውስጥ በማስገባት፣ በመጀመሪያ ተጠቃሚ.አዲስ_ይስሙላ (Teteqami.adis_ysmula) ዘዴን በመጠቀም፣ አንድ አዲስ ዝክረ ይስሙላን በመስራት፣ አንድ ብቁ ይስሙላን መፍጠር እና ፍጪውን ማዛመድ፤ እና ከዚያም ተጠቃሚ.ፈጪ‘ን (Teteqami.fech) በመተግበር በተገኘው ውጤት ዝክረ ፈጪውን ማዘመን እንችላለን፡፡ ይሄ ሂደት በዝርዝር 9.3 ላይ የሚታየውን የ‘ዘክር (zekr) ዘዴን ይሰጣል፡፡

ዝርዝር 9.3: በተጠቃሚ ቅርጸቱ ውስጥ አንድ የ‘ዘክር (zekr) ዘዴን ማከል። አረንጓዴ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  attr_accessor :zkre_ysmula
  before_save { self.emelekt = emelekt.downcase }
  validates :sim,  presence: true, length: { maximum: 50 }
  BQU_YE_EMELEKT_MEDEBEGNA_HISABEHEREG =/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :emelekt, presence: true, length: { maximum: 255 },
                    format: { with: BQU_YE_EMELEKT_MEDEBEGNA_HISABEHEREG },
                    uniqueness: true
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }

  # ለተሰጠው ሃረግ አንድ የተከተፈ ፍጪን ይመልሳል።
  def Teteqami.fech(hereg)
    waga = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(hereg, cost: waga)
  end

  # አንድ ነሲብ ይስሙላን ይመልሳል።
  def Teteqami.adis_ysmula
    SecureRandom.urlsafe_base64
  end

  # በቋሚ ክፍለጊዜዎች ውስጥ ለመጠቀም አንድ ተጠቃሚን በውሂበጎታው ውስጥ መዘከር።
  def zekr
    self.zkre_ysmula = Teteqami.adis_ysmula
    update_attribute(:zkre_fech, Teteqami.fech(zkre_ysmula))
  end
end

መልመጃዎች

የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።

የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡

  1. በሬይልስ ሰሌዳ ውስጥ፣ በውሂበጎታው ላይ ያለውን፣ የመጀመሪያ ተጠቃሚ ዋጋ ተጠቃሚ (teteqami) በተባለ ዋጋ መድቡ፣ ከዚያ የ‘ዘክር (zekr) ዘዴን ቀጥታ በተጠቃሚ (teteqami) ቁሱ ላይ በመጥራት ዘዴው እንደሚሰራ አረጋግጡ፡፡ ዝክረ_ይስሙላ‘ን (zkre_ysmula) ከ‘ዝክረ_ፈጪ (zkre_fech) ጋር ስታነጻጽሩ፣ ምን ዓይነት ልዩነት ተገነዘባችሁ?
  2. ዝርዝር 9.3 ውስጥ፣ አዲስ_ይስሙላ (adis_ysmula) እና አዲስ_ፈጪ (adis_fech) የተባሉ፣ ሁለት የክፍል ዘዴወችን፣ በግልጽ ከ‘ተጠቃሚ (Teteqami) ክፍል ጋር በማጣበቅ፣ ተጠቃሚ.አዲስ_ይስሙላ (Teteqami.adis_ysmula) እና ተጠቃሚ.ፈጪ (Teteqami.fech) ብለን ፈጠርን፣ እነሱም በ‘ተጠቃሚ (Teteqami) ክፍሉ ላይ፣ ተጠቃሚ.አዲስ_ይስሙላ (Teteqami.adis_ysmula) እና ተጠቃሚ.ፈጪ (Teteqami.fech) ብለው ስለሚጠሩ፣ በትክክል ይሰራሉ። ይህ በንዲህ እያለ፣ በዚህ ዓይነት መንገድ ዘዴወቹን መበየኑ በወቅቱ ነገሮችን ግልጽ ስለሚያደርግ ይህን ቅጥ ተጠቅመን ነበር፤ ነገር ግን ይህንን ለማድረግ ብዙ መንገዶች እንዳሉ ይታወቃል፡፡ ይህንን ግምት ውስጥ በማስገባት ኮዳችን ለማንበብ ምቹ ይሆን ዘንድ፣ ስነአጻጻፋቸው ትክክለኛ የሆኑ ሁለት የክፍል ዘዴወችን በመጠቀም፣ የክፍል ዘዴያችንን እናዛምነዋለን። መጀመሪያ ትንሽ ግራ የሚያጋባ የሚመስለውን ማለት በዝርዝር 9.4 ላይ ያለውን ኮድ በሚገባው ፋይል ውስጥ አስገቡ፤ ከዚያ ኮዱ መስራት እና አለመስራቱን ለማረጋገጥ የፈተና ስብስቡን አስኪዱ፤ ከዚያ በመቀጠል፣ በጣም ግራ የሚያጋባ የሚመስለውን ማለት በዝርዝር 9.5 ያለውን ኮድ በሚገባው ፋይል ውስጥ ካስገባችሁ በኋላ፣ ከዚያ እንደተለመደው፣ ኮዱ መስራት እና አለመስራቱን ለማረጋገጥ፣ አሁንም እንደገና የፈተና ስብስቡን አስኪዱ። (በዝርዝር 9.4 እና በዝርዝር 9.5 አውድ ውስጥ፣ ራሥ (self) ማለት ተጠቃሚ (Teteqami) ክፍሉ ማለት ሲሆን፣ ሌላው የ‘ራሥ (self) ጥቅም በተጠቃሚ ቅርጸት ውስጥ ደግሞ፣ የአንድ “teteqami” ቁስ ቅርፅን ማመላከት መሆኑን ልትገነዘቡት ይገባል፡፡ ይህ ነገር እነዚህን ነገሮች ግራ የሚያጋባ ከሚያደርጋቸው ነገሮች ውስጥ አንዱ ነው፡፡)
ዝርዝር 9.4: ራሥ‘ን (self) በመጠቀም አዲስ ይስሙላን እና ፈጪን መበየን፡፡ አረንጓዴ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  .
  .
  .
  # ለተሰጠው ሃረግ አንድ የተከተፈ ፍጪን ይመልሳል።
  def self.fech(hereg)
    waga = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(hereg, cost: waga)
  end

  # አንድ ነሲብ ይስሙላን ይመልሳል።
  def self.adis_ysmula
    SecureRandom.urlsafe_base64
  end
  .
  .
  .
end
ዝርዝር 9.5: class << self ‘ን በመጠቀም አዲስ ይስሙላን እና ፈጪን መበየን፡፡ አረንጓዴ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  .
  .
  .
  class << self
    # ለተሰጠው ሃረግ አንድ የተከተፈ ፍጪን ይመልሳል።
    def fech(hereg)
      waga = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                    BCrypt::Engine.cost
      BCrypt::Password.create(hereg, cost: waga)
    end

    # አንድ ነሲብ ይስሙላን ይመልሳል።
    def adis_ysmula
      SecureRandom.urlsafe_base64
    end
  end
  .
  .
  .

9.1.2 በማስታወሻ መግባት

አንድ የሚሰራ የ‘ተጠቃሚ.ዘክር (teteqami.zekr) ዘዴን ፈጥረናል፣ አሁን የተመሰጠረውን የተጠቃሚ-መታወቂያ እና የተጠቃሚውን ዝክረ ይስሙላ በአሳሹ ውስጥ እንደ ቛሚ ብስኩት አድርገን በማስቀመጥ አንድ ቛሚ ክፍለጊዜን መፍጠር እንችላለን። ይህንን የማድረግ መንገዱ ደግሞ የ‘ብስኩቶች (cookies) ዘዴን መጠቀም ነው፤ እሱንም (የ‘ክፍለጊዜ (session) ዘዴ ላይ እንዳደረግነው) ልክ እንደ አንድ ተርታ አድርገን ልናስተናግደው እንችላለን። አንድ ብስኩት ሁለት መረጃወችን ይይዛል፤ ማለት አንድ ዋጋ‘ን ((value)) እና አንድ ምርጫዊ የ‘መቃጠያ (expires) ቀን‘ን ይይዛል፡፡ ብስኩቱ የሚቃጠልበት ቀንን የማስገባቱ ጉዳይ በምርጫ ይወሰናል፣ ለምሳሌ:- ከ 20 ዓመት በኋላ የሚቃጠል አንድ ዝክረ ይስሙላ ጋር እኩል የሆነ ዋጋ ያለው አንድ ብስኩትን በመፍጠር እስከዛ ጊዜ ድረስ ቛሚ የሆነ ክፍለጊዜ ማድረግ እንችላለን:-

cookies[:zkre_ysmula] = { value:   zkre_ysmula,
                             expires: 20.years.from_now.utc }

(ይህ ሳጥን 9.1 ላይ እንደተብራራው፣ ለስራው ተስማሚ ከሆኑት የሬይልስ ጊዜ ረጅዎች ውስጥ አንዱን ይጠቀማል፡፡) ከ 20 ዓመት በኋላ የሚቃጠል ብስኩትን በአንድ አሳሽ ውስጥ ማዘጋጀቱ በጣም የተለመደ ጥለት ስለሆነ፤ ሬይልስም ይህንን በቀላሉ ለመተግበር የሚያስችል አንድ ቋሚ (permanent) የተባለ ልዩ ዘዴ አለው፤ ስለሆነም እሱን በመጠቀም እኛም በቀላሉ እንደሚከተለው አድርገን መጻፍ እንችላለን:-

cookies.permanent[:zkre_ysmula] = zkre_ysmula

ይህ ሬይልስን የመቃጠያ ጊዜውን ከ20 ዓመት በኋላ (20.years.from_now) እንዲሆን አድርጎ በራስሰር እንዲያዘጋጅ ያደርገዋል።

ሳጥን 9.1. ብስኩቶች ከ20 ዓመት በኋላ ይቃጠላሉ።

ክፍል 4.4.2 ላይ ሩቢ በማንኛውም ክፍል ማለት አብሮገነብ ክፍሎች ላይም ሳይቀር የፈለግነውን ዘዴ ማከል እንደምንችል እንዳየን ታስታውሱ ይሆናል፡፡ በዛን ወቅት አንድ አንሶላ? የተባለ ዘዴን በሃረግ (String) ክፍል ውስጥ አክለናል (እናም አንሶላ? ዘዴን ተጠቅመን "ተረተ" የሚለው ቃል ከግራ ወደ ቀኝ ተገላብጦ ሲነበብ አንድ ዓይነት መሆኑን አረጋግጠናል)። በተጨማሪም ሬይልስ አንድ ባዶነውን? (blank?) የተባለ ዘዴን በቁስ (Object) ክፍል ውስጥ እንዳከለ ተመልክተናል (በዛ ምክንያትም "".ባዶነውን? ("".blank?)" ".ባዶነውን? (" ".blank?) እና ምንም.ባዶነውን? (nil.blank?) ሁሉም እውነት (true) እንደሆኑ በሚገባ ተረድተናል)፡፡ ሬይልስ ለ 20 ዓመት ቛሚ ከዚያ በኋላ ግን የሚቃጠሉ ብስኩቶችን ለመፍጠር የተጠቀመበት የ‘ቋሚ.ብስኩቶች (cookies.permanent) የጊዜ ረጅ (time helpers) ዘዴን በሩቢ ቁጥር (ኢንቲጀር) ክፍል ውስጥ የ‘ውስንቁጥር (Fixnum) ዘዴን ማከሉ፣ ሌላ አዲስ ልንመለከተው የምንችል ምሳሌን ይፈጥርልናል:-

  $ rails console
  >> 1.year.from_now
  => Wed, 21 Jun 2017 19:36:29 UTC +00:00
  >> 10.weeks.ago
  => Tue, 12 Apr 2016 19:36:44 UTC +00:00

ሬይልስ ሌሎች ረጅ ዘዴወችንም በሩቢ ክፍሎች ውስጥ አክሏል:-

  >> 1.kilobyte
  => 1024
  >> 5.megabytes
  => 5242880

ከላይ የተጠቀሰው ዓይነት የሬይልስ ረጅ ዘዴ፣ አንድ ተጠቃሚ በአንድ ድር ላይ ምን ያህል ስእል መጫን እንደሚቻል ገደብ ለማስቀመጥ ሊረዳ ይችላል፤ ለምሳሌ ተጠቃሚው 5 ሜጋባይት ይዘት ያለው ስእል ብቻ በድሩ ላይ መጫን ካለበት፣ ይህንን ደንብ ተግባራዊ ለማድረግ የሬይልስ ረጅ ዘዴን በመጠቀም የሚፈቀደው 5.megabytes ብቻ ነው ብሎ መጻፍ ይቻላል።

ምንም እንኳን ይህ በሩቢ ክፍል ውስጥ ልብ የፋቀደውን ዘዴ ማከሉ ጥንቃቄ በተሞላበት ሁኔታ መደረግ ያለበት ቢሆንም፣ ሩቢ አብሮገነብ ክፍሎች ውስጥ ዘዴወችን ለማከል እና በሌላ ፕሮግራም ላይ ያልተለመደ ማለት በራሱ በፕሮግራሙ ላይ የፈለግነውን ዘዴ እንድናክል ይፈቅዳል። በእርግጥ አብዛኛው የሬይልስ ጥራቱ እና ሞገሱ የተገኘው በሩቢ ቋንቋ ተጣጣፊነት ምክንያት መሆኑ ሳይታለም የተፈታ ነው፡፡

የተጠቃሚ-መታወቂያን በብስኩቶቹ ውስጥ ለማከማቸት በ‘ክፍለጊዜ (session) ዘዴ (ዝርዝር 8.14) ላይ የተጠቀምነውን ጥለት መከተል በቻል ነበር:-

cookies[:teteqami_id] = teteqami.id

ይህ ጥለት ግን የተጠቃሚውን መታወቂያ እንዳለ በጥሬው በአሳሹ ላይ ስለሚያስቀምጠው፣ እና በተጨማሪም የአፕልኬሽኑን የብስኩቶች ቅጽ ስለሚያጋልጥ፣ አንድ አጥቂ የተጠቃሚ መለያወችን በቀላሉ እንዲጠልፍ እና በተጠቃሚዎች ላይም ሆነ በአፕልኬሽኑ ላይ ይህ ነው የማይባል ጉዳትን እንዲያደርስ በር ይከፍታል፡፡ ይህንን ችግር ለማስወገድ አንድ የተመሰጠረ ብስኩትን እንጠቀማለን፣ ይህም ብስኩቱን በአሳሹ ውስጥ ከማስቀመጥ በፊት በጥብቅነት በማመሳጠር ይሆናል:-

cookies.encrypted[:teteqami_id] = teteqami.id

የተጠቃሚውን መታወቂያ ከቋሚ ዝክረ ይስሙላው ጋር ማጣመር ስላለብን፣ ቋሚ (permanent) ዘዴን ከ‘ምስጥር (encrypted) ዘዴ ጋር በማስተሳሰር እሱን ቋሚ ማድረግ እንችላለን:-

cookies.permanent.encrypted[:teteqami_id] = teteqami.id

ብስኩቶቹ ከተዘጋጁ በኋላ፣ በሚቀጥሉት የገጽ ትይታዎች ላይ ተጠቃሚውን በእንደዚህ አይነት ኮድ ፈልገን ማውጣት እንችላለን:-

Teteqami.find_by(id: cookies.encrypted[:teteqami_id])

cookies.encrypted[:teteqami_id] የሚለው ኮድ፣ የብስኩቱን የተጠቃሚ-መታወቂያ በራስሰር ምስጥረቢስ ያደርገዋል። እናም ይህ ምስጥረቢስ የተጠቃሚ-መታወቂያ ማለት cookies[:zkre_ysmula]ዝርዝር 9.3 ላይ ከመነጨው የተጠቃሚ-መታወቂያ ማለት ከ‘ዝክረ_ፈጪ (zkre_fech) ጋር መዛመዱን ለማረጋገጥ፣ ቢክሪፕትን እንጠቀማለን። (ያለ ዝክረ ይስሙላው ለምን የተመሰጠረውን የተጠቃሚ-መታወቂያ ብቻ አንጠቀምም? ብላችሁ ታስቡ ይሆናል፤ ይህ የሆነበት ምክንያት፣ የተመሰጠረውን የተጠቃሚ-መታወቂያ ያገኘ አጥቂን ያለምንም እንቅፋት ለዘላለም ወደ ድሩ እንዲገባ ስለሚያስችለው ነው፡፡ አሁን ባለው ንድፍ ግን አንድ አጥቂ ሁለቱንም ብስኩቶች ቢያገኝ፣ የብስኩቶቹ ባለቤት (ተጠቃሚው) ከድሩ እስካልወጣ ድረስ ብቻ አጥቂው እንደ ተጠቃሚው ሁኖ ወደ ድሩ ሊገባ እንደሚችል ብቻ ያደርጋል፡፡ ስለዚህ ይህ ንድፍ፣ ተጠቃሚዎችን ከጥቃት ለመከላከል ትልቅ አስተዋጽኦ ያደርጋል ማለት ነው፡፡)

የእንቆቅልሹ የመጨረሻ ቁራጪ፣ አንድ የቀረበ ዝክረ ይስሙላን፣ ከተጠቃሚው ዝክረ ፈጪ ጋር አቻ መሆኑን እንዴት ማረጋገጥ ይቻላል? የሚለው ነው፤ እና በዚህ አውድ ውስጥ አንድ አቻን ለማረጋገጥ የሚያግዝ አንድ የቢስክሪፕት የጥንድ ማመጣጠኛ መንገድ አለ። የጥብቅ መሕለፈቃል የኮድ ምንጪ ላይ ከተመለከታችሁ፣ አንድ ይህንን የመሰለ ማነጻጸርያ ታገኛላችሁ:-8

BCrypt::Password.new(password_digest) == unencrypted_password

ይሄ ኮድ በእኛ በኩል ሲታይ ደግሞ፣ የሚከተለውን ይመስላል:-

BCrypt::Password.new(zkre_fech) == zkre_ysmula

በእርግጥ ይህ ኮድ እንዴት እንደሚሰራ ካሰባችሁ፣ በጣም ያደናግራል። ይህ የሆነበት ምክንያት ኮዱ እንዳለ በጥሬው ሲታይ ቢክሪፕት፣ አንድ ይስሙላን ምስጥረቢስ አድርጎ ከዚያ የ‘ == ስሌትን በመጠቀም፣ ከይስሙላው ጋር የሚያነጻጽር ስለሚመስል ነው። እንደዛ ይምሰል እንጅ ቢክሪፕትን የመጠቀም ዋናው አላማ ቢክሪፕትን በመጠቀም የተከተፈ ነገርን እንደገና ቢክሪፕትን ተጠቅሞ ወደ ነበረበት ኦርጅናል ነገር ፍጹም እንዳይመለስ ማድረግ ስለሆነ፣ ይህ ግምት ትክክል አይደለም ማለት ነው፡፡ በእርግጥም፣ የቢክሪፕት እንቁ ኮድ ማመንጫ ማስቀመጫ ውስጥ በአንክሮ ከተመለከትን የ == ስሌትን ግልጽ በሆነ ዘዴ መሕለፈቃልነውን? (is_password?) ተብሎ መበየኑን ያሳያል፡፡ ውስጥውስጡን ከላይ ያለው ንጽጽር ከሚከተለው አጻጻፍ ጋር እኩል ነው:-

BCrypt::Password.new(zkre_fech).is_password?(zkre_ysmula)

ንጽጽርን ለማከናወን ከዚህ የ‘ == ስሌት ይልቅ፣ የ‘መሕለፈቃልነውን? (is_password?) የተባለ የቡልየን ዘዴን ይጠቀማል። የሁለተኛው ንጽጽር ትርጉሙ ትንሽ ግልጽ ስለሆነ፣ እኛም ለአፕልኬሽኑ የሁለተኛውን አይነት የንጽጽር ቅርጽ እንመርጣለን።

ይህ በንዲህ እያለ፣ ከላይ ያለው ውይይት፣ የተጠቃሚን መሕለፈቃል ለማረጋግጥ በ‘ጥብቅ_መሕለፈቃል_አለው (has_secure_password) ከቀረበው የ‘አረጋግጥ (authenticate) ዘዴ ጋር ተመሳሳይ ሚናን ስለሚጫወት (ዝርዝር 8.15) ዝክረ ፈጪውን ከዝክረ ይስሙላው ጋር የሚያነጻጽረው ኮድን በተጠቃሚ ቅርጸቱ ላይ በተረጋግጧልን? (teregagtualn?) ዘዴ ውስጥ እንድናስቀምጠው ያሳስባል፡፡ የዚህ ትግበራም በዝርዝር 9.6 ውስጥ ይታያል፡፡ (በዝርዝር 9.6 ውስጥ ያለው የ‘ተረጋግጧልን? (teregagtualn?) ዘዴ ጥቅም ከተመሳጠረው ዝክረ ፈጪ ጋር የተሳሰረ ቢሆንም፤ በሌሎች አውዶች ላይም ጠቃሚ ሆኖ እንደሚያገለግል ተደርሶበታል፤ እናም ይህንን ዘዴ በምዕራፍ 11 ላይ እንጠቃልለዋለን፡፡)

ዝርዝር 9.6: በተጠቃሚ ቅርጸቱ ውስጥ የ‘ተረጋግጧልን? (teregagtualn?) ዘዴን ማከል። app/models/teteqami.rb
class Teteqami < ApplicationRecord
  attr_accessor :zkre_ysmula
  before_save { self.emelekt = emelekt.downcase }
  validates :sim,  presence: true, length: { maximum: 50 }
  BQU_YE_EMELEKT_MEDEBEGNA_HISABEHEREG =/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :emelekt, presence: true, length: { maximum: 255 },
                    format: { with: BQU_YE_EMELEKT_MEDEBEGNA_HISABEHEREG },
                    uniqueness: true
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }

  # ለተሰጠው ሃረግ አንድ የተከተፈ ፍጪን ይመልሳል።
  def Teteqami.fech(hereg)
    waga = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(hereg, cost: waga)
  end

  # አንድ ነሲብ ይስሙላን ይመልሳል።
  def Teteqami.adis_ysmula
    SecureRandom.urlsafe_base64
  end

  # በቋሚ ክፍለጊዜዎች ውስጥ ለመጠቀም አንድ ተጠቃሚን በውሂበጎታው ውስጥ መዘከር።
  def zekr
    self.zkre_ysmula = Teteqami.adis_ysmula
    update_attribute(:zkre_fech, Teteqami.fech(zkre_ysmula))
  end

  # የቀረበው ይስሙላ ከፍጪው ጋር አቻ ከሆነ እውነት ይመለሳል።
  def teregagtualn?(zkre_ysmula)
    BCrypt::Password.new(zkre_fech).is_password?(zkre_ysmula)
  end
end

ዝርዝር 9.6 ውስጥ ከ‘ተረጋግጧልን? (teregagtualn?) ዘዴ ጋር ያለው የ‘ዝክረ_ይስሙላ (zkre_ysmula) ነጋሪአሴት፣ በዝርዝር 9.3 ላይ ከበየነው የ‘ባሕሪ_መዳረሻ :ዝክረ_ይስሙላ (attr_accessor :zkre_ysmula) ጋር አንድ ዓይነት መዳረሻ አለመሆኑን እና፣ ለ‘ተረጋግጧልን? (teregagtualn?) ዘዴ ብቻ የሚያገለግል የሰፈር ተለዋዋጪ ተብሎ የሚጠራ፣ የተለዋዋጪ ዓይነት መሆኑን ልትገነዘቡ ይገባል፡፡ (እዚህ ላይ ነጋሪአሴቱ ዝክረ ይስሙላውን የሚያመለክት ስለሆነ፣ አንድ ተመሳሳይ ስም ያለው የነጋሪአሴት ዘዴ ስምን መጠቀሙ እንግዳ ነገር አይደለም።) እንዲሁም፣ ከ‘ዝክረ_ፈጪ (zkre_fech) ጋር አንድ ዓይነት የሆነውን የ‘ራሥ.ዝክረፈጪ (self.zkre_fech) ባሕሪን እና ምዕራፍ 6 ውስጥ ያሉትን፣ የ‘ስም (sim) እና የ‘ኤመልእክት emelekt ባሕሪወች ስማቸው ላይ በመመርኮዝ፣ ንቅ መዝገብ ተዛማጁን አምድ በውሂበጎታው ውስጥ በራስሰር እንደፈጠረ ልብ ልትሉ ይገባል (ዝርዝር 9.1)፡፡

አሁን አንድ የገባ ተጠቃሚን ለመዘከር ዝግጁ ነን፤ ይህንንም እውን ለማድረግ በዝርዝር 9.7 ላይ እንደሚታየው፣ ከ‘ግባ (gba) ጋር አብሮ የሚሄድ አንድ ዘክር (zekr) የተባለ ረጅ ዘዴን በክፍለጊዜወች ረጅ ፋይል ውስጥ እናክላለን፡፡

ዝርዝር 9.7: አንድ ተጠቃሚን አስገብቶ ከዚያ መዘከር። ቀይ app/controllers/sessions_controller.rb
class SessionsController < ApplicationController

  def new
  end

  def create
    teteqami = Teteqami.find_by(emelekt: params[:session][:emelekt].downcase)
    if teteqami && teteqami.authenticate(params[:session][:password])
      reset_session
      zekr teteqami
      gba teteqami
      redirect_to teteqami
    else
      flash.now[:danger] = 'ልክ ያልሆነ የኤመልእክት/የይለፍ ቃል ጥምረት'
      render 'new'
    end
  end

  def destroy
    wta
    redirect_to root_url
  end
end

ዝርዝር 9.8 ያለው የክፍለጊዜወች ረጅ ዝርዝር 9.7 ላይ ላለው የ‘ግባ (gba) ዘዴ ትክክለኛውን ስራ እንዳስተናገደ ሁሉ፣ አሁንም እዛው የክፍለጊዜወች ረጅ ላይ በተጠቃሚው ቁስ ላይ፣ ተጠቃሚ.ዘክር (teteqami.zekr) ብሎ የሚጠራ እና ለተጠቃሚው አንድ ዝክረ ይስሙላ አመንጪቶ በመፍጨት፣ ፍጪውን ውሂበጎታ ውስጥ የሚያስቀምጥ አንድ ዘክር (zekr) የተባለ ዘዴ እንፈጥራለን። ከዚያ ከላይ እንደተገለጸው፣ ለተጠቃሚ-መታወቂያ እና ለዝክረ ይስሙላ ቋሚ ብስኩቶችን ለመፍጠር ብስኩቶች‘ን (cookies) ይጠቀማል። ይህንን ለስራ የሚያበቃ ውጤት በዝርዝር 9.8 ላይ ይታያል፡፡

ዝርዝር 9.8: ተጠቃሚውን መዘከር። አረንጓዴ app/helpers/sessions_helper.rb
module SessionsHelper

  # የቀረበ ተጠቃሚን ማግባት።
  def gba(teteqami)
    session[:teteqami_id] = teteqami.id
  end

  # በቀጣይ ክፍለጊዜ ውስጥ አንድ ተጠቃሚን ይዘክራል።
  def zekr(teteqami)
    teteqami.zekr
    cookies.permanent.encrypted[:teteqami_id] = teteqami.id
    cookies.permanent[:zkre_ysmula] = teteqami.zkre_ysmula
  end

  # አንድ የገባ አሁንተጠቃሚን ይመልሳል (ካለ)።
  def ahun_teteqami
    if session[:teteqami_id]
      @ahun_teteqami ||= Teteqami.find_by(id: session[:teteqami_id])
    end
  end

  # ተጠቃሚ ከገባ እውነት፣ ካልገባ ግን ሐሰትን ይመለሳል።
  def gebtual?
    !ahun_teteqami.nil?
  end

    # የአሁንተጠቃሚን ማስወጣት።
  def wta
    reset_session
    @ahun_teteqami = nil
  end
end

ዝርዝር 9.8 ውስጥ ካለው ኮድ ጋር፣ ለአንድ የገባ ተጠቃሚ አሳሹ አንድ ብቁ ዝክረ ይስሙላን ስለሚያገኝ፣ ተጠቃሚው ይዘከራል የሚል ግምት ሊኖር ይችላል፤ ነገር ግን በዝርዝር 8.16 ላይ የተበየነው፣ የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ዘዴ ጊዜያዊ ክፍለጊዜን ብቻ ስለሚያውቅ እስከአሁን ድረስ ምንም አይጠቅመንም:-

@ahun_teteqami ||= Teteqami.find_by(id: session[:teteqami_id])

ቋሚ ክፍለጊዜወችን በተመለከተ፣ የተጠቃሚው መታወቂያ በ‘ክፍለጊዜ[:ተጠቃሚ_መታወቂያ] ‘ው (session[:teteqami_id]) ውስጥ ከኖረ፣ ተጠቃሚውን ፈልገን ማውጣት እንፈልጋለን፤ ካልሆነ ግን ከቋሚ ክፍለጊዜው ጋር የሚዛመደውን ተጠቃሚ ፈልገን ለማውጣት የተጠቃሚውን መታወቂያ ከዚሁ ብስኩት ውስጥ (cookies[:teteqami_id]) መመልከት እና ከዚያ ተጠቃሚውን ፈልገን ማግኘት (እና ማስገባት) አለብን፡፡ ይህንንም እንደሚከተለው አድርገን ማከናወን እንችላለን:-

if session[:teteqami_id]
  @ahun_teteqami ||= Teteqami.find_by(id: session[:teteqami_id])
elsif cookies.encrypted[:teteqami_id]
  teteqami = Teteqami.find_by(id: cookies.encrypted[:teteqami_id])
  if teteqami && teteqami.teregagtualn?(cookies[:zkre_ysmula])
    gba teteqami
    @ahun_teteqami = teteqami
  end
end

(ይህ ጥለት ልክ በዝርዝር 8.7 ላይ ያየነውን፣ የ teteqami && teteqami.authenticated አይነት ጥለትን ይጠቀማል፡፡) ከዚህ በላይ ያለው ኮድ ይሰራል፤ ይሁን እንጅ የ‘ክፍለጊዜ (session) እና የ‘ብስኩቶች (cookies) ዘዴወች አጠቃቀም መደጋገምን አስተውላችሁ ይሆናል። ስለዚህ እነዚህን ድግግሞሽ ለማስወገድ እንደሚከተለው ማድረግ እንችላለን:-

if (teteqami_id = session[:teteqami_id])
  @ahun_teteqami ||= Teteqami.find_by(id: teteqami_id)
elsif (teteqami_id = cookies.encrypted[:teteqami_id])
  teteqami = Teteqami.find_by(id: teteqami_id)
  if teteqami && teteqami.teregagtualn?(cookies[:zkre_ysmula])
    gba teteqami
    @ahun_teteqami = teteqami
  end
end

ይህ የተለመደውን፣ ነገር ግን ሊያደናግር የሚችለውን አገነባብ ይጠቀማል።

if (teteqami_id = session[:teteqami_id])

ከእይታው በስተቀር ይህ አንዱን ካንዱ የሚያነጻጽር አይደለም (ለንደዛ ቢሆን ሁለት የእኩል ይሆናል ምልክትን == በተጠቀመ ነበር)። ይህ አንድ የከሆነ (if) ዓረፍተሐሳብ የተለዋዋጪ ምደባ ነው፡፡ ይህንን ኮድ ለማንበብ ብትፈልጉ “የተጠቃሚ-መታወቂያ ከክፍለጊዜ መታወቂያ ጋር እኩል ከሆነ …” ብላችሁ ሳይሆን ማንበብ ያለባችሁ፣ “የተጠቃሚው መታወቂያ በተጠቃሚው ክፍለጊዜ ውስጥ ከኖረ …” ብላችሁ ማንበብ ይኖርባችኋል።”9

ልክ ከላይ እንደተወያየነው የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ረጅን መበየኑ በዝርዝር 9.9 ውስጥ ወደሚታየው ትግበራ ያመራናል።

ዝርዝር 9.9: ለቋሚ ክፍለጊዜዎች የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ዘዴን ማዘመን። ቀይ app/helpers/sessions_helper.rb
module SessionsHelper

  # የቀረበ ተጠቃሚን ማግባት።
  def gba(teteqami)
    session[:teteqami_id] = teteqami.id
  end

  # በቀጣይ ክፍለጊዜ ውስጥ አንድ ተጠቃሚን ይዘክራል።
  def zekr(teteqami)
    teteqami.zekr
    cookies.permanent.encrypted[:teteqami_id] = teteqami.id
    cookies.permanent[:zkre_ysmula] = teteqami.zkre_ysmula
  end

  # ከዝክረ ይስሙላ ብስኩቱ ጋር የተዛመደ ተጠቃሚን ይመልሳል።
  def ahun_teteqami
    if (teteqami_id = session[:teteqami_id])
      @ahun_teteqami ||= Teteqami.find_by(id: teteqami_id)
    elsif (teteqami_id = cookies.encrypted[:teteqami_id])
      teteqami = Teteqami.find_by(id: teteqami_id)
      if teteqami && teteqami.teregagtualn?(cookies[:zkre_ysmula])
        gba teteqami
        @ahun_teteqami = teteqami
      end
    end
  end

  # ተጠቃሚ ከገባ እውነት፣ ካልገባ ግን ሐሰትን ይመለሳል።
  def gebtual?
    !ahun_teteqami.nil?
  end

    # የአሁንተጠቃሚን ማስወጣት።
  def wta
    reset_session
    @ahun_teteqami = nil
  end
end

ዝርዝር 9.9 ውስጥ ባለው ኮድ አማካኝነት፣ አዲስ የገቡ ተጠቃሚዎች በትክክል ይዘከራሉ፤ ይህንንም መጀመሪያ ወደ ድሩ በመግባት፣ ከዚያ አሳሹን በመዝጋት እና አፕልኬሽኑን እንደገና በማስጀመር፣ አፕልኬሽኑን ስትጎበኙ ገብታችሁ እንዳለ ማረጋገጥ እንደምትችሉት አዲስ የገቡ ተጠቃሚወች በትክክል ይዘከራሉ።10 ውጤቱን በቀጥታ ማየት ከፈለጋችሁ፣ አሳሹ ውስጥ ያሉትን ብስኩቶች መመርመር ትችላላችሁ (ምስል 9.2)።11

አሁን አፕልኬሽናችን ባለንበት ደረጃ ላይ፣ አፕልኬሽኑ በአሳሹ ውስጥ ያሉትን ብስኩቶች፣ ከ20 ዓመት በኋላ ብቻ ከአገልግሎት ውጪ ስለሚያደርግ፣ ድሩ ውስጥ የገቡ ተጠቃሚዎች፣ ከድሩ ለመውጣት 20 ዓመት ከማስጠበቅ ሌላ ምንም ዓይነት አማራጪ አያቀርብላቸውም፡፡ ይህንን ዓይነት ችግር የፈተና ስብስቡ መያዝ ያለበት ነገር ነው፤ በርግጥም ይዞት ቀይሁኗል።

ዝርዝር 9.10: ቀይ
$ rails test

መልመጃዎች

የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።

የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡

  1. በሰፈር አሳሻችሁ ውስጥ ያሉት ብስኩቶች ውስጥ አንድ ዝክረ ይስሙላ እና አንድ የተመሰጠረ የተጠቃሚ-መታወቂያ መኖሩን አረጋግጡ፡፡
  2. ዝርዝር 9.6 ውስጥ የተበየነው የ‘ተረጋግጧልን? (teregagtualn?) ዘዴ በትክክል እንደሚሰራ በሰሌዳችሁ ውስጥ አረጋግጡ፡፡

9.1.3 ተጠቃሚዎችን መርሳት

ተጠቃሚዎች ከድሩ ዘግተው የሚወጡበትን ችሎታ ለማቅረብ፣ ተጠቃሚዎችን ለመዘከር ዘዴወችን እንደበየንን ሁሉ፣ አሁን ደግሞ ተመሳሳይ በሆነ መልኩ እነሱን ለመርሳት አንዳንድ ዘዴወችን እንበይናለን፡፡ በዝርዝር 9.11 ላይ እንደሚታየው፣ የ‘ተጠቃሚ.እርሳ (teteqami.ersa) ዘዴ ውጤት ዝክረ ፈጪን በ‘ምንም (nil) በማዘመን ተጠቃሚ.ዘክር‘ን (teteqami.zekr) ይቀለብሳል፡፡

ዝርዝር 9.11: በተጠቃሚ ቅርጸቱ ውስጥ አንድ የ‘መርሳት (ersa) ዘዴን ማከል። ቀይ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  attr_accessor :zkre_ysmula
  before_save { self.emelekt = emelekt.downcase }
  validates :sim,  presence: true, length: { maximum: 50 }
  BQU_YE_EMELEKT_MEDEBEGNA_HISABEHEREG =/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :emelekt, presence: true, length: { maximum: 255 },
                    format: { with: BQU_YE_EMELEKT_MEDEBEGNA_HISABEHEREG },
                    uniqueness: true
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }

  # ለተሰጠው ሃረግ አንድ የተከተፈ ፍጪን ይመልሳል።
  def Teteqami.fech(hereg)
    waga = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(hereg, cost: waga)
  end

  # አንድ ነሲብ ይስሙላን ይመልሳል።
  def Teteqami.adis_ysmula
    SecureRandom.urlsafe_base64
  end

  # በቋሚ ክፍለጊዜዎች ውስጥ ለመጠቀም አንድ ተጠቃሚን በውሂበጎታው ውስጥ መዘከር።
  def zekr
    self.zkre_ysmula = Teteqami.adis_ysmula
    update_attribute(:zkre_fech, Teteqami.fech(zkre_ysmula))
  end

  # የቀረበው ይስሙላ ከፍጪው ጋር አቻ ከሆነ እውነት ይመለሳል።
  def teregagtualn?(zkre_ysmula)
    BCrypt::Password.new(zkre_fech).is_password?(zkre_ysmula)
  end

  # አንድ ተጠቃሚን መርሳት
  def ersa
    update_attribute(:zkre_fech, nil)
  end
end

ዝርዝር 9.11 ላይ ካለው ኮድ ጋር፣ አሁን አንድ የ‘እርሳ (ersa) ረጅን በማከል እና እሱኑ በ‘ውጣ (wta) ዘዴ ላይ በመጥራት ቋሚ ክፍለጊዜወችን ለመሰረዝ (ለመርሳት) ዝግጁወች ነን (ዝርዝር 9.12)። በዝርዝር 9.12 ላይ እንደሚታየው፣ የ‘እርሳ (ersa) ረጅ ተጠቃሚ.እርሳ‘ን (teteqami.ersa) ይጠራ እና፣ ከዚያ የ‘ተጠቃሚ_መታወቂያ (teteqami_id) እና የ‘ዝክረ_ይስሙላ (zkre_ysmula) ብስኩቶችን ያጠፋል፡፡

ዝርዝር 9.12: ከድሩ ለመውጣት አንድ ቋሚ ክፍለጊዜን መሰረዝ። አረንጓዴ app/helpers/sessions_helper.rb
module SessionsHelper

  # የቀረበ ተጠቃሚን ማግባት።
  def gba(teteqami)
    session[:teteqami_id] = teteqami.id
  end
  .
  .
  .
  # የማያቋርጥ ክፍለ ጊዜን ይረሳል፡፡
  def ersa(teteqami)
    teteqami.ersa
    cookies.delete(:teteqami_id)
    cookies.delete(:zkre_ysmula)
  end

  # የአሁንተጠቃሚን ማስወጣት።
  def wta
    ersa(ahun_teteqami)
    reset_session
    @ahun_teteqami = nil
  end
end

በዚህ ጊዜ የፈተና ስብስቡ አረንጓዴመሆን አለበት:-

ዝርዝር 9.13: አረንጓዴ
$ rails test

መልመጃዎች

የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።

የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡

  1. ከድሩ ከወጣችሁ በኋላ፣ በአሳሻችሁ ውስጥ ያሉ ተዛማጅ ብስኩቶች ከአሳሻችሁ ውስጥ መወገዳቸውን አረጋግጡ፡፡

9.1.4 ሁለት ስውር ሳንካወች

መፍትሄ የሚሹ ሁለት በጣም ተቀራራቢ የሆኑ ስውር ሳንካወች አሉ፡፡ የመጀመሪያው ስውር ሳንካ:- አንድ ተጠቃሚ በጣቢያው ከገባ በኋላ፣ ሌላ ሁለተኛ የአሳሽ መስኮት ከፈተ እንበል፤ ከሁለተኛው የአሳሽ መስኮት፣ የጣቢያውን የ “ይውጡ” አገናኝ ተጠቅሞ ከጣቢያው ወጣ እንበል፤ ከዚያ በመቀጠል፣ ከመጀመሪያው የአሳሽ መስኮት የጣቢያውን የ “ይውጡ” አገናኝ ተጠቅሞ፣ ከጣቢያው በሚወጣበት ጊዜ፣ አፕልኬሽኑ ይበላሻል። ይህ ማለት ተጠቃሚው ከአንዱ መስኮት በሚወጣበት ጊዜ፣ የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ዋጋ ምንም (nil) ይሆናል፤ በዚህ ምክንያት በሁለተኛው አሳሽ ውስጥ የ “ይውጡ” አገናኝን ጠቅ በሚደረግበት ጊዜ፣ በ‘ውጣ (wta) ዘዴ ውስጥ ያለው የ‘እርሳ(ዓሁን_ተጠቃሚ) (ersa(ahun_teteqami)) ላይ አንድ ስህተት እንዲከሰት ያደርጋል (ዝርዝር 9.12)።12 ተጠቃሚው ከገባ ብቻ እንዲወጣ በማድረግ ይህንን ችግር ማስወገድ ይቻላል፡፡

ሁለተኛው ስውር ሳንካ:-13 አንድ ተጠቃሚ ሁለት የተለያዩ አሳሾችን ማለት ክሮምን እና ፋየርፎክስን ተጠቅሞ ገባ እንበል፤ ከክሮም አሳሹ ወጣ እንበል፤ ፋየርፎክስ አሳሹን ዘግቶ እንደገና ቢከፍተው አፕልኬሽኑ ይበላሻል። ይህ ማለት ተጠቃሚው ከፋየርፎክስ ሲወጣ፣ ዝክረ ፈጪው በ‘ተጠቃሚ.እርሳ (teteqami.ersa) ዘዴ አማካኝነት ዋጋው ምንም (nil) ነው ማለት ነው (ዝርዝር 9.11)፡፡ በዝርዝር 9.12 ውስጥ ያለው የ‘ውጣ (wta) ዘዴ የተጠቃሚውን መታወቂያ ስለሚሰረዝ፣ አፕልኬሽኑ አሁንም በፋየርፎክስ ላይ ይስራ እንጂ፣ ሁለቱ ደማቅ ቀለም የተቀቡት ሁኔታዎች ሃሰት (false) ስለሆኑ፡-

# ከዝክረ ይስሙላ ብስኩቱ ጋር የተዛመደ ተጠቃሚን ይመልሳል።
def ahun_teteqami
  if (teteqami_id = session[:teteqami_id])
    @ahun_teteqami ||= Teteqami.find_by(id: teteqami_id)
  elsif (teteqami_id = cookies.encrypted[:teteqami_id])
    teteqami = Teteqami.find_by(id: teteqami_id)
    if teteqami && teteqami.teregagtualn?(cookies[:zkre_ysmula])
      gba teteqami
      @ahun_teteqami = teteqami
    end
  end
end

በዚህ ምክንያት፣ ግምገማው የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ዘዴ መጨረሻ ላይ ይወርድ እና እንደ ተጠበቀው ምንም‘ን (nil) ይመልሳል፡፡

በተቃራኒው ክሮምን የምንዘጋ ከሆነ ደግሞ፣ ክፍለጊዜው ላይ ላለው የ‘ክፍለጊዜ[:ተጠቃሚ_መታወቂያ] (session[:teteqami_id]) እንደተለመደው ምንም‘ን (nil) እናዘጋጅለታለን (ምክንያቱም ሁሉም የ‘ክፍለጊዜ (session) ተለዋዋጮች አሳሹ በሚዘጋብት ጊዜ በራስሰር ስለሚቃጠሉ ነው)፤ ይሁን እንጅ፣ አሁንም የ‘ተጠቃሚ_መታወቂያ‘ው (teteqami_id) በብስኩቱ ውስጥ ይገኛል። ይህ ማለት፣ ክሮም ዳግም ሲከፈት አሁንም ከብስኩቱ መታወቂያ ጋር ተዛማጅ የሆነው ተጠቃሚ ከውሂበጎታው ጎትቶ ሊያወጣ ይችላል ማለት ነው:-

# ከዝክረ ይስሙላ ብስኩቱ ጋር የተዛመደ ተጠቃሚን ይመልሳል።
def ahun_teteqami
  if (teteqami_id = session[:teteqami_id])
    @ahun_teteqami ||= Teteqami.find_by(id: teteqami_id)
  elsif (teteqami_id = cookies.encrypted[:teteqami_id])
    teteqami = Teteqami.find_by(id: teteqami_id)
    if teteqami && teteqami.teregagtualn?(cookies[:zkre_ysmula])
      gba teteqami
      @ahun_teteqami = teteqami
    end
  end
end

በዚህ ምክንያትም፣ ውስጣዊው የ‘ከሆነ (if) ሁኔታ ይገመገማል:-

teteqami && teteqami.teregagtualn?(cookies[:zkre_ysmula])

በተለይም፣ የ‘ተጠቃሚው (teteqami) ዋጋ ምንም (nil) ስላልሆነ፣ የሁለተኛው ሂደት ይገመገማል፤ ይህም አንድ ስህተትን ያስነሳል። ይህ የሆነበት ምክንያት፣ ተጠቃሚው የፋየርፎክስ አሳሽን ዘግቶ በወጣበት ጊዜ (ዝርዝር 9.11)፣ የተጠቃሚው ዝክረ ፍጪው ስለተሰረዘ፣ የክሮም አሳሽን ተጠቅሞ አፕልኬሽኑን ሊደርስ ሲሞክር ምንም (nil) የሆነ ዝክረ ፈጪን ስለሚጠይቅ፣ በቢስክሪፕት ቤተኮድ ውስጥ አንድ ስህተት እንዲነሳ ያደርጋል:-

BCrypt::Password.new(zkre_fech).is_password?(zkre_ysmula)

ይህንን ለማስተካከል የ‘ተረጋግጧልን? (teregagtualn?) ዘዴው ሃሰት‘ን (false) እንዲመለስ እንፈልጋለን፡፡

እነዚህ በትክክል ከፈተና-መሬ ብልጸጋ የሚጠቀሙ፣ አይነት ሰንኮች ናቸው፤ ስለሆነም ሁለቱን ስህተቶች ከማስተካከላችን በፊት እነሱን ለመያዝ ፈተናዎችን እንጽፋለን፡፡ በዝርዝር 9.14 ላይ እንደሚታየው፣ በመጀመሪያ ዝርዝር 8.38 ያለውን የውህደት ፈተና ቀይበማድረግ እንጀምራለን።

ዝርዝር 9.14: ከሁለተኛ መስኮት ዘግቶ መውጣትን መፈተን። ቀይ test/integration/teteqamis_gba_test.rb
require 'test_helper'

class TeteqamisGbatTest < ActionDispatch::IntegrationTest
  .
  .
  .
  test "በብቁ መረጃ መግባት እና አከታትሎ መውጣት" do
    get gba_path
    post gba_path, params: { session: { emelekt:    @teteqami.emelekt,
                                          password: 'mehlefeqal' } }
    assert geb_tual?
    assert_redirected_to @teteqami
    follow_redirect!
    assert_template 'teteqamis/show'
    assert_select "a[href=?]", gba_path, count: 0
    assert_select "a[href=?]", wta_path
    assert_select "a[href=?]", teteqami_path(@teteqami)
    delete wta_path
    assert_not geb_tual?
    assert_redirected_to root_url
    # በሁለተኛው መስኮት ላይ መውጣትን ጠቅ የሚያደርግ አንድ ተጠቃሚን መምሰል።
    delete wta_path
    follow_redirect!
    assert_select "a[href=?]", gba_path
    assert_select "a[href=?]", wta_path,      count: 0
    assert_select "a[href=?]", teteqami_path(@teteqami), count: 0
  end
end

ዝርዝር 9.14 ላይ ለ‘ውጣት_መንገድ ሰርዝ (delete wta_path) ላይ የሚደረገው ሁለተኛው ጥሪ፣ የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ባለመኖሩ ምክንያት አንድ ስህተትን ስለሚያስነሳ የፈተና ስብስቡ ቀይ መሆን አለበት:-

ዝርዝር 9.15: ቀይ
$ rails test

ዝርዝር 9.16 ላይ እንደሚታየው፣ የአፕልኬሽን ኮዱ ውጣ (wta) እውነት ከሆነ ብቻ ገብቷልን?‘ን (gebtual?) መጥራትን ብቻ ያሳትፋል (ይህ ማለት ተጠቃሚው ከገባ ብቻ ያስወጣል ማለት ነው)።

ዝርዝር 9.16: የገባን ብቻ እንዲወጣ ማድረግ። አረንጓዴ app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  .
  .
  .
  def destroy
    wta if gebtual?
    redirect_to root_url
  end
end

ሁለተኛው ጉዳይ፣ በሁለት የተለያዩ አሳሾች ላይ የሚያጋጥም አንድ ሁኔታን ያሳትፋል፣ ይህን ከአንድ የውህደት ፈተና ጋር ማስመሰሉ በጣም ከባድ ይሁን እንጅ፤ እሱን በተጠቃሚ ቅርጸት ፈተና ውስጥ በቀጥታ መፈተሹ ግን ቀላል ነው። በዝርዝር 9.17 ላይ እንደሚታየው፣ የሚያስፈልገን ነገር ቢኖር፣ አንድ ዝክረ ፈጪ የለለው ተጠቃሚ ላይ የ‘ተረጋግጧልን? (teregagtualn?) ዘዴን መጥራት ብቻ ነው (በርግጥ በ‘አዘጋጅ (setup) ዘዴ ላይ የተበየነው የ‘@ተጠቃሚ (@teteqami) ቅርፀ ተለዋዋጪ፣ ምንም የዝክረ ፈጪ ባሕሪ ስለለለው ለፈተናው ብቁ ይሆናል)፡፡ (እዚህ ላይ አስተውሉ:- የዝክረ ይስሙላን ዋጋ ባዶ አድርገነዋል፤ ምክንያቱም አፕልኬሽኑ ዋጋውን ከመጠቀሙ በፊት፣ ስህተቱ ስለሚከሰት ዋጋው ምንም ይሁን ምን ግድ ስለማይሰጥ ነው።)

ዝርዝር 9.17: አንድ ፍጪ የሌለው የ‘ተረጋግጧልን? (teregagtualn?) ፈተና። ቀይ test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "አብነታዊ ተጠቃሚ",
                        emelekt: "teteqami@misalei.com",
                        password: "yonatan", password_confirmation: "yonatan")
  end
  .
  .
  .
  test "ተረጋግጧልን? አንድ የ`ምንም ፍጪ ላለው ተጠቃሚ ሃሰትን መመለስ አለበት" do
    assert_not @teteqami.teregagtualn?('')
  end
end

የቢክሪፕት መሕለፈቃል ዋጋ ምንም (nil) ስለሆነ ቢክሪፕት።መሕለፈቃል.አዲስ(ምንም) (BCrypt::Password.new(nil)) ፣ አንድ ስህተትን ያስነሳል፣ ስለዚህ የፈተና ስብስቡ ቀይመሆን አለበት:-

ዝርዝር 9.18: ቀይ
$ rails test

ዝርዝር 9.19 ላይ እንደሚታየው፣ ስህተቱን ለማስተካከል እና አረንጓዴ‘ን ለማግኘት ማድረግ የሚገባን አንድ ነገር ቢኖር፣ ዝክረ ፈጪው ምንም (nil) ከሆነ ሃሰት‘ን (false) መመለስ ብቻ ነው።

ዝርዝር 9.19: አንድ ያልኖረ ፍጪን ለማስተናገድ የ‘ተረጋግጧልን? (teregagtualn?) ዘዴን ማዘመን። አረንጓዴ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  .
  .
  .
  # የቀረበው ይስሙላ ከፍጪው ጋር አቻ ከሆነ እውነት ይመለሳል።
  def teregagtualn?(zkre_ysmula)
    return false if zkre_fech.nil?
    BCrypt::Password.new(zkre_fech).is_password?(zkre_ysmula)
  end

  # አንድ ተጠቃሚን መርሳት
  def ersa
    update_attribute(:zkre_fech, nil)
  end
end

ይህ ዝክረ ፈጪ ምንም (nil) ከሆነ ወዲያውኑ እሱኑ እንዲመልስ ለማድረግ የ‘መልስ (return) ቁልፈቃልን ይጠቀማል፤ ይህም የተቀረው ዘዴ በዚህ ሁኔታ ላይ ቸል እንደተባል ለማጉላት የሚጠቅም አንድ የተለመደ የአጻጻፍ መንገድ ነው፡፡ ከሱ ጋር እኩል የሆነው የአጻጻፍ ስልት ደግሞ የሚከተለው ነው:-

if zkre_fech.nil?
  false
else
  BCrypt::Password.new(zkre_fech).is_password?(zkre_ysmula)
end

ይህ ኮድ ልክ እንደበፊተኛው ኮድ በአንድ ዓይነት ሁኔታ ይሰራል። እኔ ግን በዝርዝር 9.19 ውስጥ ያለውን የአጻጻፍ ግልጽነትን እመርጣለሁ፡፡ (አጋጣሚ ሁኖ ኮዱ ሲጻፍም ትንሽ አጠር ያለ ነው፡፡)

ዝርዝር 9.19 ውስጥ ካለው ኮድ ጋር፣ ሙሉው የፈተና ስብስባችን አረንጓዴመሆን እና ሁለቱም ጥቃቅን ሰንኮች አሁን መፍትሄ ማግኘት አለባቸው:-

ዝርዝር 9.20: አረንጓዴ
$ rails test

መልመጃዎች

የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።

የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡

  1. ዝርዝር 9.16 ላይ ያለው፣ የሰንኩ ማስተካከያ ኮድ ላይ፣ አስተያየት አድርጉ እና ከዚያ የመጀመሪያው ሳንካ መኖሩን አረጋግጡ፤ ለማረጋገጥ:- ድራችሁ ላይ በሁለት የተለያዩ መስኮቶች ግቡ እና ከአንደኛው ከወጣችሁ በኋላ፣ አንደኛው ላይ “ይውጡ” የሚለውን አገናኝ ጠቅ አድርጉ።
  2. ዝርዝር 9.19 ላይ ያለው፣ የሰንኩ ማስተካከያ ኮድ ላይ፣ አስተያየት አድርጉና፣ ከዚያ ሁለተኛው ሳንካ መኖሩን አረጋግጡ፤ ለማረጋገጥ:- ሁለት የተለያዩ መስኮቶችን በመጠቀም፣ ድሩ ላይ ከገባችሁ በኋላ፣ ከአንደኛው አሳሽ ወጥታችሁ እንደገና ግቡ።
  3. ያደረጋችኋቸውን አስተያየቶች ከሳንካ ማስተካከያ ኮዱ ላይ በማንሳት የፈተና ስብስቡ ከ ቀይ ወደ አረንጓዴመቀየሩን አረጋግጡ፡፡

9.2 የ “ዘክረኝ” አመልካችሳጥን

ክፍል 9.1.3 ውስጥ ካለው ኮድ ጋር፣ አሁን አፕልኬሽናችን አንድ የተሟላ እና ሞያዊ-ደረጃ ያለው የማረጋገጫ ስርዓት አለው፡፡ የመጨረሻ ሂደት ይሆነን ዘንድ፣ አንድ “ዘክረኝ” የተባለ አመልካችሳጥንን በመጠቀም፣ ገብቶ መቆየትን እንዴት ምርጫዊ እንደምናደርግ እናያለን። እንደዚህ ዓይነቱ አንድ አመልካችሳጥን ከመግቢያ ቅጹ ጋር፣ በምስል 9.3 ላይ ባለው ስእላዊ መግለጫ ላይ ይታያል፡፡

images/figures/login_remember_me_mockup
ምስል 9.3: አንድ የ“ዘክረኝ” አመልካችሳጥን ስእላዊ መግለጫ፡፡

ትግበራውን ለመጻፍ፣ ዝርዝር 8.4 ላይ ባለው የመግቢያ ቅጽ ላይ፣ አንድ አመልካችሳጥንን በማከል እንጀምራለን፡፡ ልክ እንደ:- መሰየሚያወች፣ የጽሑፍ መስኮች፣ የመሕለፈቃል መስኮች፣ እና የማስረከቢያ አዝራሮች፣ የአመልካችሳጥኖችም፣ የሬይልስ ረጅ ዘዴን በመጠቀም መፍጠር ይቻላል። የቅጥ አሰራሩን ትክክለኛ ለማድረግ፣ በመሰየሚያው ውስጥ አመልካችሳጥኑን እንደሚከተለው አድርገን ማስታቀፍ አለብን:-

<%= f.label :ዘክረኝ, class: "አመልካችሳጥን ውስጠመስመር" do %>
  <%= f.check_box :ዘክረኝ %>
  <span>በዚህ ኮምፕዩተር ላይ ዘክረኝ</span>
<% end %>

ይህንን በመግቢያ ቅጹ ላይ ማስገባት በዝርዝር 9.21 ውስጥ የሚታየውን ኮድ ይሰጣል፡፡

ዝርዝር 9.21: አንድ የ“ዘክረኝ” አመልካችሳጥንን በመግቢያ ቅጹ ውስጥ ማከል። app/views/sessions/new.html.erb
<% provide(:title, "ይግቡ") %>
<h1>ይግቡ</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_with(url: gba_path, scope: :session, local: true) do || %>

      <%= .label :emelekt, 'ኤመልእክት' %>
      <%= .email_field :emelekt, class: 'form-control' %>

      <%= .label :password, 'መሕለፈቃል' %>
      <%= .password_field :password, class: 'form-control' %>

      <%= .label :ዘክረኝ, class: "አመልካችሳጥን ውስጠመስመር" do %>
        <%= .check_box :ዘክረኝ %>
        <span>በዚህ ኮምፕዩተር ላይ ዘክረኝ</span>
      <% end %>

      <%= .submit "ግባ", class: "btn btn-primary" %>
    <% end %>

    <p>አዲስ ተጠቃሚ? <%= link_to "ይመዝገቡ", temezgeb_path %></p>
  </div>
</div>

ዝርዝር 9.21 ውስጥ፣ አመልካችሳጥን እና ውስጠመስመር የተባሉ ሁለት የቅ.ቋ ክፍሎችን አካተናል፡፡ እነሱንም ቡትስትራፕ “በዚህ ኮምፒዩተር ላይ ዘክረኝ” የሚለው ጽሑፍን እና የአመልካችሳጥኑን በመግቢያ ቅጹ ውስጥ በአንድ መስመር ላይ ሁነው እንዲቀመጡ ለማድረግ ይጠቀምባቸዋል። ይህንን ቅጽ ቅጥ አስይዘን ለመጨረስ፣ በዝርዝር 9.22 ላይ እንደሚታየው፣ ትንሽ የቅ.ቋ ደንቦችን ማከል ይኖርብናል፡፡ እነዚህን ደንቦች ተግባር ላይ በማዋል የተገኘው የመግቢያ ቅጹ ውጤት በዝርዝር 9.4 ላይ ይታያል፡፡

ዝርዝር 9.22: የ“ዘክረኝ” አመልካችሳጥንን ቅጥ ለማስያዝ የቅ.ቋ ደንቦችን ማከል። app/assets/stylesheets/bju.scss
.
.
.
/* ቅጾች */
.
.
.
.አመልካችሳጥን {
  margin-top: -10px;
  margin-bottom: 10px;
  span {
    margin-left: 20px;
    font-weight: normal;
  }
}

#session_ዘክረኝ {
  width: auto;
  margin-left: 0;
}
images/figures/login_form_remember_me
ምስል 9.4: የመግቢያ ቅጹ ከታከለ አንድ የ“ዘክረኝ” አመልካችሳጥን ጋር።

የመግቢያ ቅጹን አርመን ስለጨረስን፣ አሁን ተጠቃሚዎች የአመልካችሳጥኑ ላይ ምልክት ካደረጉ፣ እነሱን ለመዘከር ካልሆነ ደግሞ ለመርሳት ዝግጁ ነን፡፡ ባሳለፍናቸው ክፍሎች ውስጥ፣ በሰራናቸው ስራውች ምክንያት፤ ይህ የአሁኑ ስራ እጅግ በጣም በሚገርም ሁኔታ፣ አተገባበሩ በአንድ መስመር ላይ፣ ሊጠቃለል የሚችል ኮድ ሊሆን ይችላል። የመግቢያ ቅጹ ውሂብ በሚያስረክብበት ጊዜ፣ የ‘ሰሚአሴቶች (params) ተርታው አሁን አመልካችሳጥኑ ላይ የተመሰረተ አንድ ዋጋን እንደሚያካትት በመገንዘብ እንጀምራለን (ይህንንም በመግቢያ ቅጹ ላይ ብቃት የሌለው መረጃን በማስረከብ እና ከዚያ በገጹ የአርም ክፍል ላይ የሚገኙ ውጤቶችን በመመርመር ማረጋገጥ ትችላላችሁ (ዝርዝር 9.21))። በተለይ የዚህን የሰሚአሴት ግብዓተ ዋጋ:-

params[:session][:ዘክረኝ]

አመልካችሳጥኑ ላይ ምልክት ከተደረገ ዋጋው '1' ሲሆን፣ ምልክት ካልተደረገበት ደግሞ '0' ይሆናል፡፡

የ‘ሰሚአሴቶች (params) ተርታ ተዛማጅ ዋጋን በመፈተሽ፣ እና በተረከበው ዋጋ ላይ በመመርኮዝ አሁን ተጠቃሚውን መዘከር ወይም መርሳት እንችላለን:-14

if params[:session][:ዘክረኝ] == '1'
  zekr(teteqami)
else
  ersa(teteqami)
end

ሳጥን 9.2 ላይ እንደተገለጸው፣ እንዲህ ዓይነቱን እንዲያ-ከሆነ (if-then) የቅርንጫፍ መዋቅር የሶስቲት ስሌትን (Ternary Operator) በመጠቀም እንደሚከተለው አድርጎ ወደ አንድ መስመር ኮድ መቀየር ይችላል:-15

params[:session][:ዘክረኝ] == '1' ? zekr(teteqami) : ersa(teteqami)

ይህንን በዝርዝር 9.7 ውስጥ፣ በክፍለጊዜወች መቆጣጠሪያ የ‘ፍጠር (create) ዘዴ ውስጥ የሚገኘው የ‘ዘክር ተጠቃሚ (zekr teteqami) ዘዴ ላይ መተካቱ፣ በዝርዝር 9.23 ላይ ወደሚታየው አስደናቂ የተጠቀጠቀ ኮድ ያመራል። (አሁን በዝርዝር 8.25 ውስጥ ያለውን የቢክሪፕት ቤተኮድ የ‘ዋጋ (cost) ተለዋዋጪን ለመበየን የተጠቀመበትን የሶስቲት ስሌትን መረዳት የምትችሉበት አቛም ላይ ደርሳችኋል።)

ዝርዝር 9.23: የ “ዘክረኝ” አመልካችሳጥን ርክብን ማስተናገድ፡፡ app/controllers/sessions_controller.rb
class SessionsController < ApplicationController

  def new
  end

  def create
    teteqami = Teteqami.find_by(emelekt: params[:session][:emelekt].downcase)
    if teteqami && teteqami.authenticate(params[:session][:password])
      reset_session
      params[:session][:ዘክረኝ] == '1' ? zekr(teteqami) : ersa(teteqami)
      gba teteqami
      redirect_to teteqami
    else
      flash.now[:danger] = 'ልክ ያልሆነ የኤመልእክት/የይለፍ ቃል ጥምረት'
      render 'new'
    end
  end

  def destroy
    wta if gebtual?
    redirect_to root_url
  end
end

በመግቢያው ቅጽ አመልካችሳጥን ላይ፣ ምልክት በማድረግ እና ባለማድረግ ማረጋገጥ እንደምትችሉት፣ በዝርዝር 9.23 ውስጥ ባለው ትግበራ አሁን የመግቢያ ስርዓቱ ተጠናቋል።

ሳጥን 9.2. 10 ዓይነት ሰዎች

“በዓለም ላይ ሁለትዮሽን የሚረዱ እና የማይረዱ፣ 10 ዓይነት ሰዎች አሉ።” የሚል የድሮ ተረት አለ (ያው 10 ማለት በሁለትዮሽ 2 ማለት ነው)። በዚህ ተረት አኳያ፣ በዓለም ላይ ሶስቲት ስሌትን የሚወዱ፣ የማይወዱ እና ገና ስለነሱ የማያውቁ፣ 10 ዓይነት ሰዎች አሉ ማለት እንችላለን (ገና ስለነሱ ከማያውቁት ውስጥ ከሆናችሁ፣ በቅርቡ ከአባልነቱ ትሰናበታላችሁ።)

በተደጋጋሚ የሆነ አፕልኬሽንን በምትሰሩበት ጊዜ፣ በጣም የተለመደው የከሆነ ሁናቴ ተቆጣጣሪ የአሰራር ሂደት፣ የሚከተለውን ዓይነት የአሰራር ሂደትን እንደሚከተል በፍጥነት ትገነዘባላችሁ:-

  if ቡልየን?
    አንድ_ነገር_አድርግ
  else
    ካልሆነ_ሌላ_ነገር_አድርግ
  end

ሩቢ፣ ልክ እንደሌሎቹ ብዙ ቋንቋዎች (ሲ/ሲ++ ፣ ፐርል ፣ ፒኤችፒ እና ጃቫን ጨምሮ)፣ የሶስቲት ስሌትን በመጠቀም ይህንን ኮድ፣ በተጠቀጠቀ ሂሳበሃረግ እንድትተኩ ያስችላችኋል (“ሶስቲት ስሌት” ተብሎ የተጠራበት ምክንያት ኮዱ ለሶስት የተከፋፈለ ክፍል ስላለው ነው)፡፡

  ቡልየን? ? አንድ_ነገር_አድርግ : ካልሆነ_ሌላ_ነገር_አድርግ

እንዲሁም፣ ምደባን ለመተካት የሶስቲት ስሌትን መጠቀምም ትችላላችሁ፤ ስለዚህ የሚከተለው ኮድ:-

  if ቡልየን?
    ተለዋ = አስቴር
  else
    ተለዋ = ተሸመ
  end

የሶስቲት ስሌትን በመጠቀም እንደሚከተለው ሊጻፍ ይችላል:-

  ተለዋ = ቡልየን? ? አስቴር : ተሸመ

በመጨረሻም፣ አንድ ዋጋን የሚመልስ ሥልት ውስጥ የሶስቲት ስሌትን መጠቀሙ ብዙ ጊዜ አመች ነው:-

  def አስቴር
    መዓት_ነገር_አድርግ
    ቡልየን? ? "ደስታ" : "ጆሲ"
  end

ሩቢ ሁል ጊዜ፣ በአንድ ዘዴ ውስጥ የመጨረሻውን የሂሳበሃረግ ዋጋ ይመልሳል፤ እዚህ ላይ የ አስቴር ዘዴ በ ቡልየኑ? የእውነት (true) ወይም የሃሰት (false) ዋጋ ላይ በመመርኮዝ "ደስታ" ‘ን ወይ ደግሞ "ጆሲ" ‘ን ይመልሳል።

መልመጃዎች

የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።

የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡

  1. የአሳሻችሁን ብስኩቶች በቀጥታ በመመርመር፣ የ“ዘክረኝ” አመልካችሳጥኑ እንዲኖረው የተፈለገው ውጤት ያለው መሆኑን አረጋግጡ፡፡
  2. በሰሌዳችሁ ላይ፣ ሁለቱን የሶስቲት ስሌት ባህሪያት ሊያሳዩ የሚችሉ ምሳሌዎችን ፍጠሩ (ሳጥን 9.2)፡፡

9.3 የ“ዘክረኝ” ፈተናወች

ምንም እንኳን፣ የ“ዘክረኝ” ተግባሩ አሁን እንደሚገባው እየሰራ ቢሆንም፣ ባህሪውን ለማረጋገጥ አንዳንድ ፈተናወችን መጻፉ ግን በጣም ጠቃሚ ነው። አንዱ ምክንያት፣ አሁን ከዚህ ቀጥለን እንደምናየው ዓይነት፣ ማለት ኮዱን በመጻፍ ላይ የሚገኙ የአተገባበር ስህተቶችን ለመያዝ ስለሚረዳ ይሆናል፡፡ ከሁሉ በላይ ይበልጥ አስፈላጊ የሆነው ነገር ግን፣ ዋናው የ “ teteqami” ቁስ ውስብስብ ኮድ፣ በአሁኑ ጊዜ ሙሉ በሙሉ ያልተፈተነ መሆኑን መገንዘቡ ነው፡፡ እንደነዚህ ያሉ ፈታኝ ሁኔታዎችን ለመፈተን አንዳንድ ነግሮችን መሸወድ የሚጠይቅ ሲሆን፣ መጨረሻ ላይ ግን፣ ሃያል የሆነ የፈተና ስብስብ ውጤት ባለቤት ያደርጋል፡፡

9.3.1 የ“ዘክረኝ” አመልካችሳጥንን መፈተን

ዝርዝር 9.23 ያለውን የአመልካችሳጥን አሰራር የሚያስተናግደውን ኮድ መጀመሪያ በአፕልኬሽኑ ላይ ስጽፍ፣ ይህንን ትክክለኛውን ሳይሆን:-

params[:session][:ዘክረኝ] == '1' ? zekr(teteqami) : ersa(teteqami)

ይህንን ነበር የጻፍኩት:-

params[:session][:ዘክረኝ] ? zekr(teteqami) : ersa(teteqami)

በዚህ አውድ ውስጥ፣ የ‘ሰሚአሴቶች[:ክፍለጊዜዎች][:ዘክረኝ] (params[:session][:ዘክረኝ]) ዋጋ ወይ '0' ወይ '1' ነው፣ ሁለቱም በአንድ ቡልየን አውድ ውስጥ እውነት (true) ናቸው፤ ስለሆነም ሂሳበሃረጉ የሚሰጠው ዋጋ ሁል ጊዜ እውነት ይሆናል፣ እናም አፕልኬሽኑ ደግሞ አመልካችሳጥኑ ሁሌ ምልክት እንደተደረገ አድርጎ ይወስደዋል። እንደዚህ አይነቱን ስህተት ነው፣ ፈተናው በትክክል መያዝ የሚገባው።

ተጠቃሚዎችን መዘከሩ የነሱን መግባት ስለሚጠይቅ፣ የኛ የመጀመሪያ ደረጃ ስራ፣ ተጠቃሚዎች በፈተናው በኩል እንዲገቡ ለማድረግ የሚያገለግል አንድ የረጅ ዘዴን መበየን ይሆናል፡፡ በዝርዝር 8.27 ውስጥ፣ የ‘አስቀምጥ (post) ዘዴ ውስጥ አንድ ብቃት ያለው የ‘ክፍለጊዜ (session) ተርታ ጋር በማድረግ አንድ ተጠቃሚን ወደ ድሩ አስገብተን ነበር፣ ይሁን እንጂ ይህንን ሁልጊዜ ማድረጉ የማይመች ነገር ነው። አላስፈላጊ ድግግሞሽን ለማስወገድ፣ ለኛ ወደ ድሩ የሚገባልን አንድ ግባ_እንደ (gba_ende) የተባለ ረጅ ዘዴን እንጽፋለን፡፡

አንድን ተጠቃሚን ወደ ድሩ ለማስገባት የምንጠቀምበት ዘዴ፣ በፈተናው ዓይነት ላይ የተወሰነ ይሆናል፡፡ በመቆጣጠሪያ ፈተናውች ውስጥ የ‘ተጠቃሚ.መታወቂያ‘ውን (teteqami.id) ከ:ተጠቃሚ_መታወቂያ (:teteqami_id) ቁልፍ ጋር በመመደብ የ‘ክፍለጊዜ (session) ዘዴን በቀጥታ ማንቀሳቀስ እንችላለን (ለመጀመሪያ ጊዜ ልክ በዝርዝር 8.14 ላይ እንደታየው)፡፡

def gba_ende(teteqami)
  session[:teteqami_id] = teteqami.id
end

ዝርዝር 8.14 ላይ ከተበየነው፣ የአፕልኬሽን ኮድ ማለት የ‘ግባ (gba) ዘዴ ጋር የስም ግጪት እንዳያመጣ፣ ዘዴውን ግባ_እንደ (gba_ende) ብለን ጠርተነዋል፡፡ መገኛ ቦታውም በዝርዝር 8.33 ውስጥ ካለው የ‘ገብ_ቷልን? (geb_tual?) ረጅ ጋር አንድ ላይ ማለት በ‘ፈተና_ረጅ (test_helper) ፋይል ውስጥ በሚገኘው በ‘ንቁድጋፍ::የፈተናመያዣ (ActiveSupport::TestCase) ክፍል ውስጥ ነው።

class ActiveSupport::TestCase
  fixtures :all

  # አንድ የፈተና ተጠቃሚ ከገባ፡ እውነትን ይመለሳል።
  def geb_tual?
    !session[:teteqami_id].nil?
  end

  # ልክ እንደ አንድ የተለየ ተጠቃሚ ሆኖ መግባት።
  def gba_ende(teteqami)
    session[:teteqami_id] = teteqami.id
  end
end

በእርግጥ በዚህ ምዕራፍ ውስጥ የዚህ ዘዴ ስሪት አያስፈልገንም፤ ነገር ግን በምዕራፍ 10 ላይ፣ የሚገባው የስራ መስክ ላይ እናሰማራዋለን።

በውህደት ፈተናው ውስጥ፣ ክፍለጊዜ‘ውን (session) በቀጥታ ለማንቀሳቀስ አንችልም፣ በዝርዝር 8.27 ላይ እንዳለው አድርገን ግን በክፍለጊዜው መንገድ በኩል ማስቀመጥ (post) እንችላለን፣ ይህም እዚህ ለይ ወደ ሚታየው የ‘ግባ_እንደ (gba_ende) ዘዴ ይመራናል:-

class ActionDispatch::IntegrationTest

  # ልክ እንደ አንድ የተለየ ተጠቃሚ ሆኖ መግባት።
  def gba_ende (teteqami, password: 'mehlefeqal', ዘክረኝ: '1')
    post gba_path, params: { session: { emelekt: teteqami.emelekt,
                                          password: password,
                                          ዘክረኝ: ዘክረኝ } }
  end
end

ይህ የ‘ግባ_እንደ (gba_ende) ዘዴ በ‘ድርጊትመላኪያ::የውህደትፈተና (ActionDispatch::IntegrationTest) ክፍል ውስጥ ስለተመላከተ፣ በውህደት ፈተናውች ውስጥ የሚያገለግለው ይሄው የ‘ግባ_እንደ (gba_ende) ዘዴ ስሪት ነው። ለሁለቱም የፈተና ዓይነትቶች አንድ ዓይነት የዘዴ ስምን እንጠቀማለን፣ ምክንያቱም የ‘ግባ_እንደ (gba_ende) ዘዴው ላይ ምንም ዓይነት ለውጥ ሳናደርግ፣ በአንድ ውህደት ውስጥ አንድ የመቆጣጠሪያ ፈተና ኮድን እንድናደርግ ስለሚያስችለን ነው።

እነዚህን ሁለት ዘዴዎች በአንድ ላይ ማስቀመጡ በዝርዝር 9.24 ውስጥ የተመለከቱትን ትይዩ የ‘ግባ_እንደ (gba_ende) ረጅወችን ያስገኛል፡፡

ዝርዝር 9.24: አንድ የ‘ግባ_እንደ (gba_ende) ረጅን ማከል። test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
.
.
.
class ActiveSupport::TestCase
  fixtures :all

  # አንድ የፈተና ተጠቃሚ ከገባ፡ እውነትን ይመለሳል።
  def geb_tual?
    !session[:teteqami_id].nil?
  end

  # ልክ እንደ አንድ የተለየ ተጠቃሚ ሆኖ መግባት።
  def gba_ende(teteqami)
    session[:teteqami_id] = teteqami.id
  end
end

class ActionDispatch::IntegrationTest

  # ልክ እንደ አንድ የተለየ ተጠቃሚ ሆኖ መግባት።
  def gba_ende (teteqami, password: 'mehlefeqal', ዘክረኝ: '1')
    post gba_path, params: { session: { emelekt: teteqami.emelekt,
                                          password: password,
                                          ዘክረኝ: ዘክረኝ } }
  end
end

ዝርዝር 9.24 ውስጥ ያለው፣ ሁለተኛው የ‘ግባ_እንደ (gba_ende) ዘዴ ልብ የፈቀደውን ለማድረግ አመች ይሆን ዘንድ፣ የነጋሪአሴቶች ቁልፈቃልን (ልክ እንደ ዝርዝር 7.13)፣ ማለት የ‘መሕለፈቃል:‘ን (password:) እና የ ዘክረኝ: አማራጪን እንደሚቀበል ልብ በሉ፣ ለመሕለፈቃሉ 'mehlefeqal' የተባለ ነባሪ ዋጋን እና ለ “ዘክረኝ” አመልካችሳጥኑ ደግሞ '1' ‘ን በቅደም ተከተል አዘጋጅቷል።

የ “ዘክረኝ” አመልካችሳጥን ባህሪን ለማረጋገጥ ሁለት ፈተናውችን እንጽፋለን፤ የምንጽፈው ፈተናም አመልካችሳጥኑ ምልክት ተደርጎበት እና ሳይደረግበት ለሚደረጉት ለእያንዳንዳቸው ርክብ ይሆናል፡፡ በዝርዝር 9.24 ውስጥ የተበየነውን ረጅ በመጠቀም እነዚህን ሁለት ክስተቶች መፈተኑ ቀላል ነው:-

gba_ende(@teteqami, ዘክረኝ: '1')

እና

gba_ende(@teteqami, ዘክረኝ: '0')

ብለን በመጻፍ የአመልካችሳጥኑን ባህሪ ማረጋገጥ እንችላለን።

('1' የ‘ ዘክረኝ ነባሪ ዋጋ ስለሆነ፣ አመልካችሳጥኑ ላይ ምልክት ከተደረገ የሚለውን ተዛማጅ አማራጪ ማለት ‘ግባእንደ(@ተጠቃሚ, ዘክረኝ: ’1’) (gbaende(@teteqami, ዘክረኝ: '1')) ብለን መጻፉ አያስፈልገንም ነበር፣ ነገር ግን ትይዩአዊ መዋቅሩን የበለጠ ግልጽ ለማድረግ አካትቸዋለሁ።)

ተጠቃሚው ከገባ በኋላ፣ በ‘ብስኩቶቹ (cookies) ውስጥ ያለውን የ‘ዝክረ_ይስሙላ (zkre_ysmula) ቁልፍ ላይ በመመልከት ተጠቃሚው መዘከሩን ማረጋገጥ እንችላለን፡፡ በዚህ ሁኔታ ላይ፣ የብስኩቱ ዋጋ ከተጠቃሚው ዝክረ ይስሙላ ጋር እኩል መሆኑን በፈተሽን ነበር፣ አሁን ባለን ንድፍ ግን ፈተናው የ‘ዝክረ_ይስሙላ (zkre_ysmula) ዋጋን መድረስ የሚቻልበት ምንም ዓይነት መንገድ የለውም፤ በመቆጣጠሪያ ውስጥ ያለው የ‘ተጠቃሚ (teteqami) ተለዋዋጪ አንድ የ‘ዝክረ_ይስሙላ (zkre_ysmula) ባሕሪ ሲኖረው፣ በፈተና ውስጥ ያለው @ተጠቃሚ (@teteqami) ቅርፀ ተለዋዋጪ ግን የ‘ዝክረ_ይስሙላ (zkre_ysmula) ባሕሪ የለውም (ይህ የሆነበት ምክንያትም ዝክረ_ይስሙላ‘ው (zkre_ysmula) ምናባዊ ባሕሪ ስለሆነ ነው)። ይህንን ከቁጥር የማይገባ እንከን ማስተካከሉን ለናንተ ልክ እንደ አንድ መልመጃ ይሆን ዘንድ እንተወው እና (ክፍል 9.3.1.1)፣ ለአሁኑ ተገቢው ብስኩት መኖሩን እና አለመኖሩን ለማወቅ በቀላሉ መፈተን እንችላለን።

ሳይታወሱ በሚገቡበት ጊዜ የ‘ዝክረ_ይስሙላ‘ው (zkre_ysmula) ብስኩት ባዶ መሆን አለበት፤ በሚታወሱበት ጊዜ ደግሞ ባዶ መሆን የለበትም፡፡ አለመታደል ሆኖ፣ አንድ በመሄድ ላይ አፕልኬሽን ውስጥ አንድ ብስኩትን ለባዶ ማዘጋጀቱ ባዶ ሃረግን "" ማድረግ ሲሆን፣ በፈተና ውስጥ ግን ያንን ለማዘጋጀት ምንም‘ን (nil) መጠቀም ነው፣ እናም ምንም‘ን (nil) በየለለነውን? (empty?) ላይ መጥራት አንችልም። እንደ እድል ሆኖ፣ ለሁለቱም ለ‘ምንም (nil) እና ለባዶ ሃረግ እውነት (true) የሚመልሰውን፣ ማለት በክፍል 4.4.3 ውስጥ እና በሳጥን 9.1 ላይ የተገለጸውን፣ የ‘ባዶነውን? (blank?) ዘዴን መጠቀም እንችላለን። ይህንን በ “ዘክረኝ” ፈተናችን ላይ መተግበሩ፣ በዝርዝር 9.25 ውስጥ የተመለከቱትን ውጤቶች ይሰጣል፡፡ (በዝርዝር 8.27 ላይ ያለው ተጠቃሚዎች(:ማይክል) (teteqamis(:michael)) የሚለው ኮድ፣ ዝርዝር 8.26 ላይ ያለው የእቃ ተጠቃሚን እንደሚያመላክት ልታስታውሱ ይገባል፡፡)

ዝርዝር 9.25: የ“ዘክረኝ” አመልካችሳጥን ፈተና። አረንጓዴ test/integration/teteqamis_gba_test.rb
require 'test_helper'

class TeteqamisGbatTest < ActionDispatch::IntegrationTest

  def setup
    @teteqami = teteqamis(:michael)
  end
  .
  .
  .
  test "በዘክረኝ መግባት" do
    gba_ende(@teteqami, ዘክረኝ: '1')
    assert_not_empty cookies[:zkre_ysmula]
  end

  test "ሳይዘከሩ መግባት" do
    # ኩኪውን ለማዘጋጀት መግባት፡፡
    gba_ende(@teteqami, ዘክረኝ: '1')
    # እንደገና መግባት እና ብስኩቱ መሰረዙን ማረጋገጥ።
    gba_ende(@teteqami, ዘክረኝ: '0')
    assert_empty cookies[:zkre_ysmula]
  end
end

እኔ ያደረግኩትን አይነት የአተገባበር ስህተት እንዳልፈጸማችሁ በመገመት፣ አሁን ፈተናውቹ አረንጓዴመሆን አለባቸው:-

ዝርዝር 9.26: አረንጓዴ
$ rails test

መልመጃዎች

የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።

የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡

  1. ከላይ እንደተብራራው፣ አፕልኬሽኑ አሁኑ ባለው ንድፍ፣ ባሁኑ ጊዜ በዝርዝር 9.25 ውስጥ ያለውን የውህደት ፈተና የ‘ዝክረ_ይስሙላ (zkre_ysmula) ምናባዊ ባሕሪ ዋጋ ላይ የሚደርስበት ምንም ዓይነት መንገድ እንደለለው አይተናል፡፡ ቢሆንም ቅሉ፣ አንድ መድብ (assigns) ተብሎ የሚጠራ ልዩ የፈተና ዘዴን በመጠቀም የ‘ዝክረ_ይስሙላ (zkre_ysmula) ምናባዊ ባሕሪ ዋጋን መድረስ ግን ይቻላል፡፡ በአንድ ፈተና ውስጥ የ‘መድብ (assigns) ዘዴን ከሚዛመደው ወካይ ጋር በመጠቀም፣ በመቆጣጠሪያ ውስጥ የተበየኑትን ቅርፀ ተለዋዋጮች መድረስ ትችላላችሁ፡፡ ለምሳሌ:- የ‘ፍጠር (create) ተግባር፣ @ተጠቃሚ (@teteqami) የተባለ አንድ ቅርፀ ተለዋዋጪ ቢበየን፣ መድብ(:ተጠቃሚ) (assigns(:teteqami)) ብለን በመጠቀም በፈተናው ውስጥ ልንደርስበት እንችላለን። በአሁኑ ጊዜ፣ በክፍለጊዜወች መቆጣጠሪያ ውስጥ ያለው የ‘ፍጠር (create) ተግባር አንድ ተራ ተጠቃሚ (teteqami) የተባለ ተለዋዋጪን በይኗል (ማለት ቅርፅ ያልሆነ ተለዋዋጪን በይኗል ማለት ነው)፣ ነገር ግን ይህንን ተራ ተለዋዋጪ ወደ አንድ ቅርፀ ተለዋዋጪ ከለውጥን፣ ብስኩቶቹ (cookies) በውስጣቸው የተጠቃሚውን ዝክረ ይስሙላ በትክክል እንደያዙ እና እንዳልያዙ መፈተን እንችላለን። በዝርዝር 9.27 እና በዝርዝር 9.28 ውስጥ በጥያቄ ምልክት ? እና በ ይህን_ሙሉ ቦታ ላይ የሚገቡትን ነገሮች በመሙላት፣ ይህንን የተሻሻለ የ“ዘክረኝ” አመልካችሳጥን ፈተና ጪራሽ የተሟላ አድርጉ፡፡
ዝርዝር 9.27: በ‘ፍጠር (create) ተግባር ውስጥ አንድ ቅርፀ ተለዋዋጪን ለመጠቀም የተዘጋጀ አብነት። app/controllers/sessions_controller.rb
class SessionsController < ApplicationController

  def new
  end

  def create
    ?teteqami = Teteqami.find_by(emelekt: params[:session][:emelekt].downcase)
    if ?teteqami && ?teteqami.authenticate(params[:session][:password])
      reset_session
      gba ?teteqami
      params[:session][:ዘክረኝ] == '1' ? zekr(?teteqami) : ersa(?teteqami)
      redirect_to ?teteqami
    else
      flash.now[:danger] = 'ልክ ያልሆነ የኤመልእክት/የይለፍ ቃል ጥምረት'
      render 'new'
    end
  end

  def destroy
    wta if gebtual?
    redirect_to root_url
  end
end
ዝርዝር 9.28: ለተሻሻለው የ“ዘክረኝ” ፈተና የተዘጋጀ ዝግጁገጽታ/ፋይል። አረንጓዴ test/integration/teteqamis_gba_test.rb
require 'test_helper'

class TeteqamisGbatTest < ActionDispatch::IntegrationTest

  def setup
    @teteqami = teteqamis(:michael)
  end
  .
  .
  .
  test "በዘክረኝ መግባት" do
    gba_ende(@teteqami, ዘክረኝ: '1')
    assert_equal ይህን_ሙሉ, assigns(:teteqami).ይህን_ሙሉ
  end

  test "ሳይዘከሩ መግባት" do
    # ኩኪውን ለማዘጋጀት መግባት፡፡
    gba_ende(@teteqami, ዘክረኝ: '1')
    # እንደገና መግባት እና ብስኩቱ መሰረዙን ማረጋገጥ።
    gba_ende(@teteqami, ዘክረኝ: '0')
    assert_empty cookies[:zkre_ysmula]
  end
  .
  .
  .
end

9.3.2 የመዘከር ቅርንጫፍን መፈተን

ክፍል 9.1.2 ውስጥ፣ ቀደም ባሉት ክፍሎች የተተገበረው ቋሚ ክፍለጊዜ እየሰራ መሆኑን በእጃችን አረጋግጠናል፣ በእውነቱ ከሆነ ግን በ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ዘዴ ውስጥ የሚገኘው ቅርንጫፍ በአሁኑ ጊዜ ፈጽሞ አልተፈተነም፡፡ እንደዚህ ዓይነቱን ሁኔታ ለማስተናገድ የምወደው መንገድ በተጠረጠረው ያልተፈተነ የኮድ ጥምር ውስጥ አንድ ልዩነትን ማስነሳት ነው፤ ኮዱ ካልተገኘ፣ ፈተናዎቹ አሁንም ያልፋሉ፤ ኮዱ ከተገኘ ደግሞ፣ የሚፈጠረው ስህተት ተዛማጁን ፈተና ይለየዋል። በአሁኑ ጉዳይ ላይ የተገኘው ውጤት በዝርዝር 9.29 ውስጥ ይታያል፡፡

ዝርዝር 9.29: በአንድ ያልተፈተነ ቅርንጫፍ ውስጥ አንድ ልዩነትን ማስነሳት፡፡ አረንጓዴ app/helpers/sessions_helper.rb
module SessionsHelper
  .
  .
  .
  # ከዝክረ ይስሙላ ብስኩቱ ጋር የተዛመደ ተጠቃሚን ይመልሳል።
  def ahun_teteqami
    if (teteqami_id = session[:teteqami_id])
      @ahun_teteqami ||= Teteqami.find_by(id: teteqami_id)
    elsif (teteqami_id = cookies.encrypted[:teteqami_id])
      raise  # ፈተናዎቹ አሁንም ያልፋሉ፤ ስለሆነም ይህ ቅርንጫፍ በአሁኑ ጊዜ አልተፈተነም።
      teteqami = Teteqami.find_by(id: teteqami_id)
      if teteqami && teteqami.teregagtualn?(cookies[:zkre_ysmula])
        gba teteqami
        @ahun_teteqami = teteqami
      end
    end
  end
  .
  .
  .
end

በዚህ ጊዜ ፈተናዎቹ አረንጓዴናቸው:-

ዝርዝር 9.30: አረንጓዴ
$ rails test

ይህ አንድ ትልቅ ችግር እንዳለ ያመለክታል፣ ፈተናው ማለፍ አልነበረበትም፣ ምክንያቱም በዝርዝር 9.29 ውስጥ ያለው ኮድ ተሰብሯል፡፡ በተጨማሪም፣ ቛሚ ክፍለጊዜዎች በእጅ ለመፈተሽ አስቸጋሪወች ናቸው፤ ስለሆነም የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ዘዴን ማጣራት ከፈለግን (በምዕራፍ 11 ላይ እንደምናደርገው) እሱን መፈተኑ አስፈላጊ ነው፡፡

ዝርዝር 9.24 ውስጥ፣ የተበየኑት ሁለቱንም የ‘ግባ_እንደ (gba_ende) ረጅ ዘዴ ስሪቶች በራስሰር የ‘ክፍለጊዜ[:ተጠቃሚ_መታወቂያ] (session[:teteqami_id]) ዋጋን ስለሚያዘጋጁ (በግልጽም ሆነ ወይም በመግቢያ መንገድ ላይ በማስቀመጥ)፣ በአንድ የውህደት ፈተና ውስጥ የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ዘዴ የ “ዘክር” ቅርንጫፍን መፈተኑ ከባድ ነው። እንደ እድል ሆኖ ግን፣ የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ዘዴን በአንድ የክፍለጊዜወች ረጅ ፈተና ውስጥ በቀጥታ በመፈተን ይህንን ገደብ ማለፍ እንችላለን። ለፈተናው የሚሆነውን ፋይል እንደሚከተለው አድድገን እንፈጥራለን:-

$ touch test/helpers/sessions_helper_test.rb

የፈተናው ቅደም ተከተሎች ቀላል ናቸው:-

  1. እቃወችን በመጠቀም አንድ ተጠቃሚ (teteqami) የተባለ ተለዋዋጪን መበየን።
  2. አንድ የቀረበ ተጠቃሚን ለመዘከር የ‘ዘክር (zekr) ዘዴን መጥራት።
  3. የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ከቀረበው ተጠቃሚ ጋር እኩል መሆኑን ማረጋገጥ።

የ‘ዘክር (zekr) ዘዴው የ‘ክፍለጊዜ[:ተጠቃሚመታወቂያ] ‘ን (session[:teteqami_id]) ስለማያዘጋጅ ይህ አሰራር የተፈለገውን የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) (የ “ዘክር”) ቅርንጫፍን ይፈትናል። ውጤቱ በዝርዝር 9.31 ውስጥ ይታያል፡፡

ዝርዝር 9.31: ለቛሚ ክፍለጊዜወች የተዘጋጀ አንድ ፈተና። ቀይ test/helpers/sessions_helper_test.rb
require 'test_helper'

class SessionsHelperTest < ActionView::TestCase

  def setup
    @teteqami = teteqamis(:michael)
    zekr(@teteqami)
  end

  test "የahun_teteqami ክፍለጊዜ ኒል በሚሆንበት ጊዜ ትክክለኛውን ተጠቃሚ ይመልሳል።" do
    assert_equal @teteqami, ahun_teteqami
    assert geb_tual?
  end

  test "የahun_teteqami ዝክረ ፈጪ የተሳሳተ በሚሆንበት ጊዜ ኒልን ይመልሳል።" do
    @teteqami.update_attribute(:zkre_fech, Teteqami.fech(Teteqami.adis_ysmula))
    assert_nil ahun_teteqami
  end
end

እዚህ ላይ ዝክረ ይስሙላው፣ ከዝክረ ፈጪው ጋር በትክክል የመይዛምድ ከሆነ፣ የአሁንተጠቃሚው ዋጋ ምንም (nil) መሆን እንዳለበት የሚያረጋግጥ አንድ ሁለተኛ ፈተናን እንዳከልን ተገንዝባችሁ ይሆናል፤ ስለዚህ በ‘ከሆነ (if) ዓረፍተሐሳብ እቅፍ ውስጥ ያለውን፣ የ‘ተረጋግጧልን? (teregagtualn?) ሂሳበሃረግ ይፈትናል:-

if teteqami && teteqami.teregagtualn?(cookies[:zkre_ysmula])

በአጋጣሚ፣ በዝርዝር 9.31 ውስጥ ያለውን የፈተና ኮድ፣ ልክ እንደተጻፈው እንደመጻፍ ፈንታ እንደዚህ አድርጋችሁ ገላብጣችሁ ትጽፉ ይሆናል:-

assert_equal ahun_teteqami, @teteqami

ይህ የተገላበጠ አጻጻፍም አንድ ዓይነት ውጤትን ይሰጣል፡፡ (በክፍል 5.3.4.1 በግልጽ እንደተብራራው) ለ‘እኩልነት_አረጋግጥ (assert_equal) ነጋሪአሴቶች የተለመደው ቅደም ተከተል ግን:- መጀመሪያ የሚጠበቀውን (Expected) ነገር በመቀጠል ደግሞ እውነታውን (Actual) አከታትሎ መጻፍ ነው:-

assert_equal <ተጠባቂ>, <እውነታ>

በዚህ ምክንያት ነው ዝርዝር 9.31 ይሄን የሰጠን:-

assert_equal @teteqami, ahun_teteqami

ዝርዝር 9.31 ውስጥ ባለው ኮድ ምክንያት፣ ፈተናው እንደተፈለገው ቀይ ሁኗል:-

ዝርዝር 9.32: ቀይ
$ rails test test/helpers/sessions_helper_test.rb

ዝርዝር 9.33 ላይ እንደተመለከተው፣ የ‘አስነሳ (raise) ዘዴን በማስወገድ እና ኦርጅናሉን የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ዘዴን ወደ ነበረበት በማስመለስ፣ በዝርዝር 9.31 ውስጥ ያሉትን ፈተናወች ማሳለፍ እንችላለን፡፡

ዝርዝር 9.33: የተነሳውን ልዩነት ማስወገድ። አረንጓዴ app/helpers/sessions_helper.rb
module SessionsHelper
  .
  .
  .
  # ከዝክረ ይስሙላ ብስኩቱ ጋር የተዛመደ ተጠቃሚን ይመልሳል።
  def ahun_teteqami
    if (teteqami_id = session[:teteqami_id])
      @ahun_teteqami ||= Teteqami.find_by(id: teteqami_id)
    elsif (teteqami_id = cookies.encrypted[:teteqami_id])
      teteqami = Teteqami.find_by(id: teteqami_id)
      if teteqami && teteqami.teregagtualn?(cookies[:zkre_ysmula])
        gba teteqami
        @ahun_teteqami = teteqami
      end
    end
  end
  .
  .
  .
end

በዚህ ጊዜ፣ የፈተና ስብስቡ አረንጓዴመሆን አለበት:-

ዝርዝር 9.34: አረንጓዴ
$ rails test

አሁን የ‘ዓሁን_ተጠቃሚ (ahun_teteqami) “ዘክር” ቅርንጫፍ ተፈትኗል፣ በእጅ መፈተን ሳያስፈልገን (በአንድ አሳሽ ላይ አንድ ባንድ መፈተን ሳያስፈልገን) ምልሰትን እንደምንይዝ መተማመን እንችላለን፡፡

መልመጃዎች

የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።

የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡

  1. ዝርዝር 9.33 ውስጥ ያለውን የተረጋግጧልን? (teregagtualn?) ሂሳበሃረግ በማስወገድ፣ በዝርዝር 9.31 ውስጥ ያለው ሁለተኛው ፈተና እንደሚወድቅ አረጋግጡ፡፡ በዚህም ትክክለኛውን ነገር መፈተኑን አረጋገጣችሁ ማለት ነው፡፡
  2. ክፍል 9.1.1 ላይ እንደተብራራው፣ በአፕልኬሽናችን ክፍለጊዜ ውስጥ የ‘ተጠቃሚ_መታወቂያ (teteqami_id) በአሁኑ ወቅት ለክፍለጊዜ ዳግመጫወታ ጥቃቶች የተጋለጠ ነው። በዝርዝር 9.35 እና በዝርዝር 9.36 ውስጥ ያለውን ኮድ በመጠቀም፣ በዝርዝር 9.37 ውስጥ የጎደለውን የ‘ ይህን_ሙሉ ኮድን በመሙላት ይህንን ሁኔታ አስተካክሉ፡፡ ጠቃሚ ምክር:- በክፍለጊዜ‘ው (session) ተርታ ውስጥ ያለው ይስሙላ፣ ከተጠቃሚው ክፍለጊዜ ይስሙላ ጋር እኩል ከሆነ ብቻ የ‘@ዓሁን_ተጠቃሚ‘ን (@ahun_teteqami) አዘጋጁ። ልብ በሉ፣ ዝክረ_ፈጪ (zkre_fech) ቀድሞውኑ ከእያንዳንዱ ተጠቃሚ ጋር የተሳሰረ አንድ ልዩ ዋጋ ስለሆነ፣ ከሌለው በማመንጨት፣ ካለው ደግሞ በቀላሉ ልክ እንደ አንድ ክፍለጊዜ ይስሙላ እንጠቀምበታለን። (ይህ በዝርዝር 9.36 ላይ እንደሚታየው፣ የ‘ባሕሪ_አዘምን (update_attribute) ውጤትን ከመመለስ ይልቅ ፍጪውን ለመመለስ በ‘ዘክር (zekr) ዘዴ ላይ አንድ አነስተኛ ለውጥ ማድረግን ያሳትፋል፣ የቢክሪፕት ፍጪወች ሲነደፉ የተጠበቁ ስለሆኑ እና የክፍለጊዜው ዋጋወች በማንኛውም ሁኔታ የተመሰጠሩ ስለሆኑ፣ ለዚህ ስራ ለሁለቱም ዝክረ ፈጪውን እንደገና መጠቀሙ አስተማማኝ ነው (ክፍል 8.2))፡፡ በዚህ አተገባበር የተጠለፈ አንድ ክፍለጊዜን ለማብቃት የሚያስፈልግ አንድ ነገር ቢኖር፣ የ‘ተጠቃሚ.እርሳ (teteqami.ersa) ዘዴን መጥራት ብቻ ነው፡፡ የተጠቃሚ መሕለፈቃል ዳግም አስጀማሪ፣ ማንኛውንም ነባር ክፍለጊዜዎች ጊዜያቸውን የሚያቃጥል መሆኑን ለማረጋገጥ ይህንን ዘዴ በክፍል 12.3.2.1 ላይ እንተገብራለን፡፡ በመጨረሻም፣ ይህ ኮድ ከጥበቃ ጋር የተዛመደ ስለሆነ፣ በስልጠናው ውስጥ ካሉ ሌሎች ልምምዶች መፍትሄዎች በተቃረነ መልኩ፣ ለወደፊቱ በኮድ ዝርዝሮች እና በማሳያ አፕልኬሽኑ ውስጥ ይካተታል፡፡
ዝርዝር 9.35: በመግባት ወቅት አንድ የክፍለጊዜ ይስሙላን ማዘጋጀት። app/helpers/sessions_helper.rb
module SessionsHelper

  # የቀረበ ተጠቃሚን ማግባት።
  def gba(teteqami)
    session[:teteqami_id] = teteqami.id
    # ከክፍለጊዜ ዳግመጫወታ ጥቃቶች መጠበቅ፡፡
    # ለተጨማሪ መረጃ በ https://bit.ly/33UvK0w ላይ ተመልከቱ።
    session[:yismule_kflegzie] = teteqami.yismule_kflegzie
  end
  .
  .
  .
end
ዝርዝር 9.36: በተጠቃሚዎች ላይ አንድ የክፍለጊዜ ይስሙላ ዘዴን ማከል። app/models/teteqami.rb
class Teteqami < ApplicationRecord
  .
  .
  .
  # በቋሚ ክፍለጊዜዎች ውስጥ ለመጠቀም አንድ ተጠቃሚን በውሂበጎታው ውስጥ መዘከር።
  def zekr
    self.zkre_ysmula = Teteqami.adis_ysmula
    update_attribute(:zkre_fech, Teteqami.fech(zkre_ysmula))
    zkre_fech
  end

  # የክፍለጊዜ ጠለፋን ለመከላከል፡ አንድ የክፍለጊዜ ይስሙላን ይመልሳል።
  # ለአመችነት ዝክረ ፈጪውን እንደገና መጠቀም።
  def yismule_kflegzie
    zkre_fech || zekr
  end
  .
  .
  .
end
ዝርዝር 9.37: የአሁንተጠቃሚ ዘዴ የይስሙላ ክፍለጊዜን እንዲጠቀም ማዘመን። app/helpers/sessions_helper.rb
module SessionsHelper
  .
  .
  .
  # ከዝክረ ይስሙላ ብስኩቱ ጋር የተዛመደ ተጠቃሚን ይመልሳል።
  def ahun_teteqami
    if (teteqami_id = session[:teteqami_id])
      teteqami = Teteqami.find_by(id: teteqami_id)
      if teteqami && session[:yismule_kflegzie] == ይህን_ሙሉ
        @ahun_teteqami = teteqami
      end
    elsif (teteqami_id = cookies.encrypted[:teteqami_id])
      teteqami = Teteqami.find_by(id: teteqami_id)
      if teteqami && teteqami.teregagtualn?(cookies[:zkre_ysmula])
        gba teteqami
        @ahun_teteqami = teteqami
      end
    end
  end
  .
  .
  .
end

9.4 ማጠቃለያ

ባለፉት ሶስት ምዕራፎች ውስጥ፣ ተስፋ ሰጪ ነገር ግን በቅጡ ያልተስተካከለ አፕልኬሽንን፣ ወደ ሙሉ የመመዝገቢያ እና የመግቢያ አገልግሎቶችን ወደሚያቀርብ አንድ ጣቢያ በመለወጥ ሂደት ውስጥ፣ ብዙ ነገሮችን አሟልተናል፡፡ ሁሉንም የማረጋገጫ ተግባር ለማጠናቀቅ የሚያስፈልገው፣ በግብዓት ሁኔታ እና በተጠቃሚ ማንነት ላይ በመመርኮዝ፣ ተጠቃሚው የማይመለከተውን ገጽ እንዳይደርስ መገደብ ሲሆን፤ ተጠቃሚዎች መረጃቸውን የሚያርሙበትን አንድ ችሎታ በማቅረብ ሂደት ውስጥ ይህንን ተግባር እናከናውናለን፤ ይህንን ከግብ ማድረሱ ደግሞ የምዕራፍ 10 ዋና ዓላማ ይሆናል፡፡

ከመቀጠላችሁ በፊት፣ ያደረጋችኋቸውን ለውጦች ወደ ዋና ቅርንጫፉ አዋህዱ:-

$ rails test
$ git add -A
$ git commit -m "የላቀ መግቢያ ትግበራ"
$ git checkout main
$ git merge የላቀ-መግቢያ
$ git push

አፕልኬሽኑ ወደ ሃረኩ ከመሰማራቱ በፊት፣ አፕልኬሽኑ ወደ ሃረኩ መፍለሱን እስኪጨርስ ድረስ የሃረኩ የጥገና ሁኔታን መጠቀሙ አስፈላጊ ነው (አፕልኬሽኑ በዚህ ሁኔታ ላይ በሚሆንበት ጊዜ፣ ለአጪር ጊዜ በሃረኩ አገልጋይ ላይ አይሰራም ማለት ነው)፡፡ ብዙ ተጠቃሚዎች ባሉበት አንድ የምርት ጣቢያ ውስጥ፣ በአፕልኬሽኑ ላይ የሆነ ለውጥ ከማድረጋችሁ በፊት የጥገና ሞድን ወደ “on” መቀየሩ ተገቢ ነው:-

$ heroku maintenance:on
$ git push heroku
$ heroku run rails db:migrate
$ heroku maintenance:off

ይህ አፕልኬሽናችሁን በምታሰማሩበት እና በምታፈልሱበት ጊዜ አንድ መደበኛ የስህተት ገጽን በድራችሁ ላይ ለማሳየት ያመቻቻል (ምስል 9.5)። (ካሁን ወዲያ ስለዚህ ሂደት አንነጋገርም፣ ቢያንስ አንድ ጊዜ ይህንን ነገር ለናንተ ማሳየቱ ግን ጥሩ ነው።) ለተጨማሪ መረጃ የሃረኩ ሰነድ ላይ የስህተት ገጾች የሚለው ላይ መመልከት ትችላላችሁ፡፡

images/figures/maintenance_mode
ምስል 9.5: የምርት አፕልኬሽኑ በጥገና ሞድ ውስጥ።

9.4.1 በዚህ ምዕራፍ ውስጥ የተማርናቸው ነገሮች:-

  • ሬይልስ በ‘ብስኩቶች (cookies) ዘዴ አማካይነት፣ ቋሚ ብስኩቶችን በመጠቀም ከአንድ ገጽ ወደ ሌላው ገጽ ሁኔታን ጠብቆ ማቆየት እንደሚችል፣
  • ቋሚ ክፍለጊዜወች እንዲጠቀሙበት፣ እያንዳንዱን ተጠቃሚ ከአንድ ዝክረ ይስሙላ እና ከአንድ ተዛማጅ ዝክረ ፈጪ ጋር እንዳገናኘን፣
  • የ‘ብስኩቶች (cookies) ዘዴን በመጠቀም፣ በአሳሹ ላይ አንድ የቋሚ ዝክረ ይስሙላ ብስኩትን በማስቀመጥ አንድ ቋሚ ክፍለጊዜን እንደፈጠርን፣
  • የግባት ሁኔታ የሚወሰነው፣ በአንድ የአሁንተጠቃሚ የጊዜያዊ ክፍለጊዜ የተጠቃሚ-መታወቂያ መኖር ወይም በቋሚ ክፍለጊዜ ልዩ ዝክረ ይስሙላ መኖር ላይ በመመርኮዝ እንደሆነ፣
  • አፕልኬሽኑ የክፍለጊዜውን የተጠቃሚ-መታወቂያ በመሰረዝ እና ቋሚ ብስኩቱን ከአሳሹ በማስወገድ ተጠቃሚዎችን እንደሚያስወጣ እና
  • የሶስቲት ስሌት፣ ቀላል የከሆነ-ካልሆነ ዓረፍተሐሳቦችን ለመጻፍ የሚያገለግል አንድ የተጠቀጠቀ የአጻጻፍ መንገድ እንደሆነ ተምረናል።
1. ፋየርሽፕ በተባለው አፕልኬሽን ምክንያት ምን ያህል የበይነመረብ ተጠቃሚዎች በክፍለጊዜ ጠለፋ እንደሚጠቁ በሰፊው ሊታወቅ ችሏል፤ ይህም ህዝባዊ አገልግሎት ከሚሰጥ የዋይ-ፋይ አውታረመረብ ጋር የተገናኙ ተጠቃሚዎች ዝክረ ይስሙላወቻቸው በግልጽ የሚታዩ መሆናቸውን አሳይቷል።
2. ሬይልስ 5 የተዘበራረቁ ይስሙላወችን በራስሰር የሚያመነጪ አንድ ጥብቅ_ይስሙላ_አለው (has_secure_token) የተባለ ዘዴ አስተዋውቋል፣ ይህ ዘዴ ያመነጫቸውን ይስሙላወች ሳይከትፍ ዋጋቸውን በቀጥታ በውሂበጎታ ውስጥ ያስቀምጣል፣ ስለሆነም ለአሁኑ ዓላማችን ተስማሚ አይደለም፡፡
3. ይህ ምርጫ በሬይልስካስት ዘክረኝ ላይ የተመሰረተ ነው፡፡
4. ያም ሆነ ይህ፣ በቢክሪፕት ጨው የተደረገባቸው (Salted) የሁለት ተጠቃሚዎች መሕለፈቃል ክትፎች ይዛመዱ እንደሆነ የምናውቅበት ምንም አይነት መንገድ የለም፡፡
5. እዚህ ላይ የተለያዩ ዝክረ ይስሙላወች ስለሚሆኑ አጥቂው ክፍለጊዜውን ለመጥለፍ ሁል ጊዜ ሁለቱን ማለት የተጠቃሚው መታወቂያ እና የተጠቃሚው ዝክረ ይስሙላ ያስፈልገዋል።
6. ይህ እውነታ አንዳንድ አበልጻጊወችን ይስሙላወች አንድ ዓይነት አለመሆናቸውን ለማረጋገጥ ሌላ ማረጋገጫን ከማከል አላገዳቸውም፤ ነገር ግን እንዲህ ያሉ ውሳኔወች የሚመጡት \( 10^{-40} \) ምን ያህል ትንሽ እንደሆነ ያለመረዳት ነው። ለምሳሌ:-ይቺ አለም ከተፈጠረች ግዜ ጀምሮ በአንድ ሰከንድ ውስጥ 1 ቢሊዮን ይስሙላወችን ብንፈጥር (\( 4.4\times10^7\,\mathrm{s} \)) ሁለት መሕለፈቃሎች አንድ ዓይነት መሕለፈቃል የመሆናቸው እድል \( 2\times10^{-23} \) ነው፡፡ ይህ ማለት በየትኛውም መንገድ ሲገለጽ ዜሮ ነው፡፡
7. በደንቡ መሰረት፣ አንድ ዘዴ የቁሱን ቅርፅ የማይፈልግ ከሆነ፣ ዘዴው የክፍል ዘዴ መሆን አለበት። በእርግጥ አሁን እዚህ ላይ ያደረግነው ውሳኔ ክፍል 11.2 ላይ ስንደርስ አስቀድሞ በብልሃት እንደተደረገ እናረጋግጣለን።
8.ክፍል 6.3.1 ላይ እንደተብራራው፣ “ያልተመሳጠረ መሕለፈቃል” የሚለው አባባል ትክክል አይደለም፣ ምክንያቱም መሕለፈቃሉ የተከተፈ እንጅ የተመሰጠረ ስላልሆነ ነው፡፡
9. እኔ በአጠቃላይ እንዲህ ዓይነቱን ምደባ እንደተለመደው በቅንፍ ውስጥ ማስገባትን እመርጣለሁ፤ ይህም በቅንፉ ውስጥ ያለው ኮድ እየተነጻጻረ እንዳልሆነ በማየት እንዳውቀው ስለሚረዳኝ ነው፡፡

10. ክቡር አንባቢ ጃክ ፋህኔቶክ፣ በአፕልኬሽኑ ላይ፣ አሁን ባለው ንድፍ ውስጥ ያልተካተተ አንድ (የጠርዝ ጉዳይ) እንዳለ ልብ ብለዋል:-

  1. “ዘክረኝ” ምልክት በተደረገበት በአሳሽ ሀ መግባት (ክትፍ ዝክረ ይስሙላ ሀን በ‘ዝክረ_ፈጪ (zkre_fech) ውስጥ ማስቀመጥ)።
  2. “ዘክረኝ” ምልክት በተደረገበት በአሳሽ በ መግባት (ክትፍ ዝክረ ይስሙላ በን በ‘ዝክረ_ፈጪ (zkre_fech) ውስጥ ማስቀመጥ፣ ይህም በአሳሽ ሀ ውስጥ የተቀመጠውን ዝክረ ይስሙላ ሀ ይተካል)።
  3. አሳሽ ሀ ተዘጋ (አሁን በቋሚ ብስኩቶች ላይ በመመርኮዝ፤ በሁለተኛው ሁኔታ በ‘ዓሁን_ተጠቃሚ (ahun_teteqami) ዘዴ ለመግባት)።
  4. አሳሹን እንደገና መክፈት (ምንም እንኳን ቋሚ ብስኩቶች በአሳሹ ላይ ቢኖሩም፡ ገብ_ቷልን? (geb_tual?) ሃሰትን ይመልሳል)።

ምንም እንኳን ይህ ተጠቃሚን በበርካታ ቦታዎች ከመዘከር የበለጠ አንድ ጥብቅ ንድፍ ቢሆንም፣ ተጠቃሚዎች ከአንድ አሳሽ በላይ፣ ላይ በቋሚነት ሊዘከሩ ይችላሉ የሚለውን ተስፋ ይጥሳል። መፍትሄው ከአሁኑ ንድፍ እጅግ በጣም የተወሳሰበ ነው፤ እያንዳንዱ አምድ አንድ የተጠቃሚ-መታወቂያ እና ፈጪ ያለው አንድ የተለለየ ሰንጠረዥ ውስጥ ዝክረ ፈጪውን እንዲገባ ማድረግ ነው፡፡ ከዚያ የአሁኑተጠቃሚን ለመፈተሽ፣ አንድ የተለየ ዝክረ ይስሙላ ጋር የሚጎዳኝ አንድ ፍጪን በሰንጠረዡ በኩል መመልከት ይሆናል፡፡ በተጨማሪም፣ በዝርዝር 9.11 ውስጥ ያለው የ‘እርሳ (ersa) ዘዴ፣ ከአሁን አሳሽ ፍጪ ጋር የሚጎዳኘውን አምድ ብቻ ይሰርዛል። ለጥበቃ ሲባል ዘግቶ መውጣት ለዚያ ተጠቃሚ ሁሉንም ፍጪወች ያስወግዳል፡፡

11. በስርዓታችሁ ውስጥ ብስኩቶችን እንዴት መመርመር እንደምትችሉ ለማወቅ፣ የአሳሻችሁን ስም ጎግል ላይ እንዲህ ብላችሁ አስገቡ “<የአሳሻችሁ ስም> inspect cookies”።
12. የተከበሩ አንባቢ ፓውሎ ሴሊዮ ጁኒዬርን፣ ይህንን ስለ ጠቆሙ ከልብ አመሰግናለሁ።
13. የተከበሩ አንባቢ ኒልስ ዴ ሮን ሴሊዮን፣ ይህንን ስለ ጠቆሙ ከልብ አመሰግናለሁ።
14. አስተውሉ፤ ይህ ማለት፣ አመልካችሳጥኑ ላይ ምልክት ካልተደረገ ተጠቃሚውን፣ ሁሉ ኮምፒዩተር ላይ ካሉ አሳሾች ውስጥ ያስወጣዋል ማለት ነው፡፡ በእያንዳንዱ አሳሽ ላይ በተናጠል የተጠቃሚ መግቢያ ክፍለጊዜወችን ማስታወስ የሚችል ሌላ ንድፍ ማድረጉ፣ ለተጠቃሚዎች ይበልጥ ምቹ ቢሆንም፣ ጥብቅነቱ ግን እጅግ የደከመ እና ለመተግበርም በጣም የተወሳሰበ ነው፡፡ ከፍተኛ ፍላጎት ያላቸው አንባቢዎች ደግሞ፣ ይህንን ተግባራዊ ለማድረግ እንዲሞክሩ ከወዲሁ ግብዣው ቀርቦላቸዋል፡፡
15. ካሁን በፊት የ‘ዘክር ተጠቃሚ (zekr teteqami) ዘዴን ያለ ቅንፍ አስቀምጠነው ነበር፣ በሶስቲት ስሌት ሲጻፍ ግን፣ የ‘ተጠቃሚ (teteqami) ቁሱ ግዴታ በቅንፍ ውስጥ መግባት አለበት፤ ካለበለዚያ ግን አንድ የአገባብ ስህተትን ያስከትላል፡፡