ምዕራፍ 6 ተጠቃሚዎችን መቅረጽ

ምዕራፍ 5 ውስጥ አዲስ ተጠቃሚዎችን ለመፍጠር አንድ የተቆረጠ ገጽን በመፍጠር አጠናቀን ነበር (ምዕራፍ 5.4)። በሚቀጥሉት ስድስት ምዕራፎች ውስጥ፣ ለዚህ ጨቅላ የምዝገባ ገጽ የተገባውን ቃል ኪዳን እናሟላለን፡፡ በዚህ ምዕራፍ ውስጥ የተጠቃሚዎች ውሂብ የምናስቀምጥበትን መንገድ እና ለጣቢያችን ተጠቃሚዎች አንድ የውሂብ ቅርጽን ለመቅረጽ የመጀመሪያውን ወሳኝ እርምጃ እንወስዳለን፡፡ በምዕራፍ 7 ውስጥ ተጠቃሚዎች ለጣቢያችን የሚመዘገቡበትን እና አንድ የመገለጫ ገጽ የሚፈጥሩበትን ችሎታ እንሰጣለን፡፡ አንዴ ተጠቃሚዎች ከተመዘገቡ በኋላ ወደ ጣቢያው እንዲገቡ እና ከጣቢያው እንዲወጡ እናስችላቸዋለን (ምዕራፍ 8 እና ምዕራፍ 9)፣ እና በምዕራፍ 10 (ክፍል 10.2.1) ውስጥ ገጾችን አላግባብ ከሆነ ድርሰት እንዴት እንደምንከላከል እንማራለን፡፡ በመጨረሻም፣ በምዕራፍ 11 እና በምዕራፍ 12 ላይ የመለያ ግባሬወችን (በዚህም አንድ ትክክለኛ የኤመልእክት አድራሻ መኖሩን እናረጋግጣለን) እና የመሕለፈቃል ዳግም ማስጀመርያን እናክላለን፡፡ ከምዕራፍ 6 ጀምሮ እስከ ምዕራፍ 12 ያሉትን ነገሮች በሙሉ አንድ ላይ ማጣመሩ፣ አንድ የሬይልስ አፕልኬሽን የመግቢያ እና የማረጋገጫ ስርዓትን ይገነባል። ሬይልስ የተለያዩ ቀድመው-የተገነቡ የማረጋገጫ መፍትሄዎች እንዳሉት ምናልባት ታውቁ ይሆናል፣ ሳጥን 6.1 ቢያንስ ቢያንስ መጀመሪያ ላይ፣ አንድ የራሳችሁ የሆነ የማስረገጫ ስርዓት እንዲኖር ማድረጉ ለምን የተሻለ ሃሳብ እንደሆነ ያሳያል፡፡

ሳጥን 6.1. የራሳችሁን የማስረገጫ ስርዓት ማካሄድ

ሁሉም የድር አፕልኬሽኖች ማለት ይቻላል የሆነ ዓይነት የመግቢያ እና የማረጋገጫ ስርዓት ያስፈልጋቸዋል፡፡ በዚህ ምክንያትም አብዛኛዎቹ የድር መዋቅሮች ከአንድ ወይም ከብዙ መደበኛ ቤተኮዶች ላይ ይወሰናሉ፤ እና ሬይልስም ከነሱ የተለየ አይደለም፡፡ በተለይም ዲቫይስ የተባለው እንቁ ለበርካታ የተለያዩ አጠቃቀሞች እንደ አንድ ብቁ መፍትሄ ሆኖ ብቅ ብሏል፣ በዚህ ምክንያትም ሞያዊ-ደረጃ ባላቸው አፕልኬሽኖች ዘንድም የበላይ የሆነ ተመራጪነትን ተቀናጅቷል።

የሆነ ሆኖ፣ እንደ ዲቫይስ ያለ ቤተኮድን ማለት ቅድሞ-ገነብ ስርዓትን እንደዚህ ያለ ስልጠና ላይ መጠቀሙ ስህተት ነው ብዬ አምናለሁ። (በእርግጥ፣ ዲቫይስ ራሱ ይህንን ስልጠና እንድታነቡ ይመክራል።) የተዘጋጁ ስርዓቶች እምቅ እና ምስጢራዊ በሆነ ነገር ውስጥ ያሉ “እንቆቅልሾች” ሊሆኑ ይችላሉ፣ እናም እነዚህ ስርዓቶች የተጠቀሙባቸው የተወሳሰቡ የውሂብ አቀራረጾች፣ ለጀማሪዎች (ወይም የውሂብ አቀራረጽን ጠንቅቀው ለሚያውቁ ልምድ ላላቸው አበልጻጊወች ሳይቀር) እጅግ ግራ የሚያጋቡ ይሆናሉ፡፡ እናም ርዕሰ ጉዳዩን እንደ ማስተማሪያ አድርጎ ለመጠቀም፣ ርዕሰ ጉዳዩን ቀስ በቀስ ማስተዋወቁ አስፈላጊ ይሆናል፡፡ የሚያስደስተው ነገርም፣ ሬይልስ አንድ ለምርት አፕልኬሽን ተስማሚ የሆነ በጣም ጠንካራ የመግቢያ እና የማረጋገጫ ስርዓት ማበልጸጉን ቀስ በቀስ እንድትደርሱበት ማስቻሉ ነው። በዚህ መንገድ፣ በኋላ ላይ በሌሎች የተሰራ አንድ የመግቢያ እና የማረጋገጫ ስርዓት ብትጠቀሙ እንኳን በቀላሉ ልትረዱት እና እንደፈላጋችሁት ልታሻሽሉት በሚያስችላችሁ የተሻለ ደረጃ ላይ ትሆናላችሁ፡፡

6.1 የተጠቃሚ ቅርጸት

የሚቀጥሉት ሶስት ምዕራፎች ዋና አላማ ለጣቢያችን አንድ የምዝገባ ገጽ መስራት ቢሆንም፣ (በምስል 6.1 ላይ በስእላዊ መግለጫው ላይ ለማሳየት እንደተሞከረው) ይህ የምዝገባ ገጽ አሁን የአዲስ ተጠቃሚዎች መረጃን ለመቀበል ግን አያገለግልም፤ በአሁኑ ጊዜ እነዚህን መረጃዎች ለማስቀመጥ የምንችልበት ምንም ቦታ የለንም፡፡ ስለዚህ ተጠቃሚዎችን በመመዝገብ (አባል በማድረግ) ስራ ውስጥ የመጀመሪያው ሂደት መረጃቸውን ለመያዝ እና ለማከማቸት አንድ የውሂብ መዋቅርን መስራት ነው፡፡

images/figures/signup_mockup_bootstrap
ምስል 6.1: የተጠቃሚ የምዝገባ ገጽ ስእላዊ መግለጫ።

በሬይልስ ውስጥ፣ ለአንድ የውሂብ ቅርጸት፣ ነባሪው የውሂብ አወቃቀር እንደምትጠብቁት፣ ቅርጸት (Model) ተብሎ ይጠራል (በክፍል 1.2.3 ውስጥ እንደተመለከተው፣ “ቅ (M)” በ‘ቅ.ተ.መ (MVC) ውስጥ ያለውን የ “ቅ (M)” ተግባርን ያመለክታል)፡፡ ጽናትን ለመቛቛም የሬይልስ መፍትሄ አንድ የውሂበጎታን ለረጅም-ጊዜ የውሂብ ማከማቻ አድርጎ በነባሪነት መጠቀም ሲሆን፤ ከውሂበጎታው ጋር መስተጋብርን ለመፍጠር ደግሞ ንቅ መዝገብ (Active Record)1 የተባለውን ቤተኮድ በነባሪነት ይጠቀማል። ንቅ መዝገብ፣ በተዛማጅ ውሂበጎታወች (Relational Databases) ጥቅም ላይ የዋለውን ቀላል የመጠይቅ ቋንቋን (ቀ.መ.ቋን (SQL))2 ማለት ከውሂበጎታ መረጃዎችን ለመፈለግ የሚያገለግለውን ቋንቋ ሳይጠቀም ቁስን ለመፍጠር፣ ውሂበጎታ ላይ ለማስቀመጥ፣ ለማጥፋት፣ ለማዘመን፣ ውሂብን ከውሂበጎታ ለመፈለግ እና ብዙ ነገሮችን ለማድረግ የሚያገለግሉ ዘዴወች ጋር ይመጣል። በተጨማሪም ሬይልስ የተ.መ.ቋን የውሂብ መበየኛ ቋንቋን (ው.መ.ቋ) (Data Definition Language (DDL)) መማር ሳያስፈልግ፣ የውሂብ ብይኖችን በንጹህ ሩቢ ለመጻፍ የሚያስችል አንድ ፍልሰት (Migration) የተባለ ገጸባህሪ አለው፡፡ በዚህ ምክንያትም ሬይልስ ውሂበጎታው ላይ ስለሚደረገው ነገር በዝርዝር እንዳታውቁ እንቅፋት ይሆንባችኋል ማለት ነው፡፡ ይህ በንዲህ እንዳለ፣ በዚህ መጽሐፍ ውስጥ፣ ቀላል የመጠይቅ ቋንቋ (SQLite) የተባለውን ውሂበጎታ ለብልጸጋ እና ፖስትግሬስተ.መ.ቋ የተባለውን ውሂበጎታ ደግሞ በሃረኩ ላይ ለምርት እንድንጠቀም ብቻ ሳይሆን (ክፍል 1.4)፣ ሬይልስ በሁለቱም ማለት በብልጸጋ እና በምርት አፕልኬሽናችን ውሂበጎታ ውስጥ ውሂብን እንዴት እንደሚያስቀምጥ በጪራሽ ማሰብ እንደለለብን ከወዲሁ እንደመድማለን።

እንደተለመደው፣ ጊትን ለስሪት መቆጣጠሪያ እየተጠቀማችሁ ከሆነ፣ አሁን ለተጠቃሚዎች ቅርጸት አንድ የርእስ ቅርንጫፍን ለማድረግ ጥሩ ጊዜ ይሆናል:-

$ git checkout -b ተጠቃሚዎችን-መቅረጽ

6.1.1 ውሂበጎታን ማፍለስ

በአንድ ብጁ-ግንብ የ‘ተጠቃሚ (Teteqami) ክፍል በኩል፣ ከተጠቃሚ ቁሶች ማለት ከ‘ስም (sim) እና ከ‘ኤመልእክት (emelekt) ባሕሪወቻቸው ጋር ቀደም ሲል ማለት በክፍል 4.4.5 ቆይታችን ላይ እንደተገጣጠምን ታስታውሱ ይሆናል። ያ ክፍል በወቅቱ ልክ እንደ አንድ ጠቃሚ ምሳሌ ሆኖ አገልግሎ ነበረ፣ ነገር ግን ወሳኙ የመጽናት ባህሪ ይጎድለዋል:- አንድ የተጠቃሚ ቁስ በሬይልስ ሰሌዳ ላይ ስንፈጥር ልክ ከሰሌዳው ስንወጣ የፈጠርነው የተጠቃሚ ቁስ ይጠፋል። በዚህ ክፍል ውስጥ ግባችን እንዲሁ በቀላሉ ለማይጠፉ ተጠቃሚዎች የሚሆን አንድ የተጠቃሚወች ቅርጸትን መፍጠር ነው፡፡

ልክ በክፍል 4.4.5 ላይ ለተጠቃሚዎች ክፍል እንዳደረግነው ሁሉ፣ ከሁለት ባሕሪወች ማለት ከአንድ የ‘ስም (sim) እና ከአንድ የ‘ኤመልእክት (emelekt) ባሕሪወች ጋር አንድ ተጠቃሚን በመቀረጽ እንጀምራለን፣ የኋለኛውን ባሕሪ ደግሞ እንደ አንድ ልዩ የተጠቃሚስም3 እንጠቀምበታለን፡፡ (በክፍል 6.3 ውስጥ አንድ ባሕሪ ለመሕለፈቃል እናክላለን።) በዝርዝር 4.17 ውስጥ ይህንንም በሩቢ የ‘ባሕሪ_መዳረሻ (attr_accessor) ዘዴን በመጠቀም እንዲህ አድርገን ሰርተነው ነበር፡-

class Teteqami
  attr_accessor :ስም, :ኤመልእክት
  .
  .
  .
end

በተቃራኒው፣ ተጠቃሚዎችን ለመቅረጽ ሬይልስን በምንጠቀምበት ጊዜ፣ ባሕሪያቸውን በግልጽ መለየት አያስፈልገንም። ሬይልስ ከላይ ባጪሩ እንደተመለከተው፣ ውሂቦችን ለማከማቸት አንድ ተዛማጅ ውሂበጎታን በነባሪነት ይጠቀማል፣ ይህም እያንዳንዱ ረድፍ የውሂብ ባሕሪወች አምዶች ያሉበት፣ በውሂብ ረድፎች የተዋቀሩ ሰንጠረዦችን ያቀፈ ነው። ለምሳሌ:- ተጠቃሚወችን እስከ ስማቸው እና የኤመልእክት አድራሻቸው ውሂበጎታ ላይ ለማስቀመጥ ብንፈልግ፣ አንድ ተጠቃሚዎች (teteqamis) የተባለ ሰንጠረዥን ስም (sim) እና ኤመልእክት (emelekt) ከተባሉ አምዶች ጋር እንፈጥራለን (አንድ ረድፍ ከአንድ ተጠቃሚ ጋር የተጎዳኘ ይሆናል)፡፡ የዚህ ሰንጠረዥ ምሳሌ በምስል 6.2 ውስጥ በምስል 6.3 ላይ ከተመለከተው የውሂብ ቅርጸት ጋር ይዛመዳል፡፡ (ምስል 6.3 ላይ ያለው ንድፍ፣ አጠር ያለ ንድፍ ብቻ ነው፣ ሙሉው የውሂቡ ቅርጸት ግን በምስል 6.4 ላይ ይታያል፡፡) አምዶቹን ስም (sim) እና ኤመልእክት (emelekt) ብለን በመሰየም፣ ንቅ መዝገብ የተጠቃሚ ቁስ ባሕሪወቹን እራሱ እንዲለይ እንተውለታለን።

images/figures/users_table
ምስል 6.2: በ‘ተጠቃሚዎች (teteqamis) ሰንጠረዥ ውስጥ ያለ ምሳሌያዊ ውሂብን የሚያሳይ አንድ ስእላዊ መግለጫ።
images/figures/user_model_sketch
ምስል 6.3: አንድ የተጠቃሚ የውሂብ ቅርጸት ንድፍ።

ዝርዝር 5.38 ላይ አንድ የተጠቃሚወች መቆጣጠሪያን (ከአንድ አዲስ (new) ተግባር ጋር) በሚከተለው ትእዛዝ እንደፈጠርን ታስታውሱ ይሆናል፡-

$ rails generate controller Teteqamis new

አንድ ቅርጸትን ለመፍጠር ተመሳሳዩ ትእዛዝ ደግሞ የ‘ቅርጸት-አመንጪ (generate model) ትእዛዝ ነው፣ በዝርዝር 6.1 ላይ እንደሚታየው፣ ይህንን ትእዛዝ አንድ የተጠቃሚ ቅርጸትን ከ‘ስም (sim) እና ከ‘ኤመልእክት (emelekt) ባሕሪወች ጋር ለማመንጨት ልንጠቀምበት እንችላለን፡፡

ዝርዝር 6.1: አንድ የተጠቃሚ ቅርጸትን ማመንጨት።
$ rails generate model Teteqami sim:string emelekt:string
      invoke  active_record
      create    db/migrate/20201105235800_create_teteqamis.rb
      create    app/models/teteqami.rb
      invoke    test_unit
      create      test/models/teteqami_test.rb
      create      test/fixtures/teteqamis.yml

(በደንቡ መሰረት የመቆጣጠሪያ ስሞች በድርብ ስም ሲጠሩ፣ የቅርጸት ስሞች ደግሞ በአንጻሩ በነጠላ ስማቸው ይጠራሉ፤ ስለዚህ የተጠቃሚ መቆጣጠሪያ አንድ የ‘ተጠቃሚወች (Teteqamis) መቆጣጠሪያ ተብሎ ሲሰየም፣ የተጠቃሚ ቅርጸት ደግሞ አንድ የ‘ተጠቃሚ (Teteqami) ቅርጸት ተብሎ ይሰየማል ማለት ነው፡፡ ይህንንም በደንብ ልናጤነው ይገባል።) የምንፈልጋቸው ሁለት ባሕሪወች ምን ዓይነት መሆን እንዳለባቸው (ማለት በዚህ ሁኔታ ላይ የውሂብ ምርጫችን ሃረግ (string) ነው) ከሁለት አማራጪ ሰሚአሴቶች ማለት ስም:ሃረግ (sim:string) እና ኤመልእክት:ሃረግ (emelekt:string) የተባሉ ሰሚአሴቶችን በማሳለፍ ሬይልስ ይህንን ትእዛዝ እንዲፈጽም እንነግረዋለን፡፡ ይህንን በዝርዝር 3.7 እና በዝርዝር 5.38 ውስጥ የተግባር ስሞችን ከማካተት ጋር አነጻጽሩት፡፡

ዝርዝር 6.1 ውስጥ የ‘አመንጪ (generate) ትእዛዝ ከሚያስገኛቸው ውጤቶች ውስጥ አንዱ፣ አንድ ፍልሰት (Migration) የተባለ አዲስ ፋይል ነው፡፡ ፍልሰቶች የውሂበጎታ አወቃቀሩን አከታትሎ ለመቀየር አንድ መንገድን ይሰጣሉ፣ ስለሆነም የውሂብ ቅዳችን ከተለወጡ መስፈርቶች ጋር እንዲስማማ ያደርጋሉ፡፡ በዝርዝር 6.2 ላይ እንደሚታየው፣ በተጠቃሚ ቅርጸቱ ሁኔታ ላይ ብንመለከት፣ ፍልሰቱ በቅርጸት ማመንጫ ትእዛዙ በራስሰር የተፈጠረ ነው፤ እሱም ከሁለት ማለት ከ‘ስም (sim) እና ከ‘ኤመልእክት (emelekt) አምዶች ጋር አንድ ተጠቃሚዎች (teteqamis) የተባለ ሰንጠረዥን ይፈጥራል። (ፍልሰትን በመጠቀም አንድ የውሂበጎታ ሰንጠረዥ ከባዶ ተነስቶ እንዴት እንደሚሰራ ከክፍል 6.2.5 ጀምረን እንመለከታለን፡፡)

ዝርዝር 6.2: አንድ የተጠቃሚ ቅርጸት ማፍለሻ (አንድ የ‘ተጠቃሚዎች (teteqamis) ሰንጠረዥን ለመፍጠር)፡፡ db/migrate/[ማህተመጊዜ]_create_teteqamis.rb
class CreateTeteqamis < ActiveRecord::Migration[6.0]
  def change
    create_table :teteqamis do |t|
      t.string :sim
      t.string :emelekt

      t.timestamps
    end
  end
end

ፍልሰቱ በመነጨበት ጊዜ ላይ በመመርኮዝ፣ የፍልሰቱ ፋይል ስም ከአንድ ማህተመጊዜ ቅድመቅጥያ ጋር ተያይዞ የተቀመጠ መሆኑን ልብ በሉ። ካሁን በፊት በነበረው አሰራር ላይ የፍልሰት ፋይል ስሞች በተከታታይ ሙሉ ቁጥሮች ቅድመቅጥያ ይሰየም ነበር። ይህም የበርካታ አበልጻጊወች የፍልሰት ፋይል ቁጥር፣ ከሌሎች ተባባሪ ቡድኖች ጋር አንድ ዓይነት በሚሆንበት ጊዜ ከፍተኛ እንቅፋት ይፈጥር ነበር። በአሁኑ ጊዜ ያለው አሰራር ግን፣ በአንድ ዓይነት ሰከንድ ውስጥ ብዙ ፍልሰቶች መፍጠሩ ፍጹም ሊሆን እንደማይችል ግምት ውስጥ በማስገባት፣ ማህተመጊዜያቸውን በመጠቀም እነዚህን እንቅፋቶች ለማስወገድ በቅቷል።

ፍልሰቱ ራሱ ለውጡ ወደ ውሂበጎታው እንዲደረግ የሚወስነውን አንድ የ‘ለውጥ (change) ዘዴን ያካትታል፡፡ በዝርዝር 6.2 ላይ የ‘ለውጥ (change) ዘዴው በውሂበጎታው ውስጥ ተጠቃሚዎችን ለመያዝ የሚያገለግል አንድ ሰንጠረዥን ለ‘መፍጠር ሰንጠረዥ_ፍጠር (create_table) የተባለ የሬይልስ ዘዴን ይጠቀማል፡፡ የ‘ሰንጠረዥ_ፍጠር (create_table) ዘዴው አንድ የጥምር ተለዋዋጪ4 ጋር አንድ ጥምርን ይቀበላል (ክፍል 4.3.2)፣ በዚህ ጉዳይ ላይ ተለዋዋጩ ሰ (t) (ለ “ሰንጠረዥ (table)”) ይባላል፡፡ በጥምሩ ውስጥ የ‘ሰንጠረዥ_ፍጠር (create_table) ዘዴው ሁለቱንም የ‘ሃረግ (string) አይነቶች ማለት የ‘ስም (sim) እና የ‘ኤመልእክት (emelekt) አምዶችን በውሂበጎታው ውስጥ ለመፍጠር የ t ቁስን ይጠቀማል። በዚህ ጊዜ የሰንጠረዡ ስም የብዙ መጠሪያ ስም ማለት:- (ተጠቃሚዎች (teteqamis)) ሲሆን፤ የቅርጸት ስሙ ግን ነጠላ ማለት:- (ተጠቃሚ (Teteqami)) ነው፡፡ ይህም ቅርጸት አንድ ነጠላ ተጠቃሚን ይወክላል፣ አንድ የውሂበጎታ ሰንጠረዥ ደግሞ ብዙ ተጠቃሚዎችን ይወክላል፣ የሚለውን የሬይል ባህላዊ አባባልን ያመለክታል፡፡ በጥምሩ ውስጥ ያለው፣ የመጨረሻው የ‘ሰ.ማህተመጊዜ (t.timestamps) መስመር፣ ተፈጠረ_በ (created_at) እና ተዘመነ_በ (updated_at) የሚባሉ ሁለት አስማታዊ አምዶችን የሚፈጥር ልዩ ትእዛዝ ነው፣ እነሱም አንድ ተጠቃሚ ልክ ሲፈጠር እና ሲዘምን በራስሰር የሚመዘግቡ ማህተመጊዜወች ናቸው፡፡ (ከክፍል 6.1.3 ጀምሮ ስለ እነዚህ አስማታዊ አምዶች ተጨባጪ የሆኑ ምሳሌዎችን እንመለከታለን፡፡) በዝርዝር 6.2 በፍልሰቱ የቀረበው ሙሉው የውሂብ ቅርጸት በምስል 6.4 ውስጥ ይታያል፡፡ (በምስል 6.3 ላይ በቀረበው ንድፍ ላይ የለሉት አስማታዊ አምዶች እዚህ ላይ እንደቀረቡ ልብ በሉ፡፡)

user_model_initial_3rd_edition
ምስል 6.4: ዝርዝር 6.2 የተሰራው የተጠቃሚው የውሂብ ቅርጸት።

“ወደ ላይ ማፍለስ (Migrating Up)” በመባል የሚታወቅውን የ‘ውጎ:አፍልስ (db:migrate) ትእዛዝን እንደሚከተለው አድርገን በመጠቀም ፍልሰቱን ማስኬድ እንችላለን:-

$ rails db:migrate

(በክፍል 2.2 ይህንን ትእዛዝ በአንድ ተመሳሳይ ሁኔታ ላይ እንደተጠቀምንበት ታስታውሱ ይሆናል፡፡) ለመጀመሪያ ጊዜ የ‘ውጎ፡አፍልስ (db:migrate) ትእዛዙ ሲሄድ፣ አንድ ውጎ/ብልጸጋ.ቀመቋ3 (db/development.sqlite3) የተባለ ፋይልን ይፈጥራል፤ ይህም አንድ የ‘ቀ.መ.ቋ (SQLite)5 ውሂበጎታ ነው፡፡ የ‘ውጎ/ብልጸጋ.ቀመቋ3 (db/development.sqlite3) ፋይልን የቀ.መ.ቋ የውሂብጎታ አሳሽን (DB Browser for SQLite) በመጠቀም የውሂበጎታውን መዋቅር ማየት እንችላለን፡፡ (የደመና ቅ.ማ.አን አየተጠቀማችሁ ከሆነ፣ በምስል 6.5 ውስጥ እንደሚታየው፣ በመጀመርያ የውሂበጎታ ፋይሉን በሰፈር ዲስካችሁ ላይ መጫን ይኖርባችኋል)፡፡ በምስል 6.6 ውስጥ የሚታየውን ውጤት ከምስል 6.4 ጋር ስታነጻጽሩ በምስል 6.6 ላይ መታወቂያ (id) የተባለ ፍልሰትን የማያካትት አንድ አምድ አይታችሁ ሊሆን ይችላል፡፡ በክፍል 2.2 ውስጥ ባጪሩ እንደተገለጸው፣ ይህ አምድ በራስሰር የተፈጠረ ነው፤ እናም ሬይልስም እያንዳንዱን ረድፍ በተናጠል ለመለየት ይጠቀምበታል፡፡

images/figures/sqlite_download
ምስል 6.5: ከደመና ቅ.ማ.አው አንድ ፋይልን ማውረድ።
images/figures/sqlite_database_browsera
ምስል 6.6: DB የተባለው የውሂበጎታ ማሳያ ከአዲሱ የ‘ተጠቃሚዎች (teteqamis) ሰንጠረዥ ጋር።

መልመጃዎች

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

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

  1. ሬይልስ የውሂበጎታውን አወቃቀር ለመከታተል በ‘ውጎ/ (db/) ማውጫ ውስጥ የሚገኘውን እና መርሃግብር.አርቢ (schema.rb) ተብሎ የሚጠራውን ፋይል ይጠቀማል (ስለሆነም የፋይል ስሙ መርሃግብር (Schema) ተብሎ ይጠራል)፡፡ የናንተን የ‘ውጎ/መርሃግብር.አርቢ (db/schema.rb) ፋይል ይዞታ ከዝርዝር 6.2 ፍልሰት ኮድ ይዞታ ጋር አነጻጽሩ፡፡
  2. አብዛኛዎቹ ፍልሰቶች (በዚህ ስልጠና ውስጥ ያሉትን ሁሉ ጨምሮ) ሊቀለበሱ ይቻላሉ፣ ይህ ማለት ውጎ፡ቀልብስ (db:rollback) የተባለውን አንድ ነጠላ ትእዛዝ በመጠቀም ፍልሰቶቹን “ወደ ታች ማፍለስ (Migrate Down)” እና መቀልበስ እንችላለን ማለት ነው:-
      $ rails db:rollback
    
    ይህንን ትእዛዝ ካስዳችሁ በኋላ፣ የመቀልበሱ ሂደት ስኬታማ እንደነበረ ለማረጋገጥ የ‘ውጎ/መርሃግብር.አርቢ (db/schema.rb) ፋይልን በመመርመር አረጋግጡ፡፡ (ፍልሰቶችን ለመቀልበስ የሚያገለግል ሌላ ጠቃሚ ዘዴ ለማግኘት ሳጥን 3.1 ን ተመልከቱ።) ይህ ትእዛዝ የተጠቃሚዎች ሰንጠረዥን ከውሂበጎታው ላይ ለማስወገድ የ‘ሰንጠረዥ_ጣል (drop_table) ትእዛዝን በውስጡ ይፈጽማል። ይህ የሚሰራበት ምክንያት የ‘ለውጥ (change) ዘዴው፣ የ‘ሰንጠረዥ_ጣል (drop_table) ዘዴ የ‘ሰንጠረዥ_ፍጠር (create_table) ዘዴ ተገላቢጦሹ መሆኑን ስለሚያውቅ፣ መልሶ መቀልበሱን በቀላሉ መገመት ስለሚችል ነው። የማይቀለበስ ፍልሰትን በተመለከተ፣ ለምሳሌ አንድ የውሂብጎታ አምድን ለማስወገድ፣ ከነጠላው የ‘ለውጥ (change) ዘዴ ምትክ የተለያዩ የ‘ወደላይ (up) እና የ‘ወደታች (down) ዘዴዎችን መበየኑ አስፈላጊ ነው፡፡ ስለ ሬይልስ ፍልሰት ተጨማሪ መረጃ ለማግኘት የሬይልስ መመሪያዎች ላይ ማንበብ ይቻላል።
  3. የ‘ሬይልስ ውጎ:አፍልስ (rails db:migrate) ትእዛዝን እንደገና በማከናወን ፍልሰቱን እንደገና አስኪዱ። ከዚያ የ‘ውጎ/መርሃግብር.አርቢ (db/schema.rb) ፋይል ይዞታ ልክ ካሁን በፊት ወደነበረበት ይዞታ መመለሱን አረጋግጡ፡፡

6.1.2 የቅርጸት ፋይል

ዝርዝር 6.1 ላይ ያለው የተጠቃሚ ቅርጸት ግኝት እንዴት በዝርዝር 6.2 ላይ ያለውን አንድ የፍልሰት ፋይል እንዳስገኘ አይተናል፣ ይህንን ፍልሰት የማስፈጸም ውጤትንም በምስል 6.6 አይተናል፤ ይህም አንድ ተጠቃሚዎች (teteqamis) የተባለ ሰንጠረዥ መታወቂያ (id)፣ ስም (sim)፣ ኤመልእክት (emelekt)፣ ተፈጠረ_በ (created_at) እና ተዘመነ_በ (updated_at) የተባሉ አምዶችን በመፍጠር ብልጸጋ.ቀመቋ3 (development.sqlite3) የተባለውን ፋይል እንዳዛመነ አይተናል፡፡ ዝርዝር 6.1 ራሱ ቅርጸቱንም ፈጥሯል፡፡ የዚህ ክፍል ቀሪ ጊዜ፣ እሱን ለመረዳት የተመደበ ይሆናል፡፡

በ‘አፕ/ቅርጸቶች/ (app/models/) ማውጫ ውስጥ ባለው እና በ‘ተጠቃሚዎች.አርቢ (teteqami.rb) ፋይል ውስጥ በሚኖረው ማለት የተጠቃሚ ቅርጸት ኮድን በመመልከት እንጀምራለን። ይህም በሌላ አማርኛ፣ በጣም የተጠቀጠቀ ኮድ ነው (ዝርዝር 6.3)።

ዝርዝር 6.3: ውሃ ያልቀመሰው አዲሱ የተጠቃሚ ቅርጸት። app/models/teteqami.rb
class Teteqami < ApplicationRecord
end

ክፍል 4.4.2 ላይ ይህ አገባብ class Teteqami < ApplicationRecord ማለት የ‘ተጠቃሚ (Teteqami) ክፍል ከ‘አፕልኬሽንመዝገብ (ApplicationRecord) ክፍል ይወርሳል ማለት ነው ብለን እንደተማርን አስታውሱ፤ ይህ ደግሞ ከ‘አፕልኬሽንመዝገብ::መሰረት (ActiveRecord::Base) ክፍልም ይወርሳል (ምስል 2.20)፤ በዚህ ምክንያትም የተጠቃሚ ቅርጸቱ የ‘አፕልኬሽንመዝገብ::መሰረት (ActiveRecord::Base) ተግባራት ሁሉ በራስሰር ይኖረዋል ማለት ነው፡፡ ይህ በንዲህ እንዳለ፣ አፕልኬሽንመዝገብ::መሰረት (ActiveRecord::Base) የያዘውን ካላወቅን በስተቀር እንዴት እንደሚወራረስ ማወቁ ብቻ የትም አያደርሰንም፤ ስለሆነም አንዳንድ ተጨባጪ በሆኑ ምሳሌዎች እንጀምራለን፡፡

መልመጃዎች

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

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

  1. በአንድ የሬይልስ ሰሌዳ ውስጥ፣ በክፍል 4.4.4 ላይ የተሰጠውን የአሰራር ዘዴ በመጠቀም፣ አዲስ.ተጠቃሚ (Teteqami.new) የ‘ተጠቃሚ (Teteqami) ክፍል እንደሆነ እና ከ‘አፕልኬሽንመዝገብ (ApplicationRecord) እንደሚወርስ አረጋግጡ፡፡
  2. አፕልኬሽንመዝገብ (ApplicationRecord) ከ‘አፕልኬሽንመዝገብ::መሰረት (ActiveRecord::Base) እንደሚወርስ አረጋግጡ፡፡

6.1.3 የተጠቃሚ ቁሶችን መፍጠር

ምዕራፍ 4 ላይ እንደተጠቀምንበት ሁሉ፣ አሁንም የውሂብ ቅርጸቶችን ለመመርመር የምንጠቀምበት መሳርያ የሬይልስ ሰሌዳን ይሆናል፡፡ በውሂበጎታችን ላይ ምንም ዓይነት ለውጥ ማድረግ ስለማንፈልግ በአንድ የአሸዋሳጥን (Sandbox) ውስጥ እንጀምራለን:-

$ rails console --sandbox
Loading development environment in sandbox
Any modifications you make will be rolled back on exit
>>

“እናንተ የምታደርጓቸው ማናቸውም ማሻሻያዎች በሙሉ፣ እናንተ በምትወጡበት ጊዜ ወደ ነበሩበት ይመለሳሉ” በሚለው ጠቃሚ መልእክት እንደተመለከተው፣ በአንድ የአሸዋሳጥን ውስጥ ስለጀመርን በዚህ የሰሌዳ ክፍለ ጊዜ ውስጥ የምናደርጋቸውን ማናቸውም የውሂበጎታ ለውጦች ልክ ሰሌዳውን ዘግተን ስንወጣ ሰሌዳው “ቀድሞ ወደ ነበሩበት (roll back)” ሁኔታቸው ይመልሳቸዋል (ማለት ይቀለብሳቸዋል)፡፡

ክፍል 4.4.5 ውስጥ በሰሌዳ ክፍለ ጊዜ፣ በ‘አዲስ.ተጠቃሚ (Teteqami.new) አንድ አዲስ የተጠቃሚ ቁስን ፈጥረን ነበር፤ ይህን አዲስ ተጠቃሚ በሰሌዳው ውስጥ ልንደርስ የቻልነው በዝርዝር 4.17 ውስጥ የፈጠርነውን የ‘ አብነታዊ_ተጠቃሚ.rb ፋይልን በሰሌዳው ውስጥ እንዲገኝ የሚያደርገውን የ‘ጠይቅ (require) ዘዴን በመጠቀም ብቻ ነበረ፡፡ ቅርጸቶችን የሬይልስ ሰሌዳ ውስጥ ለመጠቀም ግን ሁኔታው ለየት ያለ ነው፣ በክፍል 4.4.4 ላይ እንደምታስታውሱት፣ የሬይልስ ሰሌዳ በራስሰር የሬይልስ አካባቢን ይጪናል፤ ይህ ቅርጸቶችንም ያካትታል ማለት ነው። ይህ ማለት ደግሞ ያለምንም ተጨማሪ ስራ አንድ አዲስ የተጠቃሚ ቁስን መስራት እንችላለን ማለት ነው:-

>> Teteqami.new
=> #<Teteqami id: nil, sim: nil, emelekt: nil, created_at: nil, updated_at: nil>

እዚህ ላይ የአንድ የተጠቃሚ ቁስ ነባሪ የሰሌዳ አቀራረብን እናያለን።

ያለምንም ነጋሪአሴት አዲስ.ተጠቃሚ (Teteqami.new) ብለን ስንጠራ፣ አዲስ.ተጠቃሚ (Teteqami.new) አንድ ሁሉም ባሕሪወቹ የ‘ምንም (nil) ዋጋ ያለው ቁስን ይመልሳል። ክፍል 4.4.5 ውስጥ፣ የአብነታዊ ተጠቃሚ ክፍል የቁሱ ባሕሪወችን እንዲያዘጋጅ አንድ የተርታ ማስጀመርያን (Initialization Hash) እንዲወስድ ነድፈን ነበረ፡፡ ለዛ ንድፍ ምርጫ ያነሳሳን የ‘ንቅ መዝገብ ንድፍ ነበር፣ እሱም ቁሶችን በተመሳሳይ መንገድ እንዲጀመሩ ያስችላቸዋል:-

>> ተጠቃሚ = Teteqami.new(sim: "Michael Hartl", emelekt: "michael@misalei.com")
=> #<Teteqami id: nil, sim: "Michael Hartl", emelekt: "michael@misalei.com",
created_at: nil, updated_at: nil>

እዚህ ጋር የስም እና የኤመልእክት ባሕሪወቹ እንደተጠበቀው እንደተዘጋጁ እናያለን።

የማረጋገጫ (Validity) ጽንሰ ሃሳብ የ‘ንቅ መዝገብ ቅርጸት ቁሶችን ለመረዳት አስፈላጊ የሆነ ነገር ነው፡፡ በክፍል 6.2 ውስጥ ይህንን ርዕሰ ጉዳይ በጥልቅ እንመለከተዋለን፤ ላሁኑ ግን ይህ የማስጀመሪያ የ‘ (ተጠቃሚ) ቁስ ብቁ መሆኑን ማረጋገጡ ጥሩ ነው፤ ይህንንም የ‘ብቁነውን? (valid?) የቡልየን ዘዴን በቁሱ ላይ በመጥራት ማረጋገጥ እንችላለን:-

>> ተጠቃሚ.valid?
true

አዲስ.ተጠቃሚ (Teteqami.new) በቀላሉ አንድ አዲስ የተጠቃሚ ቁስን በማህደረ-ትውስታ (Memory) ላይ ሲፈጥር፣ የ‘ተጠቃሚ.ብቁነውን? (ተጠቃሚ.valid?) ዘዴው ያረገው ነገር ቢኖር ደግሞ ቁሱ ብቁ መሆኑን ማረጋገጥ ብቻ ነበር፤ ስለዚህ እስካሁን ድረስ ውሂበጎታውን አልነካነውም ማለት ነው። የተጠቃሚ ቁሱን ውሂበጎታው ላይ ለማስቀመጥ፣ በ‘ተጠቃሚ (teteqami) ተለዋዋጩ ላይ የ‘አስቀምጥ (save) ዘዴን መጥራት ይኖርብናል:-

>> ተጠቃሚ.save
   (0.1ms)  SAVEPOINT active_record_1
  SQL (0.8ms)  INSERT INTO "teteqamis" ("sim", "emelekt", "created_at",
  "updated_at") VALUES (?, ?, ?, ?)  [["sim", "Michael Hartl"],
  ["emelekt", "michael@misalei.com"], ["created_at", "2019-08-22 01:51:03.453035"],
  ["updated_at", "2019-08-22 01:51:03.453035"]]
   (0.1ms)  RELEASE SAVEPOINT active_record_1
=> true

የ‘አስቀምጥ (save) ዘዴው ነገሩ ከተሳካ እውነት‘ን (true) ሲመልስ አለበለዚያ ግን ሃሰት‘ን (false) ይመልሳል፡፡ (በአሁኑ ጊዜ፣ ሁሉን ነገር ውሂበጎታው ላይ የማስፈሩ ጉዳይ ስኬታማ መሆን አለበት፤ ምክንያቱም እስካሁን ድረስ ምንም ዓይነት ማስረገጫ ስለሌለ ነው፣ አንዳንዶቹ ያለብቃት ከማረጋገጫው ሲወድቁ በክፍል 6.2 ላይ እናያለን፡፡) ለማጣቀሻ ያህል የሬይልስ ሰሌዳ እንዲሁ ከ‘ተጠቃሚ.አስቀምጥ (ተጠቃሚ.save) ዘዴ ጋር የሚዛመደውን የተ.መ.ቋ ትእዛዝን ያሳያል (ማለትም INSERT INTO "teteqamis"…)፡፡ በዚህ መጽሐፍ6 ውስጥ ጥሬ ተ.መ.ቋ በጪራሽ አያስፈልገንም፣ እኔም ከአሁን ወዲያ ስለ ተ.መ.ቋ ትእዛዞች መናገሩን ከወዲሁ አቆማለሁ፣ ነገር ግን ከ‘ንቅ መዝገብ ትእዛዞች ጋር የሚዛመደውን ተ.መ.ቋ በማንበብ ብዙ መማር እንደምትችሉ ላስገነዝባችሁ እወዳለሁ።

አዲሱ የተጠቃሚ ቁስ ለ‘መታወቂያ (id) እና ለአስማታውያኖቹ አምዶች ማለት ለ‘ተፈጠረ_በ (created_at) እና ለ‘ተዘመነ_በ (updated_at) ባሕሪወች የነበሩት ዋጋወች ምንም (nil) እንደነበሩ አስተውላችሁ ይሆናል። እስኪ የኛ የ‘አስቀምጥ (save) ዘዴ የሆነ ነገርን ለውጦ ከሆነ እንመልከት:-

>> ተጠቃሚ
=> #<User id: 1, name: "Michael Hartl", email: "michael@example.com",
created_at: "2019-08-22 01:51:03", updated_at: "2019-08-22 01:51:03">

መታወቂያ‘ው (id) አንድ የ 1 ዋጋ ሲመደብለት፣ ለአስማተኞቹ አምዶች ደግሞ የወቅቱ ቀን እና ጊዜ7 እንደተመደበላቸው እናያለን፡፡ በአሁኑ ጊዜ፣ የተፈጠሩበት እና የተዘመኑበት ማህተመጊዜወች ፍጹም አንድ ናቸው፣ ነገር ግን በክፍል 6.1.5 ውስጥ እነዚህ ማህተመጊዜወች የተለያዩ ሲሆኑ እንመለከታለን፡፡

ክፍል 4.4.5 ውስጥ የተጠቃሚ ክፍል ላይ እንደተጠቀምነው ሁሉ፣ የተጠቃሚ ቅርጸት ቅርፀቶችም የነጥብ ስርዓተ-ምልክትን በመጠቀም ባሕሪያቸው እንዲደረስ ይፈቅዳሉ:-

>> ተጠቃሚ.sim
=> "Michael Hartl"
>> ተጠቃሚ.emelekt
=> "michael@misalei.com"
>> ተጠቃሚ.updated_at
=> Fri, 06 Nov 2020 03:03:14 UTC +00:00

ምዕራፍ 7 ላይ እንደምናየው፣ ከዚህ በላይ እንዳየነው አንድ ቅርጸትን በሁለት ሂደት ውስጥ ማለት መጀመሪያ መስራት እና ከዚያ ማስቀመጡ ብዙውን ጊዜ ምቹ የሆነ የአሰራር ስልት ነው፣ ነገር ግን ንቅ መዝገብ እንዲሁም በ‘ተጠቃሚ.ፍጠር (Teteqami.create) እነዚህን ሁለት ሂደቶች ወደ አንድ ሂደት እንድታጣምሯቸው ያደርጋችኋል:-

>> Teteqami.create(sim: "አብርሃም ቹቹ", emelekt: "abrham@chuchu.org")
#<Teteqami id: 2, sim: "አብርሃም ቹቹ", emelekt: "abrham@chuchu.org", created_at:
 "2020-11-06 17:25:49", updated_at: "2020-11-06 17:25:49">
>> ሶል = Teteqami.create(sim: "ሶል", emelekt: "sole@gere.com")
#<Teteqami id: 3, sim: "ሶል", emelekt: "sole@gere.com", created_at: "2020-11-06
17:28:50", updated_at: "2020-11-06 17:28:50">

የ‘ተጠቃሚ.ፍጠር (Teteqami.create) ዘዴው እውነት (true) ወይም ሃሰትን (false) ከመመለስ ይልቅ ራሱን የተጠቃሚ ቁሱን ይመልሳል፣ ይህንንም ከአንድ ምርጫዊ ተለዋዋጪ ጋር ልንበይነው እንደምንችል ልታስተውሉ ይገባል፡፡ (ይህ ማለትም ልክ ከላይ ሁለተኛው ትእዛዝ ላይ እንዳለው ሶል እንደተባለው ተለዋዋጪ ማለት ነው)።

የ‘ፍጠር (create) ተቃራኒ አጥፋ (destroy) ነው:-

>> ሶል.destroy
   (0.1ms)  SAVEPOINT active_record_1
  SQL (0.2ms)  DELETE FROM "teteqamis" WHERE "teteqamis"."id" = ?  [["id", 3]]
   (0.1ms)  RELEASE SAVEPOINT active_record_1
=> #<Teteqami id: 3, sim: "ሶል", emelekt: "sole@gere.com", created_at:
"2020-11-06 17:28:50", updated_at: "2020-11-06 17:28:50">

ልክ እንደ ፍጠር (create) የ‘አጥፋ (destroy) ዘዴም ለተጠየቀው መጠይቅ ቁሱን በመመለስ ድርጊቱን ይፈጽማል፣ እኔ በበኩሌ የ‘አጥፋ (destroy) ምላሽን የተጠቀምኩበትን ጊዜ በፍጹም አላስታውሰውም። ከዚያ በባሰ መልኩ ደግሞ ይሄው የጠፋው ቁስ እስከ አሁን ድረስ በማህደረ-ትውስታው ውስጥ ይገኛል:-

>> ሶል
=> #<Teteqami id: 3, sim: "ሶል", emelekt: "sole@gere.com", created_at:
"2020-11-06 17:28:50", updated_at: "2020-11-06 17:28:50">

ስለዚህ አንድ ቁስን በትክክል እንዳጠፋን እንዴት እናውቃለን? የተቀመጡ እና ያልጠፉ ቁሶችን እንዴት ከውሂበጎታው ውስጥ ፈልገን ማግኘት እንችላለን? ለእነዚህ መጠይቆች መልስ ለመስጠት ንቅ መዝገብን እንዴት መጠቀም እንደምንችል መማር ይጠበቅብናል፡፡

መልመጃዎች

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

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

  1. ተጠቃሚ.ስም (ተጠቃሚ.sim) እና ተጠቃሚ.ኤመልእክት (ተጠቃሚ.emelekt) የ‘ሃረግ (String) ክፍል መሆናቸውን አረጋግጡ፡፡
  2. የ‘ተፈጠረ_በ (created_at) እና የ‘ተዘመነ_በ (updated_at) ባሕሪወች የማን ክፍል አባላቶች ናቸው?

6.1.4 የተጠቃሚ ቁሶችን መፈለግ

ንቅ መዝገብ ቁሶችን ለመፈለግ በርካታ አማራጮችን ያቀርባል፡፡ ሶል የተባለው ሶስተኛው ተጠቃሚ ከውሂበጎታው ማጥፋቱን ለማረጋገጥ እና ባለፈው ጊዜ መጀመሪያ ላይ የፈጠርነውን ተጠቃሚ ለማግኘት እንችል ዘንድ ጥቂቶቹን የ‘ንቅ መዝገብ ዘዴወች እንጠቀምባቸዋለን፡፡ በሚኖረው ተጠቃሚ እንጀምራለን:-

>> Teteqami.find(1)
=> #<Teteqami id: 1, sim: "Michael Hartl", emelekt: "michael@misalei.com",
created_at: "2020-11-06 03:03:14", updated_at: "2020-11-06 03:03:14">

እዚህ ላይ የተጠቃሚውን መታወቂያ ወደ ተጠቃሚ.ፈልግ (Teteqami.find) አሳለፍን፤ እናም ንቅ መዝገብ ተጠቃሚውን ከዚያ መታወቂያ ጋር ይመልሳል።

እስኪ በ‘መታወቂያ (id) ቁጥር 3 የሚታወቀው ተጠቃሚ እስከ አሁን ድረስ በውሂበጎታው ውስጥ መኖሩን እንይ:-

>> Teteqami.find(3)
ActiveRecord::RecordNotFound (Couldn't find Teteqami with 'id'=3)

ሶስተኛውን ተጠቃሚ በክፍል 6.1.3 ላይ ስላጠፋነው ንቅ መዝገብ በውሂበጎታው ውስጥ ሊያገኘው አልቻለም፡፡ እንዳውም የ‘ፈልግ (find) ዘዴ በምትኩ አንድ ልዩነትን (Exception) ያስነሳል፣ ይህ ማለትም በአንድ ፕሮግራም አፈጻጸም ሂደት ውስጥ በፕሮግራሙ ላይ ለየት ያለ ሁኔታ እንዳለ የሚያመላክትበት አንዱ መንገድ ሲሆን፣ በዚህ ሁኔታ ላይ፣ በ‘ንቅ መዝገብ ውስጥ የአንድ መታወቂያ አለመኖርን ነው፤ በዚህ ምክንያትም ፈልግ‘ን (find) አንድ የ‘ንቅመዝገብ::መዝገብአልተገኘም (ActiveRecord::RecordNotFound) ልዩነትን8 እንዲያስነሳ አብቅቶታል፡፡

ከአጠቃላዩ የ‘ፈልግ (find) ዘዴ በተጨማሪ፣ ንቅ መዝገብም ተጠቃሚዎችን በተወሰኑ ባሕሪወች እንድንፈልግም ያደርገናል፡-

>> Teteqami.find_by(emelekt: "michael@misalei.com")
=> #<Teteqami id: 1, sim: "Michael Hartl", emelekt: "michael@misalei.com",
created_at: "2019-08-22 01:51:03", updated_at: "2019-08-22 01:51:03">

የኤመልእክት አድራሻዎችን ልክ እንደ የተጠቃሚስሞች (Usernames) አድርገን ስለምንጠቀምባቸው፣ የዚህ ዓይነት የ‘ፈልግ (find) ዘዴ ጠቃሚ የሚሆነው ተጠቃሚዎችን እንዴት አድርገን ወደ ጣቢያችን እንደምናስገባ ስንማር ነው (ምዕራፍ 7)፡፡ በርከት ያለ ቁጥር ያላቸው ተጠቃሚዎች በውሂበጎታ ውስጥ ካሉ የ‘ፈልግ_በ (find_by) ዘዴ ውጤታማ አይሆንም የሚል ስጋት ካደረባችሁ፣ እናንተ ከጨዋታው ቀድማችሁ ሂዳችኋል ማለት ነው፤ በክፍል 6.2.5 ውስጥ፣ ይህንን ጉዳይ እና የሱን መፍትሄ በውሂበጎታ መረጃ-ጠቋሚዎች በኩል እንዴት እንደምናገኝ እንሸፍናለን።

በአጠቃላይ ተጠቃሚዎችን ለመፈለግ የሚያስችሉ አንድ ሁለት የተለያዩ መንገዶችን በመመልከት እንጨርሳለን፡፡ በመጀመሪያ ስንጀምርም አንደኛ (first) የሚባል ዘዴም አለ:-

>> Teteqami.first
=> #<Teteqami id: 1, sim: "Michael Hartl", emelekt: "michael@misalei.com",
created_at: "2019-08-22 01:51:03", updated_at: "2019-08-22 01:51:03">

አንደኛ (first) በተፈጥሮው ከውሂበጎታው ውስጥ የመጀመሪያውን ተጠቃሚ ይመልሳል። ሁሉም (all) የሚባል ዘዴም አለ:-

>> Teteqami.all
=> #<ActiveRecord::Relation [#<Teteqami id: 1, sim: "Michael Hartl", emelekt:
"michael@misalei.com", created_at: "2020-11-06 03:03:14", updated_at:
"2020-11-06 03:03:14">, #<Teteqami id: 2, sim: "አብርሃም ቹቹ", emelekt:
"abrham@chuchu.org", created_at: "2020-11-06 17:25:49", updated_at:
"2020-11-06 17:25:49">]>

ከሰሌዳው ውጽአት ላይ ማየት እንደምትችሉት፣ ሁሉም.ተጠቃሚ (Teteqami.all) በውሂበጎታው ውስጥ ያሉትን ሁሉንም ተጠቃሚዎች ልክ እንደ አንድ የ‘ንቅመዝገብ::ዝምድና (ActiveRecord::Relation) ክፍል ቁስ አድርጎ ይመልሳል፣ ይህ የተመለሰው ቁስም አንድ ድርድር ነው (ክፍል 4.3.1)፡፡

መልመጃዎች

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

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

  1. አንድ ተጠቃሚን በ‘ስም (sim) ፈልጉ። በ‘ስም_ፈልግ‘ም (find_by_sim) እንደሚሰራ አረጋግጡ፡፡ (ብዙውን ጊዜ ፈልግ_በ‘ን (find_by) ቆየት ብለው በተሰሩ የሬይልስ አፕልኬሽኖች ላይ ልታዩት ትችላላችሁ።)
  2. በአብዛኛው ተግባራዊ ስራ ላይ፣ ሁሉም.ተጠቃሚ (Teteqami.all) ልክ እንደ አንድ ድርድር ሁኖ ይሰራል፣ ይሁን እንጅ በእውነቱ የ‘ተጠቃሚ::ንቅመዝገብ_ዝምድና (Teteqami::ActiveRecord_Relation) ክፍል መሆኑን አረጋግጡ፡፡
  3. ሁሉም.ተጠቃሚ (Teteqami.all) ላይ የ‘እርዝመት (length) ዘዴን በማሳለፍ፣ የሁሉንም ተጠቃሚ እርዝመትን መፈለግ እንደምትችሉ አረጋግጡ (ክፍል 4.2.2)፡፡ ሩቢ ቁሶችን የማንቀሳቀስ ችሎታው በቁሶቹ መደበኛ የክፍል ዓይነት ላይ የተመሰረተ ሳይሆን፣ በቁሶቹ ድርጊት ላይ የተመሰረተ ስለሆነ፣ ይህ አሰራር በሩቢ ውስጥ “የዳክየ አሰራር (Duck Typing)” ተብሎ ይጠራል። “ዳክዬ ከመሰለ እና እንደ ዳክዬ “ኩኩ...” ካለ ዳክዬ መሆን አለበት” በተባለው አባባል ላይ የተመሰረተ የአሰራር ሂደት ነው፡፡

6.1.5 የተጠቃሚ ቁሶችን ማዘመን

አንዴ ቁሶችን ከፈጠርን በኋላ፣ ብዙውን ጊዜ ልናዘምናቸው እንፈልጋለን። ይህንን ለማድረግም ሁለት መሰረታዊ መንገዶች አሉ፡፡ በመጀመሪያ በክፍል 4.4.5 ላይ እንዳደረግነው፣ ባሕሪወቹን በተናጥል መመደብ እንችላለን:-

>> ተጠቃሚ           # የተጠቃሚውን ባሕሪዎች ለማስታወስ ብቻ
=> #<Teteqami id: 1, sim: "Michael Hartl", emelekt: "michael@misalei.com",
created_at: "2019-08-22 01:51:03", updated_at: "2019-08-22 01:51:03">
>> ተጠቃሚ.emelekt = "mhartl@misalei.net"
=> "mhartl@misalei.net"
>> ተጠቃሚ.save
=> true

ያደረግናቸውን ለውጦቹ በውሂበጎታው ላይ ለማስፈር የመጨረሻው ሂደት አስፈላጊ መሆኑን ልብ በሉ፡፡ በውሂበጎታው መረጃ ላይ በመመርኮዝ ቁሱን እንደገና የሚጪነውን ዳግምጫን‘ን (reload) በመጠቀም፣ የተደረገው ለውጥ ውሂበጎታው ላይ ካልተቀመጠ ምን እንደሚከሰት ማየት እንችላለን:-

>> ተጠቃሚ.emelekt
=> "mhartl@misalei.net"
>> ተጠቃሚ.emelekt = "sole@gere.com"
=> "sole@gere.com"
>> ተጠቃሚ.reload.emelekt
=>  "mhartl@misalei.net"

አሁን ተጠቃሚ.አስቀምጥ‘ን (ተጠቃሚ.save) በማስኬድ ተጠቃሚውን አዘምነናል፣ በክፍል 6.1.3 ውስጥ ቃል በተገባው መሰረትም አሁን የነዚህ አስማተኛ አምዶች ማህተመጊዜም የተለያየ ሁኗል:-

>> ተጠቃሚ.created_at
=> Thu, 22 Aug 2019 01:51:03 UTC +00:00
>> ተጠቃሚ.updated_at
=> Thu, 22 Aug 2019 01:58:08 UTC +00:00

በርካታ ባሕሪወችን ባአንዴ ለማዘመን ከተፈለገ ደግሞ፣ ሁለተኛውን ማለት አዘምን‘ን (update)9 መጠቀም ይሆናል:-

>> ተጠቃሚ.update(sim: "ሰለሞን አንበሴ", emelekt: "selemon@anbesie.org")
=> true
>> ተጠቃሚ.sim
=> "ሰለሞን አንበሴ"
>> ተጠቃሚ.emelekt
=> "selemon@anbesie.org"

የ‘አዘምን (update) ዘዴ አንድ የተርታ ባሕሪወችን ይቀበላል፣ ሁሉም ነገር ያለምንም ችግር ከተሳካ፣ ሁለቱንም ማለት ማዘመኑን እና ማስቀመጡን በአንድ ጊዜ ያከናውናል (መቀመጡ መሳካቱን ለማመልከት እውነት‘ን (true) ይመልሳል)። እዚህ ላይ ማስታዋል የሚገባን አንድ ነገር ቢኖር፣ (በክፍል 6.3 ላይ ተግባራዊ እንደሆነው) አንድ መረጃን ለማስቀመጥ አንድ መሕለፈቃል ግዴታ በሚያስፈልግበት ወቅት፣ ማናቸውም ማስረገጫዎች ካልተሳኩ አዘምን (update) ላይ የሚደረገው ጥሪ ውድቅ እንደሚሆን ነው፡፡ አንድ ነጠላ ባሕሪን ብቻ ማዘመን ከፈለግን፣ የነጠላውን ማለት የ‘ባሕሪ_አዘምን (update_attribute) ዘዴን በመጠቀም የማስረገጫዎቹን የክልከላ አጥር በመዝለል ይህንን እገዳ እንዲህ አድርገን መጣስ እንችላለን:-

>> ተጠቃሚ.update_attribute(:sim, "ነጋ ገብረስላሰ")
=> true
>> ተጠቃሚ.sim
=> "ነጋ ገብረስላሰ"

መልመጃዎች

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

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

  1. ምደባን አና አንድ የ‘አስቀምጥ (save) ጥሪን በመጠቀም የተጠቃሚውን ስም አዘምኑ።
  2. አንድ የ‘አዘምን (update) ጥሪን በመጠቀም የተጠቃሚውን የኤመልእክት አድራሻ አዘምኑ።
  3. ምደባን አና አንድ የ‘አስቀምጥ (save) ጥሪን በመጠቀም የ‘ተፈጠረ_በ (created_at) አምድን በማዘመን አስማታዊ አምዶቹን በቀጥታ መለወጥ እንደምትችሉ አረጋግጡ፡፡ ዋጋውን ከ‘1.ዓመት.በፊት (1.year.ago) ብላችሁ ተጠቀሙ፣ ይህም በሬይልስ ከአንድ ዓመት በፊት የተፈጸመ አንድ ማህተመጊዜን የመፍጠሪያ አንዱ መንገድ ነው።

6.2 የተጠቃሚ ማስረገጫወች

ክፍል 6.1 ውስጥ የፈጠርነው የተጠቃሚ ቅርጸት አሁን የሚሰራ የ‘ስም (sim) እና የ‘ኤመልእክት (emelekt) ባሕሪወች አሉት፤ ይሁን እንጅ ሁለቱም ባሕሪወች ባዶ ሃረግንም ሳይቀር ያገኙትን ሃረግ ልክ እንደ ብቁ አድርገው ያግበሰብሳሉ፤ በነሱ ቤት እነዚህ ሁኔታዎች ተቀባይነት አላቸው፡፡ ይሁን እንጂ አሁንም ቢሆን ስሞች እና የኤመልእክት አድራሻዎች ከዚህ በበለጠ የተወሰኑ መሆን አላባቸው፡፡ ለምሳሌ ስም (sim) ባዶ መሆን የለበትም፤ የ‘ኤመልእክት (emelekt) ደግሞ ከተለየ የኤመልእክት አድራሻ የቅርጸት ባህሪ ጋር መዛመድ አለበት፡፡ በተጨማሪም ተጠቃሚዎች በሚገቡበት ጊዜ የኤመልእክት አድራሻዎችን እንደ ልዩ የተጠቃሚስም ስለምንጠቀምበት፣ በውሂበጎታው ውስጥ አንድ ዓይነት የሆነ የኤመልእክት አድራሻ እንዲደጋገም መፍቀድ የለብንም፡፡

ባጪሩ ስም (sim) እና ኤመልእክት (emelekt) ልክ እንደ ማንኛውም ተራ ሃረግ እንዲሆኑ መፍቀድ የለብንም፤ በዋጋቸው ላይ የተወሰኑ ገደቦችን ማስቀመጥ ይኖርብናል። ንቅ መዝገብ ማስረገጫዎችን በመጠቀም እንደዚህ ያሉ ገደቦችን እንድናደርግ ይፈቅድልናል (ከዚህ በፊት በክፍል 2.3.2 ላይ ባጪሩ ታይቷል)። በዚህ ክፍል ውስጥ፣ ብዙውን ጊዜ ለተለመዱ ምክንያቶች ማስረገጫነት የሚያገለግሉ ዘዴወችን እንመላከታለን። ከእነዚህም መካከል መኖርን (presence)እርዝመትን (length)ቅርጸትን (format) እና ልዩነትን (uniqueness) የሚያረጋግጡ ዘዴወች ይገኙባቸዋል። በክፍል 6.3.2 መጨረሻ ላይ አንድ የተለመደ ማለት ማስረገጫ (Confirmation) የተባለ የማጽናት ማስረገጫን እንጨምር እና፣ ተጠቃሚዎች ደንቦቹን የሚጥሱ ርክቦችን ሲያቀርቡ፣ ማስረገጫዎቹ እንዴት አድርገው የሚመቹ የስህተት መልእክቶችን እንደሚሰጡን በክፍል 7.3 ላይ እናያለን፡፡

6.2.1 አንድ የማስረገጫ ፈተና

ሳጥን 3.3 ላይ እንደተጠቀሰው፣ ፈተና-መሬ ብልጸጋ ሁልጊዜ ለሁሉ ስራ ትክክለኛ መሳሪያ አይሆንም፤ ነገር ግን የቅርጸት ማረገጫዎች በትክክል የፈተና-መሬ ብልጸጋ የሚገቧቸው ዓይነት በይነገጽታዎች ናቸው፡፡ አንድ የውድቀት ፈተና ተጽፎ ከዚያም እንዲያልፍ ካልተደረገ በስተቀር፣ አንድ የተሰጠ ማስረገጫ በትክክል የሚጠበቀውን ስራ እየሰራ መሆኑን እርግጠኛ ለመሆን በጣም ከባድ ነው።

ዘዴያችን በአንድ ብቁ የቅርጸት ቁስ ይጀምራል፤ ከዚያ ከባሕሪወቹ ውስጥ አንዱን ባሕሪ እኛ ብቁ እንዳይሆን በፈለግነው ነገር እናዘጋጅዋለን፣ ከዚያም በትክክል ብቁ አለመሆኑን እንፈትነዋለን፡፡ ልክ እንደ አንድ የደህንነት መረብ ይሆነን ዘንድ፣ የማስጀመሪያ ቅርጸቱ ብቁ መሆኑን ለማረጋገጥ በመጀመሪያ አንድ ፈተና እንጽፋለን። በዚህ መንገድ የማስረገጫ ፈተናወቹ ሳያልፉ ሲቀሩ፣ መውደቃቸው በትክክለኛው ምክንያት እንደሆነ እናውቃለን ማለት ነው (እናም ምክንያቱ የማስጀመሪያ ቁሱ ከድሮው ብቁ ስላልሆነ እንዳልሆነ እናውቃለን ማለት ነው)።

በሚቀጥለው ክፍለ ጊዜ እና በአጠቃላይ ፈ.መ.ብን በምትሰሩበት ጊዜ፣ የጽሑፍ አርታኢውን ለሁለት ቦታ በመክፈል ማለት በግራ በኩል የፈተና ኮዱን፣ በቀኝ በኩል ደግሞ የአፕልኬሽኑን ኮድ አድርጎ መስራቱ በጣም አመች ይሆናል፡፡ የኔ የደመና ቅ.ማ.አ የአወቃቀር ምርጫየ በምስል 6.7 ውስጥ ይታያል፡፡

images/figures/split_pane
ምስል 6.7: ፈ.መ.ብ ከተከፈለ ውስን-ቦታ ጋር።

ዝርዝር 6.1 ውስጥ ያለው ትእዛዝ ተጠቃሚዎችን መፈተን እንድንጀምር አንድ የማስጀመሪያ ፈተናን ቢፈጥርም እንኳን፣ አሁን ባለው ሁኔታ ላይ ግን የፈጠረው ፈተና ጪራሽ ባዶ ነው (ዝርዝር 6.4)፡፡

ዝርዝር 6.4: በተግባር ባዶው ነባሪው የተጠቃሚ ፈተና። test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase
  # test "the truth" do
  #   assert true
  # end
end

አንድ የቁስ ብቃት ፈተናን ለመጻፍ፣ በመጀመሪያ ከእያንዳንዱ ፈተና በፊት በራስሰር የሚሄድ ልዩ የአዘጋጅ (setup) ዘዴን (በምዕራፍ 3 መልመጃዎች ውስጥ በደንብ ተብራርቷል) በመጠቀም፣ አንድ የማስጀመርያ ብቁ የ‘@ተጠቃሚ (@teteqami) ቅርጸት ቁስን እንፈጥራለን፣ @ተጠቃሚ (@teteqami) ቅርፀ ተለዋዋጪ ስለሆነ፣ በሁሉም ፈተናወች ውስጥ በራስሰር ይገኛል፣ እናም የ‘ብቁነውን? (valid?) ዘዴን በመጠቀም፣ ብቃቱን መፈተን እንችላለን (ክፍል 6.1.3)፡፡ ውጤቱ በዝርዝር 6.5 ውስጥ ይታያል፡፡

ዝርዝር 6.5: ለብቁ ተጠቃሚ የሚሆን አንድ የማስጀመርያ ፈተና። አረንጓዴ test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com")
  end

  test "ብቁ መሆን አለበት" do
    assert @teteqami.valid?
  end
end

ዝርዝር 6.5 የ‘አረጋግጥ (assert) ዘዴን በጥሬው ይጠቀማል፣ በዚህ ሁኔታ ላይ ተጠቃሚ.ብቁነውን? (@teteqami.valid?) ከተሳካ እውነት‘ን (true) ካልሆነ ደግሞ ሃሰት‘ን (false) ይመልሳል።

በአሁኑ ጊዜ የተጠቃሚ ቅርጸታችን ምንም ዓይነት ማስረገጫ ስለለው፣ ይህ የማስጀመሪያ ፈተና ማለፍ አለበት:-

ዝርዝር 6.6: አረንጓዴ
$ rails test:models

እዚህ ላይ የቅርጸት ፈተናወችን ብቻ ለማስኬድ ሬይልስ ቅርጸቶች:ፈትን‘ን (rails test:models) ተጠቅመናል፣ (ይህንን ክፍል 5.3.4 ላይ ካለው የውህደት ፈተናን ለማስኬድ ከተጠቀምንበት ከ‘ሬይልስ ውህደት:ፈትን (rails test:integration) ትእዛዝ ጋር አነጻጽሩ)፡፡

መልመጃዎች

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

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

  1. በሰሌዳው ውስጥ አንድ አዲስ ተጠቃሚ በአሁኑ ጊዜ ብቁ መሆኑን አረጋግጡ፡፡
  2. ክፍል 6.1.3 ውስጥ የተፈጠረው ተጠቃሚም ብቁ መሆኑን አረጋግጡ፡፡

6.2.2 መኖርን ማስረገጥ

ምናልባት ካሉት ማስረገጫወች ውስጥ ሁሉ መሰረታዊ የሆነ ማስረገጫ ቢኖር የመኖር (Presence) ማስረገጫ ነው፣ ጥቅሙም አንድ የተሰጠ ባሕሪ መኖሩን ማረጋገጥ ብቻ ነው። ለምሳሌ:- በዚህ ክፍለ ጊዜ፣ የአንድ ተጠቃሚ መረጃ ውሂበጎታው ላይ ከመቀመጡ በፊት ሁለቱም ማለት የስም እና የኤመልእክት መስኮቹ መኖራቸውን እናረጋግጣለን፡፡ በክፍል 7.3.3 ላይ አዲስ ተጠቃሚዎችን ለመፍጠር በመመዝገቢያ ቅጹ ላይ ይህንን መስፈርት እንዴት እንደምናስፋፋ እንመለከታለን፡፡

ዝርዝር 6.5 ውስጥ ያለውን አንድ ፈተና መሰረት በማድረግ፣ አንድ የ‘ስም (sim) ባሕሪ መኖሩን በመፈተን እንጀምራለን፡፡ በዝርዝር 6.7 ላይ እንደምንመለከተው፣ ማድረግ ያለብን ነገር ቢኖር @ተጠቃሚ (@teteqami) ተለዋዋጪን ከአንድ ባዶ የ‘ስም (sim) ባሕሪ ሃረግ ጋር ማዘጋጀት ነው (በዚህ ሁኔታ ላይ፣ አንድ የክፍትቦታወች ሃረግ ይሆናል) ከዚያም (የ‘አለመሆኑን_አረጋግጥ (assert_not) ዘዴን በመጠቀም) የተገኘው የተጠቃሚ ቁሱ ብቁ እንዳልሆነ እንፈትሻለን፡፡

ዝርዝር 6.7: አንድ የ‘ስም (sim) ባሕሪ ማረጋገጫ ፈተና። ቀይ test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com")
  end

  test "ብቁ መሆን አለበት" do
    assert @teteqami.valid?
  end

  test "ስም መኖር አለበት" do
    @teteqami.sim = "     "
    assert_not @teteqami.valid?
  end
end

በዚህ ጊዜ የቅርጸት ፈተናው ቀይመሆን አለበት:-

ዝርዝር 6.8: ቀይ
$ rails test:models

ከዚህ በፊት በምዕራፍ 2 መልመጃዎች ላይ ባጪሩ እንዳየነው፣ የስም ባሕሪ መኖሩን የማስረገጫው መንገድ በዝርዝር 6.9 ላይ እንደሚታየው፣ የ‘አስረግጥ (validates) ዘዴን ከመኖር፡ እውነት (presence: true) ነጋሪአሴት ጋር መጠቀም ነው፡፡ የባሕሪ መኖር ማስረገጫው ማለት የ‘መኖር፡ እውነት (presence: true) ነጋሪአሴቱ የሚወስደው አንድ የተርታ አማራጪ ብቻ ነው፤ ተርታወች የመጨረሻ ነጋሪአሴት ሁነው ወደ አንድ ዘዴ በሚያልፉበት ጊዜ፣ በክፍል 4.3.4 ላይ እንደተማርነው የሐረግ ቅንፎቻቸውን መጠቀም እና አለመጠቀም ምርጫዊ እንደሆነ ሳታስታውሱ የምትቀሩም አይመስለኝም። (በክፍል 5.1.1 ላይ እንደተመለከተው፣ በሬይልስ ውስጥ የተርታዎች አማራጮችን መጠቀሙ አንድ ተደጋጋሚ የሆነ ገጽታ ነው።)

ዝርዝር 6.9: አንድ የ‘ስም (sim) ባሕሪ መኖሩን ማረጋገጥ። አረንጓዴ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  validates :sim, presence: true
end

ዝርዝር 6.9 በአስማት የሚሰራ ይመስላል፣ ነገር ግን አስረግጥ (validates) አንድ ዘዴ ብቻ ነው፡፡ ቅንፎችን በመጠቀም በዝርዝር 6.9 ውስጥ ያለው የ‘አስረግጥ (validates) ዘዴ ምስረታ ሲጻፍ አንደሚከተለው ነው:-

class Teteqami < ApplicationRecord
  validates(:sim, presence: true)
end

በተጠቃሚ ቅርጸታችን10 ላይ አንድ ማስረገጫ በመታከሉ ምክንያት የመጣውን ውጤት ለመመልከት እስኪ ወደ ሰሌዳው ጎራ እንበል:-

$ rails console --sandbox
>> ተጠቃሚ = Teteqami.new(sim: "", emelekt: "michael@misalei.com")
>> ተጠቃሚ.valid?
=> false

እዚህ ላይ አንድ ቁስ ከአንድ ወይም ከዚያ በላይ ማስረጋገጫዎችን ሲወድቅ ሃሰት‘ን (false) እና ሁሉንም ማስረገጫዎች በሚያልፍበት ጊዜ ደግሞ ለማለፉ እውነትን (true) የሚሰጠውን የ‘ብቁነውን? (valid?) ዘዴን በመጠቀም የ‘ተጠቃሚ (teteqami) ተለዋዋጪን ፈትሸናል። በዚህ ጊዜ ያለን ማስረገጫ አንድ ብቻ ነው፤ ስለሆነም የትኛው እንዳለፈ ያለ ምንም ጥርጥር ማወቅ እንችላለን፣ ነገር ግን ስህተቶች‘ን (errors) በመጠቀም በውድቀቱ ምክንያት የመነጨውን ቁስ መመርመሩ አሁንም ቢሆን ጠቃሚ ሊሆን ይችላል:-

>> ተጠቃሚ.errors.full_messages
=> ["Sim can't be blank"]

(የስህተት መልእክቱ ሬይልስ የ‘ባዶነውን? (blank?) ዘዴን በመጠቀም አንድ ባሕሪ መኖሩን እንደሚያረጋግጥ የሚመሰክር አንድ ፍንጪ ነው፣ ይህንን ዘዴም በክፍል 4.4.3 መጨረሻ ላይ አይተነዋል፡፡)

የተጠቃሚው መስፈርት ብቁ ስላልሆነ፣ ተጠቃሚውን በውሂበጎታው ላይ ለማስቀመጥ የሚደረገው ፈተና በራስሰር ውድቅ ይሆናል:-

>> ተጠቃሚ.save
=> false

በዚህ ምክንያትም፣ በዝርዝር 6.7 ውስጥ ያለው ፈተና አሁን አረንጓዴመሆን አለበት፡-

ዝርዝር 6.10: አረንጓዴ
$ rails test:models

የአፕልኬሽኑ ኮድ ፈተናውን ለማለፍ እንዲበቃ፣ (ዝርዝር 6.11) በዝርዝር 6.7 ውስጥ ያለውን ቅድ በመከተል የ‘ኤመልእክት (emelekt) ባሕሪው መኖሩን ለማረጋገጥ አንድ ፈተና መጻፉ በጣም ቀላል ነው (ዝርዝር 6.12)

ዝርዝር 6.11: አንድ የ‘ኤመልእክት (emelekt) ባሕሪ ማረጋገጫ ፈተና። ቀይ test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com")
  end

  test "ብቁ መሆን አለበት" do
    assert @teteqami.valid?
  end

  test "ስም መኖር አለበት" do
    @teteqami.sim = "     "
    assert_not @teteqami.valid?
  end

  test "ኤመልእክት መኖር አለበት" do
    @teteqami.emelekt = "     "
    assert_not @teteqami.valid?
  end
end
ዝርዝር 6.12: አንድ የ‘ኤመልእክት (emelekt) ባሕሪ መኖሩን ማረጋገጥ። አረንጓዴ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  validates :sim, presence: true
  validates :emelekt, presence: true
end

በዚህ ጊዜ፣ የመኖር ማስረገጫዎች ተጠናቀዋል እና የፈተና ስብስቡ አረንጓዴመሆን አለበት:-

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

መልመጃዎች

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

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

  1. አንድ አዲስ ቶማስ የተባለ ተጠቃሚ ፍጠሩ እና መጀመሪያ ብቁ እንዳልሆነ አረጋግጡ፡፡ የቁሱ ሙሉ የስህተት መልእክቶች ምን ይላል?
  2. ቶማስ.ስህተቶች.መልእክቶች (ቶማስ.errors.messages) አንድ የስህተቶች ተርታ መሆኑን አረጋግጡ፡፡ በቶማስ የኤመልእክት አድራሻ ላይ ብቻ የተፈጠረውን ስህተት እንዴት መድረስ ትችላላችሁ?

6.2.3 የእርዝመት ማስረገጫ

የተጠቃሚ ቅርጸታችንን ለእያንዳንዱ ተጠቃሚ አንድ ስም እንደሚያስፈልገው ገድበነው ነበር፣ ነገር ግን ከዚያ ገደብ ባሻገር መሄድ አለብን፤ በጣቢያችን ላይ የተጠቃሚው ስም ስለሚታይ፣ የስሙ እርዝመት ላይ የተወሰነ ገደብን ማስቀመጥ ይኖርብናል፡፡ ይህ ሂደት በክፍል 6.2.2 ውስጥ ካደረግነው ሂደት ሁሉ የቀለለ ሂደት ነው፡፡

አንድ ከፍተኛ እርዝመትን ለመምረጥ የሚረዳ ሳይንስ የለም፤ ስለዚህ ያገራችን ደብር ያውቃል ብለን 50 ቁጥርን እንመርጥ እና እሱኑ ልክ እንደ አንድ ከፍተኛ ወሰን አድርገን እንወስደዋለን፣ ይህ ማለት የሚቀርበው ስም ሆሄው 51 እና ከዚያ በላይ ከሆነ ስሙ በጣም ረዥም መሆኑን ያረጋግጥልናል ማለት ነው። በተጨማሪም፣ ምንም እንኳን ይህ ችግር፣ ችግር የማያመጣ ቢመስልም፣ የአንድ ተጠቃሚ የኤመልእክት አድራሻ እርዝመት ከአብዛኞቹ ውሂበጎታወች ከፍተኛ የሆሄ ቁጥር ማለት ከ 255 በላይ ሊያልፍ የሚችልበት አጋጣሚ ግን ሊኖር ይችላል። በክፍል 6.2.4 ውስጥ ያለው የቅርጸት ማስረገጫ እንደዚህ ዓይነት ገደብን ስለማይፈጽም፣ በዚህ ክፍል ውስጥ ሁሉ ስራችን የተሟላ ይሆን ዘንድ አንድ ገደብ እናክልበታለን፡፡ ዝርዝር 6.14 የተገኙትን የፈተና ውጤቶች ያሳያል፡፡

ዝርዝር 6.14: የ‘ስም (sim) እና የ‘ኤመልእክት (emelekt) እርዝመትን ማስረገጫ ፈተናዎች። ቀይ test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com")
  end
  .
  .
  .
  test "ስም ረጅም መሆን የለበትም" do
    @teteqami.sim = "ኤ" * 51
    assert_not @teteqami.valid?
  end

  test "ኤመልእክት ረጅም መሆን የለበትም" do
    @teteqami.emelekt = "ኤ" * 244 + "@example.com"
    assert_not @teteqami.valid?
  end
end

ለምቾት ሲባል፣ አንድ የ 51 ሃረግ ሆሄዎች እርዝመትን ለመስራት በዝርዝር 6.14 ላይ “የሃረግ ማባዛትን” ተጠቅመናል። ሰሌዳውን በመጠቀም እንዴት እንደሚሰራ ማየት እንችላለን:-

>> "ኤ" * 51
=> "ኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤ"
>> ("ኤ" * 51).length
=> 51

የኤመልእክት እርዝመት ማስረገጫው ከሚገባው በላይ አንድ ሆሄን በመጨመር ተቀባይነት ያለውን አንድ የኤመልእክት አድራሻ ያዘጋጃል (እዚህ ላይ የመጨረሻው የኤመልእክት አድራሻ የሆሄ እርዝመት 255 መሆን ስላለበት፣ የኤመልእክት አድራሻው የሆሄው እርዝመት 256 ከሆነ ተቀባይነት የለውም ማለት ነው):-

>> "ኤ" * 244 + "@misalei.com"
=> "ኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤ
ኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤ
ኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤ
ኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤ
ኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤኤ@misalei.com"
>> ("ኤ" * 244 + "@misalei.com").length
=> 256

በዚህ ጊዜ በዝርዝር 6.14 ውስጥ ያሉ ፈተናወች ቀይመሆን አለባቸው፡-

ዝርዝር 6.15: ቀይ
$ rails test

እነሱ እንዲያልፉ ለማድረግ፣ እርዝመቱን ለመገደብ የሚጠቅም የማስረገጫ ነጋሪአሴትን መጠቀም ይኖርብናል፤ ይህም በቀላሉ እርዝመት‘ን (length)፣ የከፍተኛውን እርዝመት ወሰን ለመገደብ ከ‘ከፍተኛ (maximum) ሰሚአሴት ጋር መጠቀም ነው (ዝርዝር 6.16)።

ዝርዝር 6.16: ለ‘ስም (sim) እና ለ‘ኤመልእክት (emelekt) ባሕሪዎች የእርዝመት ማስረገጫዎችን ማከል። አረንጓዴ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  validates :sim, presence: true, length: { maximum: 50 }
  validates :emelekt, presence: true, length: { maximum: 255 }
end

አሁን ፈተናወቹ አረንጓዴመሆን አለባቸው:-

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

የፈተና ስብስባችን በድጋሜ ስላለፈ፣ ወደ ከባዱ የኤመልእክት ቅርጸት ማስረገጫ መሄድ እንችላለን።

መልመጃዎች

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

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

  1. ከተወሰነው ሆሄ በላይ የስም እና የኤመልእክት አድራሻ ያለው አንድ አዲስ ተጠቃሚ ፍጠሩ እና ከዚያ ተጠቃሚው ብቁ አለመሆኑን አረጋግጡ፡፡
  2. በእርዝመት ማረጋገጫው የመነጩት የስህተት መልዕክቶች ምንድን ናቸው?

6.2.4 የቅርጸት ማስረገጫ

የ‘ስም (sim) ባሕሪ ማስረገጫችን አነስተኛ ገደቦችን ብቻ ያስገድዳሉ (ከ 51 ሆሄዎች በታች የሆነ ማንኛውም ባዶ ያልሆነ ስምን ሳይቀር ተቀባይ ያደርገዋል) ግን በእርግጥ የ‘ኤመልእክት (emelekt) ባሕሪው አንድ የኤመልእክት አድራሻ ብቁ ለመሆኑ በጣም ጥብቅ የሆነ መስፈርትን ማሟላት አለበት፡፡ እስካሁን ድረስ ባዶ የሆኑ የኤመልእክት አድራሻዎችን ብቻ ነጽገናል፣ በዚህ ክፍል ውስጥ፣ የኤመልእክት አድራሻውን የተለመደውን የ teteqami@misalie.com ዓይነት ስርዓተ ይዘት እንዲያሟላ እንጠይቃለን።

ፈተናወቹም ሆኑ ማስረገጫው ሙሉ በሙሉ ሁሉንም ነገር የሚያሟሉ አይደሉም፣ በጣም ብቁ የሆኑትን የኤመልእክት አድራሻዎችን ለመቀበል እና ብቁ ያልሆኑትን ላለመቀበል ብቻ ግን በቂ ናቸው፡፡ ብቁ እና ብቁ ያልሆኑ የኤመልእክት አድራሻ ስብስቦችን በሚያሳትፉ ሁለት ፈተናወች እንጀምራለን። እነዚህን ስብስቦች ለማዘጋጀት፣ በዚህ የሰሌዳ ክፍለ ጊዜ ውስጥ እንደሚታየው፣ የሃረጎችን ድርድር ለመስራት ስለሚያስችለው ጠቃሚ %w[] ዘዴ ማወቁ ጠቃሚ ነው:-

>> %w[asny bekele kebede]
=> ["asny", "bekele", "kebede"]
>> adrashawech = %w[TETEQAMI@asny.COM YE_TE-TEQAMI@asny.bekele.org
mejemeriya.mecheresha@asny.jp]
=> ["TETEQAMI@asny.COM", "YE_TE-TEQAMI@asny.bekele.org", "mejemeriya.mecheresha@asny.jp"]
>> adrashawech.each do |adrasha|
?>   puts adrasha
>> end
TETEQAMI@asny.COM
YE_TE-TEQAMI@asny.bekele.org
mejemeriya.mecheresha@asny.jp

እዚህ ላይ የ‘እያንዳንዳቸው (each) ዘዴን (ክፍል 4.3.2) በመጠቀም በእያንዳንዱ የ‘አድራሻወች (adrashawech) ድርድር አባል ላይ በመደጋገም እንዴት የያንዳንዱን አባል ዋጋ ማግኘት እንደምንችል እንመለከታለን። ይህንን ብልሃት ሰንቀን አሁን አንዳንድ መሰረታዊ የኤመልእክት ቅርጸት ማስረገጫ ፈተናወችን ለመጻፍ ዝግጁውች እንሆናለን፡፡

የኤመልእክት ቅርጸት ማስረገጫ አታላይ እና ለስህተት የሚያጋልጥ ስለሆነ፣ በማስረገጫው ውስጥ ያሉ ማናቸውንም ስህተቶች ለመያዝ ፈተናወቹን ለማለፍ ብቁ የሚሆኑ የኤመልእክት አድራሻ ፈተናወችን በመፈተን እንጀምራለን፡፡ በሌላ አነጋገር የማረጋገጫ ገደቡን ካስቀመጥን በኋላም ቢሆን፣ ልክ እንደ teteqami@misalei,com ያሉ ብቁ ያልሆኑ የኤመልእክት አድራሻዎች ውድቅ ማድረጉን ብቻ ሳይሆን፣ ብቁ የሆኑ ማለት እንደ teteqami@misalei.com ያሉ ብቁ አድራሻዎችን ደግሞ ተቀባይነት እንዳላቸው ማረጋገጥ እንፈልጋለን (በአሁኑ ጊዜ ሁሉም ባዶ ያልሆኑ የኤመልእክት አድራሻዎች ብቁ ስለሆኑ ተቀባይነት አላቸው)። ብቁ የኤመልእክት አድራሻዎችን የሚወክሉ ናሙናወች በዝርዝር 6.18 ውስጥ ይገኛል፡፡

ዝርዝር 6.18: ለብቁ የኤመልእክት ቅርጽት የሚሆኑ ፈተናወች። አረንጓዴ test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com")
  end
  .
  .
  .
  test "የኤመልእክት ማስረገጫ ብቁ አድራሻዎችን መቀበል አለበት" do
    biku_adrashawech = %w[teteqami@misalie.com TETEQAMI@asny.COM
                          YE_TE-TEQAMI@asny.bekele.org
                          mejemeriya.mecheresha@asny.jp alice+bob@baz.cn]
    biku_adrashawech.each do |biku_adrasha|
      @teteqami.emelekt = biku_adrasha
      assert @teteqami.valid?, "#{biku_adrashawech.inspect} ብቁ መሆን አለበት"
    end
  end
end

ከአንድ ብጁ የስህተት መልእክት ጋር፣ አንድ ሁለተኛ አማራጫዊ ነጋሪአሴትን ማካተታችንን ልብ በሉ፣ ይህ መልእክት እዚህ ላይ ፈተናው እንዳይሳካ የሚያደርገውን የኤመልእክት አድራሻ ይለየዋል፡-

assert @teteqami.valid?, "#{valid_address.inspect} ብቁ መሆን አለበት"

(ይህ በክፍል 4.3.3 ውስጥ የተገለጸውን፣ ውስጠገምት የተደረገውን የ‘መርምር (inspect) ዘዴን ይጠቀማል።) ዝርዝር 6.18 ‘ን በመሰለ አሰራር ላይ፣ ማለት አንድ ፈተናን ከ‘እያንዳንዳቸው (each) ምልልስ ጋር በመጠቀም ወቅት፣ ውድቀት የሚያስከትለውን ልዩ አድራሻ በምልልሱ ውስጥ ማካተቱ እጅግ ጠቃሚ ሲሆን፣ ያለበለዚያ ግን ማናቸውም ውድቀቶች ለሁሉም የኤመልእክት አድራሻዎች አንድ ዓይነት የሆነውን እና የችግሩ መንስኤን ለመለየት የሚያበቃውን የመስመር ቁጥርን ለይቶ ማወቅ ብቻ ይሆናል።

ቀጥሎም እንደ teteqami@misalie፣com (በነጥብ ምትክ ነጠላ ሰረዝ ሲሆን) እና teteqami_at_desta.org (የአት ‘@’ ምልክቱ አለመኖር) ላሉት ብቁ ላልሆኑ እና እንዲሁም ለተለያዩ ብቁ ላልሆኑ የኤመልእክት አድራሻወች ብቁ ያለመሆን ፈተናወችን እናክላለን፡፡ ዝርዝር 6.19 ልክ እንደ ዝርዝር 6.18 ውድቀት የሚያስከትለውን አድራሻ በትክክል ለመለየት አንድ የተበጀ የስህተት መልእክትን ያካትታል፡፡

ዝርዝር 6.19: የኤመልእክት ቅርጸት ማስረገጫ ፈተናወች። ቀይ test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com")
  end
  .
  .
  .
  test "የኤመልእክት ማስረገጫ ብቁ ያልሆኑ አድራሻዎችን መንጸግ አለበት" do
    biku_yalhonu_adrashawech = %w[teteqami@misalie,com
                               teteqami_at_seny.org teteqami.sim@misalie.
                                mola@dereje_tesfaye.com belay@wesen+daniel.com]
    biku_yalhonu_adrashawech.each do |biku_yalhone_adrasha|
      @teteqami.emelekt = biku_yalhone_adrasha
      assert_not @teteqami.valid?, "#{biku_yalhone_adrasha.inspect} ብቁ መሆን አለበት"
    end
  end
end

በዚህ ጊዜ ፈተናው ቀይመሆን አለበት፡-

ዝርዝር 6.20: ቀይ
$ rails test

የአፕልኬሽኑ ኮድ ለኤመልእክት የቅርፀት ማስረገጫ የ‘ቅርፀት (format) ማስረገጫን ይጠቀማል፣ ይህም በዚህ መልኩ ይሰራል:-

validates :emelekt, format: { with: /<መደበኛ ሂሳበሃረግ>/ }

ይህ ከተሰጠው መደበኛ ሂሳበሃረግ (Regular Expression) (ወይም ሬጀክስ (regex)) ጋር ባሕሪውን ያስረግጣል፣ ይህም በሃረጎች ውስጥ ጥለቶችን ለማዛመድ የሚያገለግል ሃይለኛ (እና ብዙውን ጊዜ እንቆቅልሽ) የሆነ ቋንቋ ነው። ይህ ማለትም ብቁ ያልሆኑትን የኤመልእክት አድራሻዎች ሳናዛምድ፣ ብቁዎቹን የኤመልእክት አድራሻዎች ብቻ ለማዛመድ አንድ መደበኛ ሂሳበሃረግን መስራት አለብን ማለት ነው።

እርግጥ ነው በተገቢው የኤመልእክት መስፈርት መሰረት፣ አንድ ሙሉ ለሙሉ የኤመልእክት አድራሻዎችን ለማዛመድ የሚችል መደበኛ ሂሳበሃረግ አለ፣ ነገር ግን እጅግ ሰፊ፣ ግልጽ ያልሆነ እና ምናልባትም ውጤታማ11 ላይሆን የሚችል ነው፡፡ ግባችን ከተለመዱት መካከል ጥቂቶቹን ብቻ እንጅ፣ ሁሉንም የኤመልእክት አድራሻ የቅርጸት ስህተቶችን ፈልጎ ለማግኘት አይሆንም። ስለዚህ በተግባሩ ጠንካራ መሆኑን የሚያረጋግጥ እና በሁኔታው ላይ በበለጠ የሚሰራ አንድ መደበኛ ሂሳበሃረግን እንገነባለን። እሱም ይህንን ይመስላል፡-

BQUYE_EMELEKT_MEDEBGNA_HISABEHEREG = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

ይህ ከየት እንደመጣ ለመረዳት እንችል ዘንድ፣ ሰንጠረዥ 6.1 በደንብ ከፋፍሎ አቅርቦታል።12

ሂሳበሃረግ ትርጉም
/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i የተሟላው መደበኛ ሂሳበሃረግ
/ የመደበኛ ሂሳበሃረጉ መጀመሪያ
\A በመጀመሪያ ላይ የሚገኝ ሃረግን ያዛምዳል
[\w+\-.]+ ቢያንስ ቢያንስ አንድ የፊደል ሆሄ፣ የመደመር ምልክት፣ የሰረዝ ምልክት ወይም ነጥብ መኖር ይገባዋል
@ አንድ የቃልበቃል “የአት ምልክት” መኖር ይገባዋል
[a-z\d\-.]+ ቢያንስ ቢያንስ አንድ ፊደል፣ የሰረዝ ምልክት፣ ቁጥር ወይም ነጥብ መኖር ይገባዋል
\. አንድ የቃልበቃል የነጥብ ምልክት መኖር ይገባዋል
[a-z]+ ቢያንስ ቢያንስ አንድ ፊደል መኖር ይገባዋል
\z መጨረሻ ላይ የሚገኝ አንድ ሃረግን ያዛምዳል
/ የመደበኛ ሂሳበሃረጉ መጨረሻ
i ለመልከፊደል-ግድየለሽ (የትንሽ እና የዓቢ የእንግሊዝኛ ፊደላትን መርሃባ ብሎ የሚቀበል)
ሰንጠረዥ 6.1: ብቁውን የኤመልእክት መደበኛ ሂሳበሃረግ መከፋፈል።

ሰንጠረዥ 6.1 ‘ን በማጥናት ብዙ ልትማሩ ብትችሉም፣ መደበኛ ሂሳበሃረግን በትክክል ለመረዳት አንድ እንደ ሩቡላር ያለ የመደበኛ ሂሳበሃረግ በይነተገናኝ አዛማጅን መጠቀሙን ግን ልክ እንደ አንድ አስፈላጊ ነገር አድርጌ እቆጥረዋለሁ (ምስል 6.8)፡፡13 የሩቡላር የድርጣቢያ መደበኛ ሂሳበሃረግን ለማዘጋጀት አንድ የሚያምር የበይነተገናኝ ገጽታን፣ ከአንድ ምቹ ቀልጣፋ ማጣቀሻ ጋር ያካተተ ነው፡፡ ሰንጠረዥ 6.1 ‘ን አንድ ለሩቡላር አሳሽ በተከፈተ መስኮት ላይ እንድታጠኑት አሳስባችኋለሁ፣ ይሄ ነው ከተባለ በላይ ስለ መደበኛ ሂሳበሃረግ ማንበቡ፣ እነሱን በበይነተገናኝ አካል ላይ የመሞከርን ያህል ሊተካ አይችልም፡፡ (ማሳሰቢያ:- በሩቡላር ውስጥ በሰንጠረዥ 6.1 ያለውን መደበኛ ሂሳበሃረግ የምትጠቀሙ ከሆነ፣ በአንድ የተሰጠ የፈተና ሃረግ ውስጥ በአንድ ጊዜ ከአንድ በላይ የኤመልእክት አድራሻን ማዛመድ ትችሉ ዘንድ፣ የ \A እና \z ሆሄወችን አውጥታችሁ እንድትማሩ ከወዲሁ እመክራለሁ፡፡ በተጨማሪም መደበኛ ሂሳበሃረጉ አነዚህን /.../ ሆሄወች በውስጡ ያካተተ መሆኑን ልብ በሉ፤ ስለዚህ ሩቡላርን በምትጠቀሙበት ጊዜ እነሱን ማስወገድ እንደሚኖርባችሁ አስተውሉ።)

images/figures/rubular
ምስል 6.8: የሚያምር ገጽታ ያለው የሩቡላር መደበኛ ሂሳበሃረግ አርታኢ።

ለ‘ኤመልእክት (emelekt) ቅርጸት ማረጋገጫ ከሰንጠረዥ 6.1 መደበኛ ሂሳበሃረጉን ተግባር ላይ ማዋሉ በዝርዝር 6.21 ውስጥ ያለውን ኮድ ይሰጣል።

ዝርዝር 6.21: የኤመልእክት ቅርጸትን በአንድ መደበኛ ሂሳበሃረግ ማስረገጥ። አረንጓዴ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  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 }
end

እዚህ ላይ የመደበኛ ሂሳበሃረጉ ማለት ብቁ_የኤመልእክት_መደበኛ_ሂሳበሃረግ (BIKU_YE_EMELEKT_MEDEBEGNA_HISABEHEREG) አንድ ቋሚ ተላዋዋጪ ነው፤ ይህም በዓብይ ፊደል የሚጀምር አንድ ስም በሩቢ ውስጥ አንድ ቋሚ ተላዋዋጪ እንደሆነ ያመለክታል፡፡ ኮዱ ከ:-

 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 }

ጥለት ጋር የሚዛመዱትን የኤመልእክት አድራሻዎች ብቻ ብቁ እንደሆኑ አድርጎ ይቆጥራል። (ከዚህ በላይ ያለው ሂሳበሃረግ አንድ አነስተኛ ድክመት አለው፣ እንደ abrham@chuchu..com ያለ ተከታታይ ነጥቦች የያዘ ብቁ ያልሆነ አድራሻን ያስተናግዳል፡፡ ይህንን ጉድለት ለማስተካከል በዝርዝር 6.21 ውስጥ ያለውን መደበኛ ሂሳበሃረግን የማዘመኑ ጉዳይ፣ ልክ እንደ አንድ መልመጃ ይሆን ዘንድ ለናንተ ተትቷል (ክፍል 6.2.4.1))፡፡

በዚህ ጊዜ ፈተናው አረንጓዴመሆን አለበት፡-

ዝርዝር 6.22: አረንጓዴ
$ rails test:models

ይህ ማለትም አንድ ገደብ ብቻ ይቀራል ማለት ነው፤ እሱም የኤመልእክት ልዩነትን ማስገደድ ይሆናል፡፡

መልመጃዎች

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

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

  1. ዝርዝር 6.18 ተቀባይነት ያላቸውን የኤመልእክት አድራሻዎች፣ እና ከዝርዝር 6.19 ደግሞ ተቀባይነት የለላቸውን የኤመልእክት አድራሻዎች በሩብላር የሆሄ መፈተኛ ቦታ ውስጥ በማስገባት፣ የዝርዝር 6.21 መደበኛ ሂሳበሃረግ ሁሉንም የኤመልእክት አድራሻወች እንደሚያዛምድ አረጋግጡ፡፡
  2. ከዚህ በላይ እንደተጠቀሰው፣ በዝርዝር 6.21 ላይ ያለው መደበኛ ሂሳበሃረግ ይህንን የመሰለ abrham@chuchu..com ማለት በግዝአቱ ላይ ተከታታይ ነጥብ ያለው፣ ተቀባይነት የለለውን የኤመልእክት አድራሻን ይፈቅዳል። አንድ የሚወድቅ ፈተናን ታገኙ ዘንድ፣ ይህንን የኤመልእክት አድራሻ በዝርዝር 6.19 ውስጥ ከሚገኙት ብቁ ያልሆኑ አድራሻወች ላይ አክሉት፣ ከዚያ በኋላ በዝርዝር 6.23 ላይ ያለውን በጣም የተወሳሰበውን መደበኛ ሂሳበሃረግ በመጠቀም ፈተናው እንደሚያልፍ አድርጉ፡፡
  3. abrham@chuchu..com የሚለውን የኤመልእክት አድራሻ በሉብላር ላይ በማከል፣ እና በዝርዝር 6.23 ውስጥ የተመለከተው፣ መደበኛ ሂሳበሃረግ ሁሉንም ብቁ አድራሻዎች እንጂ ማንኛውንም ብቁ ያልሆነ አድራሻን የማያዛምድ መሆኑን አረጋግጡ።
ዝርዝር 6.23: በኤመልእክት የግዝአት ስሞች ውስጥ ጥንድ ነጥቦችን አለመፍቀድ። አረንጓዴ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  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 }
end

6.2.5 የልዩነት ማስረገጫ

የኤመልእክት አድራሻዎች ልዩነትን ለማስገደድ (እናም ልክ እንደ የተጠቃሚስሞች አድርገን ልንጠቀምባቸው እንችል ዘንድ) የ‘፡ልዩነት (:uniqueness) አማራጪን በ‘አስረግጥ (validates) ዘዴ ላይ እንጠቀማለን፡፡ እዚህ ላይ ግን አንድ የሚያስፈልግ ልዩ መስፈርት ስላለ ይህንን ክፍል ሳትዘሉ በጥንቃቄ እንድታነቡት አስጠነቅቃችኋለሁ።

በአንዳንድ አጪር ፈተናወች እንጀምራለን፡፡ ባለፈው የቅርጸት ፈተናችን ውስጥ አብዛኛውን ጊዜ አዲስ.ተጠቃሚ‘ን (Teteqami.new) ተጠቅመን ነበረ፣ ይህም በማህደረ-ትውስታ ውስጥ አንድ የሩቢ ቁስን ይፈጥራል፣ የልዪነት ፈተኖችን ለመፈተን ግን መዝገቡን በውሂበጎታ14 ውስጥ ማስቀመጥ ይኖርብናል። የመጀመሪያው የተደጋገመ የኤመልእክት ፈተና በዝርዝር 6.24 ውስጥ ይታያል (እዚህ ላይ፣ የተደጋገመ ማለት በሁለመናው ጪራሽ አንድ የሆነ ማለት ነው)፡፡

ዝርዝር 6.24: የተደጋገሙ የኤመልእክት አድራሻዎችን ለመንጸግ አንድ ፈተናን ማከል። ቀይ test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com")
  end
  .
  .
  .
  test "የኤመልእክት አድራሻዎች ልዩ መሆን አለባቸው" do
    yetedegageme_teteqami = @teteqami.dup
    @teteqami.save
    assert_not yetedegageme_teteqami.valid?
  end
end

እዚህ ላይ ያለው ዘዴ @ተጠቃሚ.ተደጋጋሚ‘ን (@teteqami.dup) በመጠቀም ከ‘@ተጠቃሚ (@teteqami) ጋር አንድ አይነት የኤመልእክት አድራሻ ያለው አንድ ተጠቃሚን መስራት ነው፣ ይህም አንድ የተደጋገመ ተጠቃሚን ከአንድ አይነት ባሕሪዎች ጋር ይፈጥራል። ከዚያ @ተጠቃሚን (@teteqami) በውሂበጎታ ውስጥ የምናስቀምጥ ስለሆነ፣ የተደጋገመው ተጠቃሚ ቀድሞውኑ በውሂበጎታው ውስጥ የተፈጠረ አንድ የኤመልእክት አድራሻ ይኖረዋል፣ ስለሆነም የኤመልእክት አድራሻው ብቁ መሆን አይገባውም።

ዝርዝር 6.24 ላይ እንደሚታየው፣ ልዩነት፡ እውነት (uniqueness: true) ዘዴን የ‘ኤመልእክት (emelekt) ማስረገጫ ላይ በማከል በዝርዝር 6.25 ውስጥ ያለውን አዲሱን ፈተና ማሳለፍ እንችላለን፡፡

ዝርዝር 6.25: የኤመልእክት አድራሻወች ልዩነትን ማስረገጥ። አረንጓዴ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  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
end

ይህም ሆኖ ግን እስከአሁን አልጨረስንም፡፡ የኤመልእክት አድራሻዎች በመደበኛነት ለመልከፊደል-ግድየለሽ (Case Insensitive) እንደሆኑ ተደርገው ይካሄዳሉ፤ ማለትም eden@nega.com ከ‘ EDEN@NEGA.COM ወይም ከ‘ EdEN@NEga.coM ጋር አንድ ዓይነት እንደሆነ ተደርጎ ይስተናገዳል፤ ስለዚህ ማረጋገጫችን ይህንንም በግምት ውስጥ ማስገባት ይኖርበታል ማለት ነው፡፡15 እናም የመልከፊደል-ግድየለሽነትን መፈተኑ አስፈላጊ ስለሆነ፣ ፈተናውን የምናካሂደው በዝርዝር 6.26 ላይ ባለው ኮድ ይሆናል፡፡

ዝርዝር 6.26: የኤመልእክት መልከፊደል-ግድየለሽ ልዩነትን መፈተን። ቀይ test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com")
  end
  .
  .
  .
  test "የኤመልእክት አድራሻዎች ልዩ መሆን አለባቸው" do
    yetedegageme_teteqami = @teteqami.dup
    yetedegageme_teteqami.emelekt = @teteqami.emelekt.upcase
    @teteqami.save
    assert_not yetedegageme_teteqami.valid?
  end
end

እዚህ ላይ፣ በሃረጎች ላይ አንድ የ‘ዓቢ-ፊደል (upcase) ዘዴን እየተጠቀምን ነው (በክፍል 4.3.2 ውስጥ ባጪሩ ተገልጿል)፡፡ ይህ ፈተና ከመጀመሪያው የተደጋገመ የኤመልእክት አድራሻ ፈተና ጋር ተመሳሳይ ፈተናን ቢያደርግም፣ እዚህ ፈተና ላይ ግን በአብይ ፊደላት የተጻፉ የኤመልእክት አድራሻዎችን ብቻ ይፈትናል። ይህ ፈተና ትንሽ ጠጠር ያለ ሆኖ ካገኛችሁት ወደ ሰሌዳችሁ ጎራ በሉ:-

$ rails console --sandbox
>> ተጠቃሚ = Teteqami.create(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com")
>> ተጠቃሚ.emelekt.upcase
=> "TETEQAMI@MISALEI.COM"
>> yetedegageme_teteqami = ተጠቃሚ.dup
>> yetedegageme_teteqami.emelekt = ተጠቃሚ.emelekt.upcase
>> yetedegageme_teteqami.valid?
=> true

በእርግጥ የ‘ተደጋገመ_ተጠቃሚ.ብቁነውን? (yetedegageme_teteqami.valid?) የልዩነት ማስረገጫ መልከፊደል-ግድየለሽ ስለሆነ፣ በአሁኑ ጊዜ የሚሰጠን መልስ እውነት (true) ይሆናል፣ ነገር ግን እኛ ሃሰት (false) እንዲሆን እንፈልጋለን። እንደ እድል ሆኖ ፡ልዩነት (:uniqueness) ለዚህ ስራ ሲባል አንድ የ‘መልከፊደል-ግድየለሽ (:case_sensitive) ምርጫን ይቀበላል (ዝርዝር 6.27)፡፡

ዝርዝር 6.27: መልከፊደል-ግድየለሽነትን በመንጸግ የኤመልእክት አድራሻውች ልዩነትን ማረጋገጥ። አረንጓዴ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  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: { case_sensitive: false }
end

ዝርዝር 6.25 ውስጥ ያለውን እውነት (true) ዝርዝር 6.27 ውስጥ በ‘መልከፊደል-ግድየለሽ: ሃሰት (case_sensitive: false) እንደተካነው አስተውሉ፡፡ (ሬይልስም ፡ልዩነት (:uniqueness) እውነት (true) እንደሆነ ከሁኔታው ይረዳል፡፡)

በዚህ ጊዜ አፕልኬሽናችን (ከአንድ ጠቃሚ ማስጠንቀቂያ ጋር) የኤመልእክት ልዩነትን ያስፈጽማል እናም የፈተና ስብስባችን ማለፍ አለበት:-

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

እዚህ ጋር አንድ ትንሽ ችግር አለ፤ ይህም የንቅ መዝገብ ልዩነት ማስረገጫ በውሂበጎታው ውስጥ ያለው ውሂብ ልዩ ለመሆኑ አንዳችም ዋስትና አይሰጥም። ምክንያቱን የሚያብራራ አንድ አጋጣሚ እነሆ:-

  1. ተወልደ tewelde@tekie.com አድራሻን ተጠቅሞ በማሳያ አፕልኬሽኑ ላይ በመመዝገብ ላይ ነው፡፡
  2. አጅሬው በድንገት “ለኔ መለያ ፍጠር” አዝራር ላይ ሁለት ጊዜ ጠቅ አደረገ፣ ይህም ሁለት ቀልጣፋ መጠይቅን በተከታታይ መላክ ማለት ነው፡፡
  3. እዚህ ላይ የሚከተለው ቅደም ተከተል ይከሰታል፡- 1 - የመጀመሪያው የምዝገባ መጠይቅ ማስረገጫውን ያለፈ አንድ ተጠቃሚን በማህደረ-ትውስታ ውስጥ ይፈጥራል፤ 2 - የሁለተኛው የምዝገባ መጠይቅም እንደ መጀመሪያው አንድ ዓይነት የሆነ ተግባር ይፈጽማል፤ የመጀመሪያው የምዝገባ መጠይቅ ውሂበጎታው ላይ ሰፈረ/ተቀመጠ የሁለተኛውም የምዝገባ መጠይቅ ውሂበጎታው ላይ ሰፈረ/ተቀመጠ።
  4. ውጤት:- ምንም እንኳ የልዩነት ማስረገጫ ቢኖረንም፣ ጪራሽ ተመሳሳይ የሆኑ የኤመልእክት አድራሻ ያላቸው ሁለት የተጠቃሚ መዝገቦች ግን በውሂበጎታው ውስጥ ይገኛሉ ማለት ነው፡፡

ከላይ ያለው ቅደም ተከተል የማያጋጥም ይመልሳል አይደል? እመኑኝ ያጋጥማል፤ በጣም ብዙ ተገልጋይ ባላቸው በማንኛውም የሬይልስ ድረጣቢያ ላይ ሊከሰት ይችላል (ይሄንን እኔ በአንድ ወቅት ትልቅ አበሳ ከፍየ ነበር የተማርኩት)፡፡ እንደ አጋጣሚ ሆኖ ግን መፍትሄውን ተግበር ላይ ማዋሉ በጣም ቀላል ነው፣ ይህም በውሂበጎታው እና በቅርጸቱ ላይ ልዩነትን ማስገደድ ብቻ ይኖርብናል፣ ዘዴያችንም በኤመልእክት አምድ (ሳጥን 6.2) ላይ አንድ የውሂበጎታ መረጃ-ጠቋሚን (Index) መፍጠር እና ከዚያ መረጃ-ጠቋሚው ልዩ እንዲሆን ማድረግ ይሆናል፡፡

ሳጥን 6.2. የውሂበጎታ መረጃ-ጠቋሚወች

በአንድ ውሂበጎታ ውስጥ አንድ አምድን በምንፈጥርበት ጊዜ፣ በዚያ አምድ መሰረት መዝገቦችን እንፈልግ እንደሆነ ማጤኑ አስፈላጊ ነው። ለምሳሌ;- በዝርዝር 6.2 ውስጥ በፍልሰት የተፈጠረውን የኤመልእክት ባሕሪ ተመልከቱ፡፡ ከምዕራፍ 7 ጀምሮ ተጠቃሚዎች ወደ ማሳያ አፕልኬሽኑ እንዲገቡ ስንፈቅድ ከተረከበው የኤመልእክት አድራሻ ጋር የሚዛመደውን የተጠቃሚ መዝገብ መፈለግ ይኖርብናል፡፡ አለመታደል ሆኖ በገራገሩ የውሂብ ቅርጸት ላይ በመመርኮዝ፣ አንድ ተጠቃሚን በኤመልእክት አድራሻ ለመፈለግ ብቸኛው መንገድ በውሂበጎታው ውስጥ ያሉትን እያንዳንዱን የተጠቃሚ ረድፍ በመመልከት የኤመልእክት ባሕሪውን ከተሰጠው የኤመልእክት አድራሻ ጋር ማነጻጸር ነው። ይህ ማለት እያንዳንዱን ረድፍ አንድ ባንድ መመርመር አለብን ማለት ነው (ምክንያቱም ተጠቃሚው በውሂበጎታው ውስጥ የመጨረሻው ምዝግብ ሊሆን ይችላል)። ይህ በውሂበጎታ ዓለም ውስጥ የሙሉ-ሰንጠረዥ ቅኝት (Full-table Scan) በመባል ይታወቃል፣ እና ይህም በሽዎች የሚቆጠሩ ተጠቃሚዎች ላሉት አንድ ጣቢያ አንድ መጥፎ ነገር ይሆናል፡፡

በኤመልእክት አምድ ላይ አንድ የመረጃ-ጠቋሚን ማድረጉ ችግሩን ያስወግዳል፡፡ የአንድ ውሂበጎታ መረጃ-ጠቋሚን ለመረዳት፣ እሱን ከአንድ የመጽሐፍ ማውጫ ጋር አነጻጽሮ ማየቱ ጠቃሚ ነው፡፡ እንበል በአንድ መጽሐፍ ውስጥ አንድ “ተዋበች” የሚል ሆሄን ትፈልጋላችሁ እንበል። የዚህን ሆሄ ክስተቶች ለማግኘት፣ መጽሐፉ ውስጥ ያሉትን ግጾች በሙሉ አንድ ባንድ መቃኘት ይኖርባችኋል ማለት ነው፤ ይህም የወረቀት የሙሉ-ሰንጠረዥ ቅኝትን አደረጋችሁ እንደማለት ነው፡፡ በሌላ በኩል በመጽሐፉ ውስጥ “ተዋበች” የሚለውን ሆሄ የያዙ ሁሉንም ገጾች ለመመልከት፣ በመጽሐፉ ማውጫ ላይ “ተዋበች” ን በቀላሉ መፈለግ ትችላላችሁ፡፡ አንድ የውሂበጎታ መረጃ-ጠቋሚም በመሰረቱ በተመሳሳይ መንገድ ይሰራል፡፡

የኤመልእክት መረጃ-ጠቋሚው ለውሂብ መቀረጪያ መስፈርታችን አንድ አዲስ ጪማሬ ነው፣ ይህም በሬይልስ ውስጥ ፍልሰቶችን በመጠቀም ይስተናገዳል (በክፍል 6.1.1 ላይ እንደተገለጸው)፡፡ በክፍል 6.1.1 ላይ፣ የተጠቃሚ ቅርጸቱ አንድ አዲስ ፍልሰትን በራስሰር እንደፈጠረ ተመልክተናል (ዝርዝር 6.2)፡፡ አሁን ባለው ሁኔታ ላይ ግን ካሁን በፊት በነበረ አንድ ቅርጸት ላይ መዋቅርን እያከልን ስለሆነ፣ የ‘ፍልሰት (migration) አመንጪን በመጠቀም አንድ ፍልሰትን በቀጥታ መፍጠር ይኖርብናል:-

$ rails generate migration mereja_tequami_mechemer_to_teteqamis_emelekt

የኤመልእክት ልዩነት ፍልሰቱ ልክ እንደ ተጠቃሚዎች ፍልሰት ቀድሞ የተበየነ ስላልሆነ፣ ይዘቱን ከዝርዝር 6.29 ቀድተን መገልበጥ ይኖርብናል፡፡16

ዝርዝር 6.29: የኤመልእክት ልዩነት ማስገደጃን ማፍለስ፡፡ db/migrate/[ማህተመጊዜ]_mereja_teequami_mechemer_to_teteqamis_emelekt.rb
class MerejaTequamiMechemerToTeteqamisEmelekt < ActiveRecord::Migration[6.0]
  def change
    add_index :teteqamis, :emelekt, unique: true
  end
end

ይህ በ‘ተጠቃሚዎች (teteqamis) ሰንጠረዥ የ‘ኤመልእክት (emelekt) አምድ ላይ አንድ መረጃ-ጠቋሚ ለማከል፣ አንድ መረጃ-ጠቋሚ_አክል (add_index) የተባለ የሬይልስ ዘዴን ይጠቀማል፡፡ መረጃ-ጠቋሚው በራሱ ልዩነትን አያስገድድም፣ ልዩነት: እውነት (unique: true) የተባለው አማራጪ ግን ልዩነትን ያስገድዳል።

የመጨረሻው ሂደት ውሂበጎታውን ማፍለስ ነው:-

$ rails db:migrate

(እዚህ ላይ ፍልሰቱ ካልተሳካ፣ ከማንኛውም የሚሄድ የአሸዋሳጥን ሰሌዳ ክፍለ ጊዜ መውጣታችሁን አረጋግጡ፣ የአሸዋሳጥን ሰሌዳው ውሂበጎታውን ሊዘጋ እና ፍልሰቶችን ሊከላከል ይችላል።)

በዚህ ጊዜ እቃዎች (fixtures) በተባለው ፋይል ውስጥ ያለው አንድ የልዩነት ገደብ በመጣሱ ምክንያት የፈተና ስብስቡ ቀይ መሆን አለበት፣ የእቃዎች (fixtures) ፋይሉ ለፈተና ውሂበጎታው የሚያገለግሉ የናሙና ውሂቦችን ይይዛል። የተጠቃሚ እቃዎች በዝርዝር 6.1 ውስጥ በራስሰር የመነጨ ሲሆን፣ በዝርዝር 6.30 ላይ እንደሚታየው የኤመልእክት አድራሻዎቹ ልዩ አይደሉም፡፡ (ብቁወችም አይደሉም፣ ግን’ኮ የእቃዎች ውሂብ በማስረገጫዎች ውስጥ ፈጽሞ አያልፍም።)

ዝርዝር 6.30: ነባሪዎቹ የተጠቃሚ እቃዎች። ቀይ test/fixtures/teteqami.yml
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/
# FixtureSet.html

one:
  sim: MyString
  emelekt: MyString

two:
  sim: MyString
  emelekt: MyString

እስከ ምዕራፍ 8 ድረስ እቃዎች ስለማያስፈልጉን፣ ለአሁኑ እነሱን አስወግደን ፊክስቸርስ የተባለውን ፋይል ባዶውን እንተወዋለን (ዝርዝር 6.31)።

ዝርዝር 6.31: አንድ ባዶ የፊክስቸሮች ፋይል። አረንጓዴ test/fixtures/users.yml
# ባዶ

እያንዳንዱ የኤመልእክት አድራሻ ልዩ ለመሆኑ የሚያስፈልገውን መስፈርት ካሟላን በኋላም፣ በኤመልእክት ልዩነት ላይ እርግጠኛ ለመሆን አሁንም አንድ ማድረግ ያለብን ተጨማሪ ለውጥ አለ፡፡ አንዳንድ የውሂበጎታ አያያዥ ፕሮግራሞች፣ መልከፊደል-ግድየለሽ መረጃ-ጠቋሚዎችን ይጠቀማሉ። በዚህ ምክንያትም፣ “Girmeso@MiSALie.CoM” የሚለው የኤመልእክት አድራሻን፣ እና “girmeso@misalie.com” የሚለው የኤመልእክት አድራሻን፣ ልክ እንደ ሁለት የተለያየ የኤመልእክት አድራሻ አድርገው ያስተናግዱታል። የኛ አፕልኬሽን ግን እነዚህን አድራሻወች ልክ እንደ አንድ አድራሻ አድርጎ ያስተናግዳቸዋል። እናም ይህንን አለመጣጣም ለማስወገድ፣ ማንኛውንም የኤመልእክት አድራሻ ውሂበጎታው ላይ ከማስቀመጣችን በፊት የኤመልእክት አድራሻውን ከ:- “Girmeso@MiSALie.CoM” ወደ:- “girmeso@misalie.com” በመለወጥ ሁሉንም አድራሻዎች የንዑስ-ፊደል አድራሻ መስፈርት እንዲኖራቸው እናደርጋለን፡፡ ይህንን የምናደርግበት መንገድም መልሰጥሪ (Callback) ይባላል፣ ይህም በንቅ መዝገብ ቁስ ክፍለ ጊዜ በአንድ የተለየ ሁኔታ ላይ የሚጠራ ዘዴ ነው፡፡

አሁን ባለው ሁኔታ ላይ፣ ያ የተለየ ሁኔታ ቁሱ ከመቀመጡ በፊት ስለሆነ፣ ተጠቃሚውን ወደ ውሂበጎታ ላይ ከማስቀመጣችን በፊት የኤመልእክት ባሕሪውን ወደ ንዑስ-ፊደላት ለመቀየር የ‘ከማስቀመጥ_በፊት (before_save) መልስጥሪን መጠቀም ይሆናል።17 ውጤቱም በዝርዝር 6.32 ውስጥ ይታያል፡፡ (እዚህ ላይ የመጀመሪያውን ትግበራ ለመተግበር የ‘ከማስቀመጥ_በፊት (before_save) መልስጥሪን ተጠቅመናል፣ በክፍል 11.1 ላይ መልሰጥሪን ለመበየን የተመረጠውን ዘዴ አጣቅሴ (Method Reference) ተብሎ የሚጠራውን የተለመደ ዘዴ በምንጠቀምበት ወቅት ይህንን ጉዳይ በድጋሜ እንወያይበታለን።)

ዝርዝር 6.32: የኤመልእክት ባሕሪውን ወደ ንዑስ-ፊደል በመለወጥ የኤመልእክት ልዩነትን ማረጋገጥ። ቀይ app/models/teteqami.rb
class Teteqami < ApplicationRecord
  before_save { self.emelekt = emelekt.downcase }
  validates :sim,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :emelekt, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
end

ዝርዝር 6.32 ውስጥ ያለው ኮድ አንድ ጥምርን ወደ ከማስቀመጥ_በፊት (before_save) መልሰጥሪ ያሳልፍ እና የተጠቃሚውን የኤመልእክት አድራሻ፣ የሃረግ ንዑስ-ፊደል (downcase) ዘዴን በመጠቀም፣ አንድ ወቅታዊ የንዑስ-ፊደላት ስሪት ዋጋን ያዘጋጃል፡፡

ሁሉም የኤመልእክቶች መልከፊደል-ግድየለሽ ከሆኑ ከንዑስ-ፊደላት ጋር በሚዛመድ መልኩ በጥሩ ሁኔታ ስለሚሰራ ዝርዝር 6.32 የ‘ልዩነት (uniqueness) ገደብን ወደ እውነት (true) እንደሚመልሰው ልታስተውሉ ይገባል፡፡ ብዙ የውሂበጎታወች አንድ መረጃ-ጠቋሚን ተጠቅሞ ከአንድ መልከፊደል-ግድየለሽ ተዛማጅ ጋር ለማጣመር አስቸጋሪ ስለሚሆንባቸው፣ ይህ አሰራር በእርግጥ፣ የዝርዝር 6.29 የውሂበጎታ መረጃ-ጠቋሚን ከመተግበር ጋር የተያያዙ ችግሮችን ይከላከላል፡፡18

የመጀመሪያ ገደቡን ወደ ነበረበት መመለስ፣ በዝርዝር 6.26 ውስጥ ያለውን ፈተና ይሰብረዋል፣ ካሁን በፊት የነበረውን የዝርዝር 6.24 ፈተና ኮድን መልሶ በመጠቀም ግን ፈተናው በቀላሉ እንዲያልፍ ማድረግ ይቻላል፣ እናም ይህ የፈተና ኮድ በድጋሜ፣ በዝርዝር 6.33 ላይ ተጽፎ ቀርቧል፡፡

ዝርዝር 6.33: የመጀመሪያውን የኤመልእክት ልዩነት ፈተና ወደነበረበት መመለስ። አረንጓዴ test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com")
  end
  .
  .
  .
  test "የኤመልእክት አድራሻዎች ልዩ መሆን አለባቸው" do
    yetedegageme_teteqami = @teteqami.dup
    @teteqami.save
    assert_not yetedegageme_teteqami.valid?
  end
end

በነገራችን ላይ፣ በዝርዝር 6.32 ውስጥ ያለውን ምደባ እንደዚህ አድርገን መጻፍ እንችል ነበር:-

self.emelekt = self.emelekt.downcase

(ራሥ (self) የአሁኑ ተጠቃሚን በሚያመለክትበት ጊዜ) በተጠቃሚ ቅርጸቱ ውስጥ የራሥ (self) ቁልፍቃሉ ከይሆናል ምልክቱ በስቀኝ በኩል ከሆነ ግን እሱን መጠቀሙ እና አለመጠቀሙ ምርጫዊ ይሆናል:-

self.emelekt = emelekt.downcase

በ‘ አንሶላ ዘዴ (ክፍል 4.4.2) ውስጥ በ‘አገላብጥ (reverse) አውድ ውስጥ ይህንን ሃሳብ በግልጽ ተመልክተናል፤ ማለት ራሥ (self) አንድ ተለዋዋጪን በመመደብ ወቅት አማራጫዊ እንዳልሆነም አስተውለናል፣ ስለዚህ:-

emelekt = emelekt.downcase

አይሰራም፡፡ (ይህንን ጉዳይ በክፍል 9.1 ውስጥ በሰፊው እንወያይበታለን፡፡)

በዚህ ጊዜ፣ ከዚህ በፊት በተወልደ ላይ የተከሰተው አጋጣሚ በተገቢው ሁኔታ እንደሚሰራ እንመልከት:- በመጀመሪያው የምዝገባ መጠይቅ መሰረት፣ የውሂበጎታው የተጠቃሚውን መዝገብ ያስቀምጥ እና የሁለተኛው መጠይቅ የተደጋገመ የኤመልእክት አድራሻ ልዩነት ገደብን ስለሚጥስ፣ የውሂበጎታው የተጠቃሚውን መዝገብ እንዳይቀመጥ ውድቅ ያደርገዋል፡፡ (በዚህ ሁኔታ ላይ አንድ ስህተት በሬይልስ ዘገባ ውስጥ ሊታይ ይችላል፣ ነገር ግን ያ ምንም ዓይነት ጉዳት አያደርስም፡፡) በተጨማሪም፣ ይህንን የመረጃ-ጠቋሚ በኤመልእክት ባሕሪ ውስጥ ማከሉ፣ በክፍል 6.1.4 ውስጥ በግልጽ እንደተጠቀሰው አንድ ሁለተኛ ግብን ያከናውናል፤ በሳጥን 6.2 ላይ እንደተጠቀሰው፣ በ‘ኤመልእክት (emelekt) ባሕሪ ላይ ያለው የመረጃ-ጠቋሚ፣ ተጠቃሚዎችን በኤመልእክት አድራሻ ሲፈልጉ፣ የሙሉ-ሰንጠረዥ ቅኝትን በመከላከል፣ የመቀልጠፍ አቅም ችግርን ያስተካክላል፡፡

መልመጃዎች

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

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

  1. በዝርዝ 6.34 ላይ የተሰጠውን የፈተና ኮድ በመጠቀም፣ በዝርዝር 6.32 ላይ የኤመልእክት አድራሻወች ሁሉ ውሂበጎታ ውስጥ ከመቀመጣቸው በፊት ወደ ንዑስ-ፊደል መለወጣቸውን የሚያረጋግጥ አንድ ፈተና አክሉ፡፡ ይህ ፈተና፣ አንድ ዋጋን ከውሂበጎታው እንደገና ለመጫን የ‘ዳግምጫን (reload) ዘዴን እና እኩልነትን ለመፈተሽ ደግሞ የ‘እኩልነት_አረጋግጥ (assert_equal) ዘዴን ይጠቀማል። ዝርዝር 6.34 ላይ ያለው ፈተና፣ ትክክለኛውን ነገር መፈተኑን ለማረጋገጥ፣ የ‘ከማስቀመጥ_በፊት (before_save) መልሰጥሪ ላይ አስተያየት በማድረግ ፈተናው ቀይመሆኑን አረጋግጡ፣ ከዚያ አስተያየቱን በማስወገድ ፈተናው ወደነበረበት አረንጓዴመመለሱን ደግማችሁ አረጋግጡ፡፡
  2. ዝርዝር 6.35 ላይ እንደሚታየው፣ የ‘ኤመልእክት (emelekt) ባሕሪውን በቀጥታ ለማሻሻል፣ የ “አናጋ” ዘዴን emelekt.downcase! በመጠቀም መጻፍ መቻሉን የፈተና ስብስቡን በማስኬድ አረጋግጡ።
ዝርዝር 6.34: ዝርዝር 6.32 ኤመልእክትን ወደ ንዑስ-ፊደል የመለውጥ ፈተና። test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com")
  end
  .
  .
  .
  test "የኤመልእክት አድራሻዎች ልዩ መሆን አለባቸው" do
    yetedegageme_teteqami = @teteqami.dup
    @teteqami.save
    assert_not yetedegageme_teteqami.valid?
  end

  test "የኤመልእክት አድራሻዎች በንዑስ-ፊደል መቀመጥ አለባቸው" do
    deblaqa_melkefidel_emelekt = "Beyene@MiSALie.CoM"
    @teteqami.emelekt = deblaqa_melkefidel_emelekt
    @teteqami.save
    assert_equal deblaqa_melkefidel_emelekt.downcase, @teteqami.reload.emelekt
  end
end
ዝርዝር 6.35: አንድ የመልሰጥሪ ተለዋጪ አተገባበር። አረንጓዴ 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
end

6.3 አንድ ጥብቅ መሕለፈቃልን ማከል።

ለስም እና ለኤመልእክት መስኮች ማስረገጫዎችን ስለበየንን፣ አሁን ከተጠቃሚ ባሕሪወች፣ የመጨረሻና መሰረታዊ የሆነውን፣ አንድ ጥብቅ የመሕለፈቃል አምድን ለማከል ዝግጁ ነን፡፡ ዘዴው እያንዳንዱ ተጠቃሚ አንድ መሕለፈቃል እና አንድ የመሕለፈቃል ማረጋገጫ እንዲኖረው ይጠይቃል፣ ከዚያም የተከተፈውን (hashed) መሕለፈቃል ውሂበጎታው ውስጥ ያስቀምጣል። (እዚህ ላይ አንድ ግራ የሚያጋባ ነገር ሊኖር ይችላል፡፡ በአሁኑ ዓውድ ውስጥ hashክፍል 4.3.3 የሚገኘውን የሩቢ ፕሮግራም የውሂብ መዋቅር የሚያጣቅስ ሳይሆን፣ በተሰጠው ውሂብ ላይ ፈጽሞ ወደ ነበረበት ሊመለስ የማይችል አንድ የመክተፍ ሥልት (hash function) ውጤትን ነው፡፡) እንዲሁም፣ በአንድ የተሰጠ መሕለፈቃል ላይ በመመርኮዝ አንድ ተጠቃሚን ለማረጋግጥ የሚያስችል አንድ መንገድን እናክላለን፣ ይህንንም በምዕራፍ 8 ላይ ተጠቃሚዎችን ወደ ጣቢያው መግባት እንዲፈቅድላቸው የምንጠቀምበት ዘዴ ይሆናል፡፡

ተጠቃሚዎችን የማረጋገጫ ዘዴው፣ አንድ ርክብ መሕለፈቃልን መውሰድ፣ ከዚያ እሱኑ መክተፍ፣ እና ውጤቱን ውሂበጎታ ውስጥ ካለው ክትፍ ዋጋ ጋር ማነጻጸር እና ሁለቱ ክትፎች ከተዛመዱ፣ የተረከበው መሕለፈቃል ትክክል እና ተጠቃሚው ደግሞ የተረጋገጠ ይሆናል። ከጥሬ መሕለፈቃሎች ይልቅ፣ የተከተፈ ዋጋቸውን በማነጻጸር፣ መሕለፈቃሎቹን ውሂበጎታው ላይ ሳናስቀምጥ ተጠቃሚዎችን ማረጋገጥ እንችላለን፡፡ ይህ ማለት አጋጣሚ ሁኖ የውሂበጎታችን ቢጠለፍ እንኳ፣ የተጠቃሚዎቻችን መሕለፈቃሎች አሁንም ቢሆን ጥብቆች ናቸው ማለት ነው።

6.3.1 አንድ የተከተፈ መሕለፈቃል

በጣም ጥብቁ የመሕለፈቃል ፋብሪካው የሚተገበረው ጥብቅ_መሕለፈቃል_አለው (has_secure_password) ተብሎ የሚጠራውን አንድ ነጠላ የሬይልስ ዘዴን በመጠቀም ነው፣ ይህንንም እንደሚከተለው አድርገን በተጠቃሚ ቅርጸቱ ውስጥ ማካተት እንችላለን:-

class Teteqami < ApplicationRecord
  .
  .
  .
  has_secure_password
end

ከላይ እንደሚታየው ዘዴውን በአንድ ቅርጸት ውስጥ በምናካትትበት ጊዜ፣ ይህ ዘዴ የሚከተሉትን ተግባራት ያክላል፡-

  • በውሂበጎታው መሕለፈቃል_ፈጪ (password_digest) ባሕሪ ላይ አንድ በጥብቅ የተከተፈ ውጤትን የማስቀመጥ ችሎታን፣
  • አንድ ጥንድ ምናባዊ ባሕሪወችን19 (የ‘መሕለፈቃል password እና የመሕለፈቃል ማረጋገጫ password_confirmation)፣ ቁሱ በሚፈጠርበት ጊዜ የመሕለፈቃል እና የመሕለፈቃል ማረጋገጫ መኖርን ማረጋገጥ እና፣ መሕለፈቃሉና የመሕለፈቃል ማረጋገጫው መዛመዱን ማስረገጥን፣
  • መሕለፈቃሉ ትክክል ከሆነ የተጠቃሚ ቁሱን፣ ትክክል ካልሆነ ደግሞ ሃሰትን (false) የሚመልስ አንድ የ‘አረጋግጥ (authenticate) ዘዴን ያክላል።

ጥብቅ_መሕለፈቃል_አለው (has_secure_password) አስማቱን እንዲሰራ ለማድረግ ብቸኛው መስፈርት፣ ተዛማጅ ቅርጸቱ አንድ መሕለፈቃል_ፈጪ (password_digest) የተባለ ባሕሪ እንዲኖረው ማድረግ ብቻ ነው። (ፍጪ (Digest) የሚለው ስም ከስነ መሰውራዊ መክተፍ ተግባሮች የመጣ የስያሜ ቃል ነው። በዚህ አውድ ውስጥ የተከተፈ መሕለፈቃል እና ፍጪ መሕለፈቃል ሁለቱንም አንድ ዓይነት አባባሎች ናቸው፡፡)20

የተጠቃሚ ቅርጸቱን በርተመለከተ፣ በምስል 6.9 ላይ የሚታየውን የውሂብ ንድፍ መተግበርን ይጠይቃል፡፡

user_model_password_digest_3rd_edition
ምስል 6.9: የተጠቃሚ የውሂብ ቅርጸቱ ከአንድ የታከለ የ‘መሕለፈቃል_ፈጪ (password_digest) ባሕሪ ጋር።

ምስል 6.9 ላይ የተመለከተውን፣ የውሂብ ቅርጸት ለመተግበር በመጀመሪያ ለ‘መሕለፈቃል_ፈጪ (password_digest) አምድ አንድ ተገቢ ፍልሰትን እናመነጫለን፡፡ በዚህ ሁኔታ ላይ ሬይልስ የ‘ተጠቃሚዎች teteqamis ሰንጠረዥ ላይ ዓምዶችን ለማከል አንድ ፍልሰትን በራስሰር እንዲገነባ፣ የፍልሰት ስሙን በ‘ለ_ተጠቃሚዎች (to_teteqamis) መጨረሱ አመች ይሆናል፣ ነገር ግን የፈለግነውን ማንኛውንም የፍልሰት ስም መምረጥ እንችላለን። ውጤቱ ለተጠቃሚወች_መሕለፈቃል_ፈጪ_አክል (mehlefekal_fech_akl_to_teteqamis) ከሚለው የፍልሰት ስሙ ጋር እንደሚከተለው ይታያል፡-

$ rails generate migration mehlefekal_fech_akl_to_teteqamis password_digest:string

እዚህ ጋር ደግሞ መፍጠር የምንፈልገውን የስም እና የባሕሪውን ዓይነት ከ‘መሕለፈቃል_ፈጪ:ሃረግ (password_digest:string) ነጋሪአሴት ጋር አቅርበናል፡፡ (ይህንን በዝርዝር 6.1 ውስጥ መጀመሪያ ከመነጨው እና የ‘ስም:ሃረግ (sim:string) እና የ‘ኤመልእክት:ሃረግ (emelekt:string) ነጋሪአሴቶችን ካካተተው የተጠቃሚዎች (teteqamis) ሰንጠረዥ ጋር አነጻጽሩ፡፡) በዝርዝር 6.36 ውስጥ እንደሚታየው፣ መሕለፈቃል_ፈጪ:ሃረግ‘ን (password_digest:string) በማካተት፣ ሬይልስ ሙሉውን ፍልሰት እንዲገነባልን በቂ መረጃ ሰጥተነዋል።

ዝርዝር 6.36: አንድ የ‘መሕለፈቃል_ፈጪ (password_digest) አምድን የሚያክል ፍልሰት። db/migrate/[ማህተመጊዜ]_mehlefekal_fech_akl_to_teteqamis.rb
class MehlefekalFechAklToTeteqamis < ActiveRecord::Migration[6.0]
  def change
    add_column :teteqamis, :password_digest, :string
  end
end

ዝርዝር 6.36 አንድ የ‘መሕለፈቃል_ፈጪ (password_digest)አምድን ወደ ተጠቃሚዎች (teteqamis) ሰንጠረዥ ለማከል የ‘አምድ_አክል (add_column) ዘዴን ይጠቀማል፡፡ ይህንን አምድ ውሂበጎታው ላይ ለመፍጠር፣ በቃ ውሂበጎታውን እንደሚከተው አድርገን እናፈልሳለን:-

$ rails db:migrate

ፍጪ መሕለፈቃሉን ለመስራት ጥብቅ_መሕለፈቃል_አለው (has_secure_password) ቢክሪፕት የተባለ አንድ ዘመናዊ የመክተፍ ሥልትን ይጠቀማል። መሕለፈቃሉን በቢክሪፕት በመክተፍ፣ አንድ አጥቂ አንድ የውሂበጎታ ቅጂን ማግኘት ቢችልም እንኳ፣ ወደ ጣቢያው ለመግባት እንደማይችል ግን እናረጋግጣለን። ማሳያ አፕልኬሽኑ ውስጥ ቢክሪፕትን ለመጠቀም፣ የቢክሪፕት (bcrypt) እንቁን በ‘እንቁፋይል (Gemfile) ውስጥ ማከል ይኖርብናል (ዝርዝር 6.37))።

ዝርዝር 6.37: የቢክሪፕት (bcrypt) እንቁን በ‘እንቁፋይል (Gemfile) ውስጥ ማከል።
source 'https://rubygems.org'

gem 'rails',          '6.1.4.1'
gem 'bcrypt',         '3.1.13'
gem 'bootstrap-sass', '3.4.1'
.
.
.

ከዚያ እንደተለመደው ጠቅል-ጫን‘ን (bundle install) አስኪዱ:-

$ bundle _2.2.17_ install

6.3.2 ተጠቃሚ ጥብቅ መሕለፈቃል አለው

አሁን የተጠቃሚ ቅርጸቱን በተፈለገው የ‘መሕለፈቃል_ፈጪ (password_digest) ባሕሪ እና በተፈለገው የቢክሪፕት እንቁ ስለተጫነ፣ በዝርዝር 6.38 ላይ እንደሚታየው፣ ለተጠቃሚ ቅርጸቱ ጥብቅ_መሕለፈቃል_አለው‘ን (has_secure_password) ለማከል ዝግጁ ነን፡፡

ዝርዝር 6.38: በተጠቃሚ ቅርጸቱ ውስጥ ጥብቅ_መሕለፈቃል_አለው‘ን (has_secure_password) ማከል። ቀይ 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
end

ዝርዝር 6.38 ውስጥ በ ቀይ አመልካች እንደተመለከተው፣ እና በማዘዥያ መስመሩ ላይ ማረጋገጥ እንደምትችሉት አሁን ፈተናወቹ ወድቀዋል:-

ዝርዝር 6.39: ቀይ
$ rails test

ይህ የሆነበት ምክንያት፣ በክፍል 6.3.1 ውስጥ እንደተገለጸው ጥብቅ_መሕለፈቃል_አለው (has_secure_password) በ‘መሕለፈቃል (password) እና በመሕለፈቃል ማረጋገጫ (password_confirmation) ምናባዊ ባሕሪወች ላይ ማስረገጫዎችን ስለሚያስገድድ ሲሆን፤ በአንጻሩ ግን ዝርዝር 6.26 ውስጥ ያሉ ፈተናወች አንድ የ‘@ተጠቃሚ (@teteqami) ተለዋዋጪን ያለ እነዚህ ባሕሪወች ስለሚፈጥሩ ነው፡-

def setup
  @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com")
end

ስለሆነም የፈተና ስብስቡ በድጋሚ እንዲያልፍ ለማድረግ፣ በዝርዝር 6.40 ውስጥ እንደሚታየው፣ አንድ የመሕለፈቃልን እና የሱን ማረጋገጫ ማከል ይኖርብናል።

ዝርዝር 6.40: አንድ መሕለፈቃልን እና የሱን ማረጋገጫ ማከል። አረንጓዴ test/models/teteqami_test.rb
require 'test_helper'

class TeteqamiTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com",
                     password: "yonatan", password_confirmation: "yonatan")
  end
  .
  .
  .
end

በሩቢ ተርታ አገባብ መሰረት የ‘አዘጋጅ (setup) ዘዴው ውስጥ ያለው የመጀመሪያው መስመር መጨረሻው ላይ አንድ ተጨማሪ ነጠላ ሰረዝ እንደሚያስፈልገው ልትገነዘቡ ይገባል (ክፍል 4.3.3)፡፡ ይህን ነጠላ ሰረዝ መተው፣ አንድ የአገባብ ስህተት እንዲፈጠር ያደርጋል፣ እንደዚህ አይነት ነገሮች በሚሲከሰቱ ጊዜ ስህተቶቹን ለመለየት እና ለመፍታት የራሳችሁን ቴክኒካዊ ስልት (ሳጥን 1.2) መጠቀም ይኖርባችኋል።

በዚህ ጊዜ ፈተናወቹ አረንጓዴመሆን አለባቸው፡-

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

ጥብቅ_መሕለፈቃል_አለው‘ን (has_secure_password) በተጠቃሚ ቅርጸቱ (ክፍል 6.3.4) ውስጥ የማከል ጥቅሞችን በአጪር ጊዜ ውስጥ እናያለን፣ በመጀመሪያ ግን በመሕለፈቃል ጥበቃ ላይ አንድ አነስተኛ መስፈርትን እንጨምራለን።

መልመጃዎች

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

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

  1. ምንም እንኳ አንድ ተጠቃሚ ብቁ ስም እና የኤመልእክት አድራሻ ቢኖረውም፣ የተጠቃሚው መዝገብ በውሂበጎታው ላይ ግን ፈጽሞ እንደማይቀመጥ አረጋግጡ፡፡
  2. መሕለፈቃል ለሌለው አንድ ተጠቃሚ ሬይልስ የሚሰጣቸው የስህተት መልእክቶች ምን እና ምን ናቸው?

6.3.3 የመሕለፈቃል እርዝመት መስፈርቶች

በአጠቃላይ መሕለፈቃሎች ለመገመት አስቸጋሪ እንዲሆኑ፣ የመሕለፈቃል ሆሄወች ላይ፣ የአነስተኛ እርዝመት መስፈርትን ማድረጉ ጥሩ ልምድ ነው፡፡ በሬይልስ ውስጥ የመሕለፈቃል ማጠንከሪያን ለማስገደድ ብዙ አማራጮች አሉ፤ ነገር ግን ስራው እንዲቀልልን ቢያንስ አንድ አነስተኛ እርዝመትን እና አንድ የመሕለፈቃል ባሕሪው ባዶ መሆን እንደማይገባው የሚያስገድድ ማለት ሁለት መስፈርቶችን እናደርጋለን፡፡ ስድስትን (6) ልክ እንደ አንድ ምክንያታዊ አነስተኛ እርዝመት አድርጎ መምረጡ፣ በዝርዝር 6.42 ላይ የሚታየውን የማስረገጫ ፈተና ይሰጣል፡፡

ዝርዝር 6.42: አንድ የመሕለፈቃል አነስተኛ እርዝመት ፈተና። ቀይ test/models/teteqami_test.rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase

  def setup
    @teteqami = Teteqami.new(sim: "Abnetawi Teteqami", emelekt: "teteqami@misalei.com",
                     password: "yonatan", password_confirmation: "yonatan")
  end
  .
  .
  .
  test "መሕለፈቃል መኖር አለበት (ባዶ ያልሆነ)" do
    @teteqami.password = @teteqami.password_confirmation = " " * 6
    assert_not @teteqami.valid?
  end

  test "መሕለፈቃል አነስተኛ እርዝመት ሊኖረው ይገባል" do
    @teteqami.password = @teteqami.password_confirmation = "ኤ" * 5
    assert_not @teteqami.valid?
  end
end

ዝርዝር 6.42 ላይ የተጠቀጠቀ በርካታ ምደባን መጠቀማችንን ልብ በሉ:-

@teteqami.password = @teteqami.password_confirmation = "ኤ" * 5

ይህ ለመሕለፈቃሉ እና ለማረጋገጫው አንድ የተወሰነ ዋጋን ለመመደብ ያዘጋጃል (በዚህ ጊዜ፣ አንድ እርዝመቱ 5 የሆነ ሃረግን ይገነባል፣ ሃረጉም ልክ በዝርዝር 6.14 ላይ እንደተደረገው፣ ሃረግ ማባዛትን በመጠቀም የተገነባ ነው።)

ተዛማጁን የተጠቃሚ ስም ከፍተኛ (maximum) እርዝመት ማስገደጃውን በማየት፣ ለአንድ አነስተኛ (minimum) እርዝመት ገደብ የሚጥለውን ኮድ፣ ለመገመት ትችሉ ይሆናል (ዝርዝር 6.16):-

validates :password, length: { minimum: 6 }

ይህንን የባዶ ያልሆኑ መሕለፈቃሎች ማስረገጫ፣ ከአንድ የ‘ኖረ ( presence) ማስረገጫ (ክፍል 6.2.2) ጋር ማጣመሩ በዝርዝር 6.43 ውስጥ ወደሚታየው፣ የተጠቃሚ ቅርጸት ግኝት ይመራናል። (የ‘ጥብቅ_መሕልፈቃል_አለው (has_secure_password) ዘዴ የ‘ኖረ (presence) ማስረገጫን ያካትታል፣ የሚያሳዝነው ግን ማረጋገጫው የሚያረጋግጠው ባዶ የሆኑ የመሕለፈቃል መዝገቦችን ብቻ ነው። ማለትም ተጠቃሚዎች እንደ '      ' (ስድስት ክፍትቦታ) ያሉ መሕለፈቃሎችን እንዲፈጥሩ ያስችላቸዋል)

ዝርዝር 6.43: የተሟላው የጥብቅ መሕለፈቃሎች ትግበራ። አረንጓዴ 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 }
end

በዚህ ጊዜ ፈተናው አረንጓዴመሆን አለበት፡-

ዝርዝር 6.44: አረንጓዴ
$ rails test:models

መልመጃዎች

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

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

  1. ብቁ ስም እና የኤመልእክት አድራሻ ያለው፣ ነገር ግን የመሕለፈቃል እርዝመቱ አጪር የሆነ አንድ ተጠቃሚ ተቀባይነት እንደለለው አረጋግጡ፡፡
  2. ከስህተቱ ጋር ተዛማጅ የሆኑት የስህተት መልእክቶች ምንድን ናቸው?

6.3.4 አንድ ተጠቃሚን መፍጠር እና ማረጋገጥ

አሁን መሰረታዊው የተጠቃሚ ቅርጸት ተጠናቋል፣ በክፍል 7.1 ውስጥ አንድ የተጠቃሚ መረጃ ማሳያ ገጽን ለመስራት እንደ አንድ ቅድመ ዝግጅት ይሆነን ዘንድ፣ በውሂበጎታ ውስጥ አንድ ተጠቃሚን እንፈጥራለን፡፡ እንዲሁም የ‘አረጋግጥ (authenticate) ዘዴ አስፈላጊነትን በአንክሮ ማየትን ጨምሮ፣ ጥብቅ_መሕለፈቃል_አለው‘ን (has_secure_password) በተጠቃሚ ቅርጸቱ ላይ ማከሉ ያመጣውን ተጨባጪ ለውጥንም እንመረምራለን፡፡

ተጠቃሚዎች በድር በኩል ለማሳያ አፕልኬሽኑ ገና መመዝገብ (ይህ የምዕራፍ 7 ግብ ነው) ባይችሉም፣ አንድ አዲስ ተጠቃሚን ለመፍጠር ግን የሬይልስ ሰሌዳን እንጠቀማለን። ለአመቺነት በክፍል 6.1.3 ውስጥ የተወያየንበትን የ‘ፍጠር (create) ዘዴን እንጠቀማለን፣ ነገር ግን በዚህ ጊዜ የተፈጠረው ተጠቃሚ ውሂበጎታው ላይ እንዲቀመጥ ለማድረግ በአንድ አሸዋሳጥን ውስጥ ላለመጀመር ጥንቃቄ እናደርጋለን፡፡ ይህ ማለት የሬይልስ ሰሌዳ (rails console) ክፍለ ጊዜን መጀመር እና ከዚያ ከአንድ ብቁ ስም እና የኤመልእክት አድራሻ ጋር አንድ ብቁ የመሕለፈቃል እና ተዛማጅ የመሕለፈቃል ማረጋገጫን ያሟላ አንድ ተጠቃሚን መፍጠር ማለት ነው፡-

$ rails console
>> Teteqami.create(sim: "Michael Hartl", emelekt: "michael@misalei.com",
?>             password: "yonatan", password_confirmation: "yonatan")
=> #<Teteqami id: 1, sim: "Michael Hartl", emelekt: "michael@misalei.com",
"2020-11-12 00:00:18", updated_at: "2020-11-12 00:00:18",
password_digest: [FILTERED]>

ይህ መስራቱን ለማረጋገጥ፣ እስኪ በምስል 6.1021 ላይ እንደሚታየው፣ የውጎ አሳሽ ለቀመቋ (“DB Browser for SQLite”) ፕሮግራምን በመጠቀም፣ በብልጸጋ ውሂበጎታ ውስጥ የ‘ተጠቃሚዎች (teteqamis) ሰንጠረዥ ግኝትን እንመልከት፡፡ (የደመና ቅ.ማ.አን እየተጠቀማችሁ ከኖነ፣ ልክ በምስል 6.5 ላይ እንደሚታየው አድርጋችሁ የውሂበጎታ ፋይሉን ማውረድ ይኖርባችኋል፡፡) አምዶቹ በምስል 6.9 ውስጥ ከተበየኑት የውሂብ ቅርጸት ባሕሪወች ጋር እንደሚዛመዱ አስተውሉ፡፡

images/figures/sqlite_user_row_with_password
ምስል 6.10: በ‘ቀ.መ.ቋ ውሂበጎታ ውጎ/ብልጸጋ.ቀመቋ3 (db/development.sqlite3) ውስጥ ያለ አንድ የተጠቃሚ ረድፍ።

ወደ ሰሌዳው በመመለስ ዝርዝር 6.43 ውስጥ ያለው የ‘ጥብቅ_መሕለፈቃል_አለው (has_secure_password) ዘዴ ያስገኘውን ውጤት የ‘መሕለፈቃል_ፈጪ (password_digest) ባሕሪ ላይ መመልከት እንችላለን፡-

>> ተጠቃሚ = Teteqami.find_by(emelekt: "michael@misalei.com")
>> ተጠቃሚ.password_digest
=> "$2a$12$WgjER5ovLFjC2hmCItmbTe6nAXzT3bO66GiAQ83Ev03eVp32zyNYG"

ይህ የተጠቃሚውን ቁስ ለማስጀመር ያገለገለ የተከተፈው የ‘ዮናታን ("yonatan") መሕለፈቃል ስሪት ነው። ቢሲክሪፕትን በመጠቀም የተገነባ ስለሆነ፣ የመጀመሪያውን መሕለፈቃል22 ለማግኘት ፍጪውን ተጠቅሞ ማስላቱ (ኮምፒተሮችን ተጠቅሞ ማስላቱ) ፈጽሞ የማይታሰብ ነው።

ክፍል 6.3.1 ላይ እንደተመለከተው፣ ጥብቅ_መሕለፈቃል_አለው (has_secure_password) በተዛማጁ ቅርጸት ቁሶች ላይ አንድ የ‘አረጋግጥ (authenticate) ዘዴን በራስሰር ያክላል፡፡ ይሄ ዘዴ ለአንድ የተለየ ተጠቃሚ የተሰጠ አንድ መሕለፈቃልን፣ ፍጪውን በማስላት እና ውጤቱን በውሂበጎታው ውስጥ ካለው መሕለፈቃል_ፈጪ (password_digest) ጋር በማነጻጸር ብቃቱን ይወስናል። ቀደም ብለን ለፈጠርነው ተጠቃሚ አንዳንድ ብቃት የለላቸው መሕለፈቃሎችን እንደሚከተለው አድርገን በመሞከር ይህንን እወንውታ ማረጋገጥ እንችላለን፡-

>> ተጠቃሚ.authenticate("ትክክለኛ_ያልሆነ_መሕለፈቃል")
false
>> ተጠቃሚ.authenticate("አታላይ")
false

እዚህ ጋር የ‘ተጠቃሚ.አረጋግጥ (ተጠቃሚ.authenticate) ዘዴው ብቃት ለሌለው መሕለፈቃል ሃሰት‘ን (false) ይመልሳል፡፡ በብቁ መሕለፈቃል የምናረጋግጥ ከሆንን ግን የ‘አረጋግጥ (authenticate) ዘዴው ተጠቃሚውን ራሱን ማለት ተጠቃሚ ቁሱን ይመልስልናል:-

>> ተጠቃሚ.authenticate("yonatan")
=> #<Teteqami id: 1, sim: "Michael Hartl", emelekt: "michael@misalei.com",
created_at: "2019-08-22 03:15:38", updated_at: "2019-08-22 03:15:38",
password_digest: [FILTERED]>

ምዕራፍ 8 ላይ የተመዘገቡ ተጠቃሚዎችን ወደ ጣቢያችን ለማስገባት የ‘አረጋግጥ (authenticate) ዘዴን እንጠቀማለን፡፡ በእርግጥ የ‘አረጋግጥ (authenticate) ዘዴው ተጠቃሚውን እንዲመልስ ማድረጉ ለእኛ አስፈላጊ አይሆንም፤ ለኛ የሚያስፈልገን በአንድ የቡልየን አውድ ውስጥ አንድ የ‘እውነት (true) ዋጋን እንዲመልስልን ብቻ ነው፡፡ አናጋ አናጋ !! አንድ ቁስን ወደ ተጓዳኙ የቡልየን ዋጋ ይለውጣል ተብለን በክፍል 4.2.2 ውስጥ እንደተማርን ታስታውሳላችሁ፣ እሱ ተጠቃሚ.አረጋግጥ (ተጠቃሚ.authenticate) ላይ ተግባሩን በጥሩ ሁኔታ እንደሚተገብርም ማየት እንችላለን:-

>> !!ተጠቃሚ.authenticate("yonatan")
=> true

መልመጃዎች

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

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

  1. ሰሌዳውን አቁማችሁ እንደገና አስጀምሩት፣ እና ከዚያ በዚህ ክፍል ላይ የፈጠራችሁትን ተጠቃሚ ፈልጉ።
  2. ያገኛችሁትን ተጠቃሚ በአንድ አዲስ ስም ቀይሩ፣ እና የ‘አስቀምጥ (save) ዘዴን ጥሩበት፣ ለምን ተጠቃሚው በውሂበጎታው ላይ መቀመጥ አልቻለም?
  3. የተጠቃሚውን ስም በገዛ ስማችሁ መድቡ/ቀይሩ። ጠቃሚ ምክር:- አስፈላጊውን ዘዴ በክፍል 6.1.5 ውስጥ ተምረናል።

6.4 ማጠቃለያ

በዚህ ምዕራፍ ውስጥ፣ ከባዶ ጀምረን በስም በኤመልእክት እና በመሕለፈቃል ባሕሪወች ዋጋቸው ላይ በርካታ አስፈላጊ መስፈርቶችን የሚያስገድዱ ማስረገጫዎችን ያጣመረ አንድ የሚሰራ የተጠቃሚ ቅርጸትን ፈጥረናል፡፡ በተጨማሪም፣ አንድ በተሰጠ መሕለፈቃል ላይ፣ ተጠቃሚዎችን በጥብቅ ማረጋገጥ ችለናል፡፡ በአስራ ሁለት መስመር ኮዶች ብቻ ይህንን የመሰለ ችሎታ ማግኘቱ በጣም የሚያስደንቅ ነው፡፡

የእያንዳንዱን ተጠቃሚ መረጃ የሚያሳይ አንድ ገጽን ጨምሮ፣ በሚቀጥለው ምዕራፍ 7 ላይ አዲስ ተጠቃዎችን የሚፈጥር አንድ የመመዝገቢያ ቅጽን እንሰራለን፡፡ ከዚያ በምዕራፍ 8 ላይ ተጠቃሚዎች ወደ ጣቢያው መግባት እንዲችሉ ለማስቻል ክፍል 6.3 ላይ ያለውን የማረጋገጫ ፋብሪካ እንጠቀማለን፡፡

ጊትን እየተጠቀማችሁ ከሆነ እና እስከአሁን ድረስ ምንም ካላቀላቀላችሁ፣ አሁን ጊዜው ለማቀላቀል የተመረጠ ይሆናል፡-

$ rails test
$ git add -A
$ git commit -m "አንድ መሰረታዊ የተጠቃሚ ቅርጸትን መስራት (ጥብቅ መሕለፈቃሎችን ጨምሮ)"

ከዚያ ወደ ዋና ቅርንጫፉ መልሳችሁ አዋህዱ እና ወደ ሩቁ ማከማቻ ግፉት:-

$ git checkout main
$ git merge ተጠቃሚዎችን-መቅረጽ
$ git push

በምርት ላይ የተጠቃሚ ቅርጸቱ እንዲሰራ ለማድረግ፣ በሃረኩ ላይ መፍለሶችን ማስኬድ ይኖርብናል፣ ይህንንም በሃረኩ አስኪድ (heroku run) ማድረግ እንችላለን፡-

$ rails test
$ git push heroku
$ heroku run rails db:migrate

ይህን በአንድ የምርት ሰሌዳ ውስጥ በማስኬድ፣ መስራቱን ማረጋገጥ እንችላለን፡-

$ heroku run rails console --sandbox
>> Teteqami.create(sim: "Michael Hartl", emelekt: "michael@misalei.com",
?>             password: "yonatan", password_confirmation: "yonatan")
=> #<Teteqami id: 1, sim: "Michael Hartl", emelekt: "michael@misalei.com",
"2020-11-12 00:00:18", updated_at: "2020-11-12 00:00:18",
password_digest: [FILTERED]>

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

  • ፍልሰቶች የአፕኬሽናችንን የውሂብ ቅርጸት ማሻሻል እንደሚያስችሉን፣
  • ንቅ መዝገብ የውሂብ ቅርጸቶችን ለመፍጠር እና ለማንቀሳቀስ፣ ከብዙ ዘዴወች ጋር እንደሚመጣ፣
  • የ‘ንቅ መዝገብ ማስረገጫዎች በቅርጸት ውስጥ ባሉት ውሂብ ላይ መስፈርቶችን ማስቀመጥ እንደሚያስችለን፣
  • የተለመዱ ማስረገጫዎች የመኖር፣ የእርዝመት እና የቅርጸት ማስረገጫዎችን እንደሚያካትቱ፣
  • መደበኛ ሂሳበሃረጎች ውስብስብ ነገር ግን ሃይለኛ እንደሆኑ፣
  • አንድ የውሂበጎታ መረጃ-ጠቋሚን መበየን፣ ውሂብ የመመልከት ቅልጥፍናን እንደሚያሻሽል እና እንዲሁም በውሂበጎታው ላይ የልዩነት መኖርን እንደሚያስገድድ፣
  • አብሮገነቡ የ‘ጥብቅ_መሕልፈቃል_አለው (has_secure_password) ዘዴን በመጠቀም አንድ ጥብቅ መሕለፈቃልን አንድ ቅርጸት ላይ ማከል እንደምንችል ተምረናል።
1. ስሙ የመጣው ከ “active record pattern” ሲሆን፤ የታወቀው እና የተሰየመው Patterns of Enterprise Application Architecture በተባለው መጽሐፍ ውስጥ፣ በደራሲው ማርቲን ፎውለር ነው፡፡
2. ሲነበብ “ኤስ-ኩ-ኤል (ess-cue-ell)” ተብሎ የሚነበብ ቢሆንም “ሲኴል (sequel)” የሚለው አነባበብም የተለመደ ነው። (ያልተወሰነ ጽሑፉን ማለት “ኤ‘ን (a)” እና “አን‘ን (an)” በመመልከት) አንድ ጸሃፊን የትኛውን ዓይነት አጻጻፍን/አባባልን እንደሚመርጥ በሚጠቀመው ወሰን የሌለው ጽሑፍ አጻጻፍ መለየት ይቻላል። “a SQL database” ብለው የሚጽፉ “ሲኴል (sequel)” ብለው ማንበብን/መጥራትን ሲመርጡ “an SQL database” ብለው የሚጽፉ ደግሞ “ኤስ-ኩ-ኤል (ess-cue-ell)” ብለው ማንበብን/መጥራትን ይመርጣሉ። ያንተ ምርጫስ የትኛው ነው? ትሉ ይሆናል፣ መልሱን በቅርቡ ታዩት ነበረ፤ ከጠየቃችሁ ግን መልሴ የኋለኛው ይሆናል፡፡
3. የኤመልእክት አድራሻን እንደተጠቃሚስም በመጠቀም ወደፊት ከተጠቃሚዎች ውሂብ ጋር መገናኘት የሚያስችለንን እድል እንከፍታለን፡፡ (ምዕራፍ 11 እና ምዕራፍ 12)
4. የ‘ሰ (t) ቁስ ይህንን እንዴት በትክክል እንደሚሰራው ለማወቅ መጨነቅ የለባችሁ። የእንቆቅልሽ ምንጣፍ (Abstraction Layer) አስደሳችነቱ ስለሱ ማወቅ የማያስፈልገን መሆኑ ነው። እኛ የሚያስፈልገን የ‘ሰ (t) ቁስ ስራውን በሚገባ እንደሚሰራ መተማመን ብቻ ነው፡፡
5. ሲነበብ/ሲጠራ “ኤስ-ኩ-ኤል-ላይት (ess-cue-ell-ite)” ተብሎ የሚነበብ/የሚጠራ ቢሆንም፣ “ሲኴል-ላይት (sequel-ite)” የሚለው አነባበብም/አባባልም የተለመደ ነው፡፡
6. ተ.መ.ቋን በተመለከተ አጪር ትምህርት የሚሰጠው በክፍል 14.3.3 ውስጥ ብቻ ከመሆኑ በስተቀር፡፡
7. በውሂበጎታው ውስጥ ያሉ ውሂቦች በሙሉ ቅንጁ ሁለንተናዊ ጊዜ (Coordinated Universal Time) (ቅ.ሁ.ጊ UTC) በተባለው የጊዜ አቆጣጠር ተመዝግበው በውሂበጎታው ውስጥ ተቀምጠዋል፣ ይህ አቆጣጠርም በአብዛኛው ስራ ላይ የግሪንዊች አማካይ ጊዜ (Greenwich Mean Time) የተባለው የጊዜ አቆጣጠር ከሚሰጠው አገልግሎት ጋር አንድ ዓይነት ነው (ማለት በሁለቱ ያለው የጊዜ ልዩነት የአንድ ሰከንድ ክፍልፋይ ነው)፡፡ የቃል መነሻ ስብስቡን ጊ.ቅ.ሁ (CUT) ብሎ እንደመሰየም ለምን ቅ.ሁ.ጊ (UTC) ብለው ሰየሙት? ይህ ጥያቄ በመመደቢያ እና የቴክኖሎጂ ብሔራዊ ተቋም ላይ፣ የጊዜ መደብን በተመለከተ በአብዛኛው የሚቀርብ ጥያቄ አምድ ላይ እንዲህ ተብሎ ተጠይቆ ነበር:- ቅንጁ ሁለንተናዊ ጊዜ (Coordinated Universal Time) ለሚለው ስም ቅ.ጊ.ሁ (CTU) የተባለ የቃል መነሻ ስብስብን እንደመሰየም ፈንታ ለምን ቅ.ሁ.ጊ (UTC) ተብሎ ተሰየመ? የተሰጠው መልስም የሚከተለው ነበር:- በ 1970 እ.ኤ.አ. የ‘ቅ.ጊ.ሁ (CTU) ስርዓት በአለም አቀፍ የቴሌኮሙኒኬሽን ህብረት (አ.አ.ቴ.ህ (ITU)) ውስጥ፣ በዓለም አቀፍ የቴክኒክ አማካሪዎች ቡድን፣ አለም አቀፍ የሆነ የጊዜ መቁጠርያ እንዲሆን ተወሰነ። አ.አ.ቴ.ህ (ITU) የቃል መነሻ ስብስቡን፣ ሊያጋጥሙ የሚችሉትን የስም መወዛገብ ለመቀነስ እና በአለም ላይ ላለ ሁሉም ቋንቋ አንድ ትርጉም ሊሰጥ በሚችል፣ የቃል መነሻ ስብስብ መግለጹ የበለጠ እንደሆነ ወሰነ። እናም የዚሁ ስም የቃል መነሻ ስብስብ በእንግሊዝኛ ጊ.ቅ.ሁ (CUT)፣ በፈረንሳይኛ ደግሞ ጊ.ሁ.ቅ (TUC) ስለሆነ ሁሉንም ለማስማማት ሲባል ቅ.ሁ.ጊ (UTC) የተባለው የቃል መነሻ ስብስብ ተመረጠ።
8. ልዩነት (Exceptions) እና ልዩነትን ማስተናገድ (Exception Handling) በመጠኑ ላቅ ያሉ የሩቢ ፕሮግራም ርዕሰ ጉዳዮች ናቸው፣ እናም በዚህ መጽሐፍ ውስጥ ብዙ አያስፈልጉንም። ይሁን እንጅ፣ እነሱ በጣም አስፈላጊ ነገሮች ናቸው፣ እና እኔም በክፍል 14.4.1 ውስጥ፣ እንደ ምክር ከተሰጡት የሩቢ መጽሐፍት ውስጥ አንዱን ተጠቅማችሁ ስለነሱ እንድትማሩ ከወዲሁ ሃሳቤን አቀርባለሁ፡፡
9. ይህ ዘዴ ካሁን በፊት፡ ባሕሪዎች_አዘምን (update_attributes) በመባል ይታወቅ ነበረ።
10. ከሰሌዳ ትእዛዙ የሚገኘው ውጤት ትምህርት የሚሰጥ ካልሆነ በስተቀር ውጤቱን አልጽፈውም/እንዲታይ አላደርገውም፣ ለምሳሌ ከ‘አዲስ.ተጠቃሚ (Teteqami.new) የሚገኙ ውጤቶችን እና ወዘተረፈ እንደማለት ነው፡፡
11. ለምሳሌ "Michael Hartl"@misalei.com ከጥቅስ ምልክቶች ጋር በመሃል ክፍት ቦታ ያለው የኤመልእክት አድራሻ በደንቡ መሰረት ተቀባይነት ያለው መሆኑን ታውቃላችሁ? የሚገርም ነገር ነው፣ ነገር ግን ይሄ የተለመደ አይደለም።
12.ሰንጠረዥ 6.1 ውስጥ “ፊደል” ማለት “የእንግሊዝኛ ንዑስ ፊደል” ማለት ሲሆን መጨረሻ ላይ ያለው i ግን ሁሉንም ዓይነት የእንግሊዝኛ ፊደላት መቀበልን/ማዛመድን ያስገድዳል፡፡
13. የሩቡላር አፕልኬሽንን እኔ ጠቃሚ ሆኖ እንዳገኘሁት ሁሉ እናንተም ጠቃሚ ሆኖ ካገኛችሁት፣ ሉብላርን ለገነባው አቶ ማይክል ሎቪት ላደረገው ድንቅ ስራ ወሮታውን እንድትከፍሉ (ዶኔት እንድታደርጉ) ወንድማዊ የሆነ ድጋፌን በክብረት አቀርባለሁ፡፡
14. በዚህ ክፍል መግቢያ ላይ እንደገለጸነው ለፈተና አገልግሎት ብቻ የተወሰነ የፈተና ውሂበጎታ በ‘ውጎ/ፈተና.ቀመቋ3 (db/test.sqlite3) ውስጥ አለ፡፡
15. በአጠቃላይ ሲታይ፣ የኤመልእክት አድራሻ በሁለት ክፍሎች የተመሰረተ አድራሻ ነው፡፡ እነሱም የመጀመሪያው ክፍል የተጠቃሚውን ስም የያዘ ሲሆን፣ ሁለተኛው ክፍል ደግሞ የኤመልእክት አገልግሎት የሚሰጠውን ድርጅት የግዝአት ስም የያዘ ይሆናል፡፡ ለምሳሌ:- “eden@nega.com” የሚለው የኤመልእክት አድራሻ “eden” የሚለው የተጠቃሚውን ስም የሚያመለክት ሲሆን፣ “nega.com” ደግሞ የአገልግሎት ሰጪውን የግዝአት ስም ያመላክታል ማለት ነው። በኤመልእክት አድራሻ አሰራር ደንብ መሰረት፣ የኤመልእክት አድራሻው የግዝአት ስም በተፈለገው ዓይነት የእንግሊዝኛ ፊደላት መጻፍ ይቻላል ማለት:- “Nega.com” ወይም “Nega.Com”። በርግጥ ከተመለከትን eden@nega.comEden@nega.com የተለየ ነው፣ እናም ይህንን እውነታ እንዳለ አሜን ብሎ መቀበሉ አደጋ ላይ ሊጥል እንደሚችል ስለ.ኮም የተባለው ጣቢያ እንዲህ የሚል ምክር ይሰጣል:- “በአብይ እና በንዑስ ፊደላት የተጻፉ የኤመልእክት አድራሻወች፣ ብዙ ውዥንብር በመፍጠር እርስ በርስ የሚያያዙ ችግሮችን እና ወሰን የሌለው የስራ እንቅፋትን ሊያስከትሉ እንደሚችሉ ግምት ውስጥ በማስገባት ተጠቃሚዎችን ለአንድ ጣቢያ ሲመዘገቡ፣ የኤመልእክት አድራሻቸውን ትክክለኛ የሆነውን የእንግሊዝኛ ፊደል ተጠቅመው እንዲጽፉ መመኘቱ ሞኝነት ነው፡፡ ማንኛውም የኤመልእክት አገልግሎት ሰጪ ድርጅት፣ ወይም የበይነመረብ አገልግሎት አቅራቢ (በ.አ.አ (ISP))፣ የኤመልእክት አድራሻዎች በሙሉ፣ በንዑስ ፊደላት መጻፍ እንዳለባቸው ያስገድዳል፣ እናም የተቀባዩ የኤመልእክት አድራሻ በትክክል ያልተጻፈበት መልእክትን ወደ መጣበት መልሶ በመስደድ ጥጉን ያስይዘዋል (ለምሳሌ:- ሁሉንም የኤመልእክት አድራሻ በአብይ ፊደላት ጽፎ መስደድ ይህን ችግር ያስከትላል)።” ይህንን ጠቃሚ ምክር እንድንመለከት አስተያየታቸውን ላበረከቱት ክቡር አንባቢ ሪሌይ ሞሰስን ከልብ ላመሰግናቸው እወዳለሁ።
16.ዝርዝር 6.2 ላይ ያለው የፍልሰት ፋይል ውስጥ፣ የ‘ተጠቃሚዎች (teteqamis) ሰንጠረዥ ላይ፣ ይህንን የኤመልእክት አድራሻ መረጃ-ጠቋሚ መጨመር እንችል ነበር፣ ነገር ግን ውሂበጎታውን ወደኋላ መመለስ እና ከዚያ በኋላ ደግሞ እንደገና ማፍለስን ይጠይቃል፡፡ የኛ አሰራር ግን የሬይልስ የአሰራር ሂደትን በመከተል፣ ™ የውሂብ ቅዳችንን መቀየር በፈለግን ጊዜ ፍልሰትን መጠቀም ይሆናል፡፡
17. ስለ መልሰጥሪወች ተጨማሪ መረጃ ለማግኘት ከፈለጋችሁ፣ የሬይልስ አ.ፕ.በ (API) ስለ መልስጥሪዎች መግቢያ ገጽን መጎብኘት ትችላላችሁ፡፡
18. ይህንን ጉዳይ ላመለከቱት ክቡር አንባቢ አሌክስ ፍሬድማን‘ን በጣም የከበረ ምስጋና ይድረሳቸው ብያለሁ።
19. ምናባዊ ባሕሪ ማለት በውሂበጎታ ውስጥ ምንም ዓይነት ውክልናን ያልያዘ የክፍል ባሕሪ ነው። ይህ ማለት ባሕሪወቹ ውሂበጎታው ጋር ሳይገናኙ መረጃው ላይ ብቻ የተወሰኑ ናቸው ማለት ነው።
20. የተከተፉ መሕለፈቃሎች በተሳሳተ መንገድ “ምስጥር (Encrypted)” መሕለፈቃሎች ተብለው ተጠቅሰዋል፡፡ ለምሳሌ ያየን እንደሆን፣ የዚህ ስልጠና የመጀመሪያዎቹ ሁለት ስሪቶች እና የ‘ጥብቅ_መሕለፈቃል_አለው (has_secure_password) የኮድ ምንጩ ሳይቀር የዚህ ስህተት ተካፋዮች ሁነዋል፡፡ የዚህ ቃል ስነአባባል (Terminology) የተሳሳተ ነው፣ ምክንያቱም የመመስጠር አሰራር የተነደፈው፣ አንድ ነገርን ወደነበረበት መልሶ እንዲያቀርብ ነው፡፡ ይህ ማለትም፣ አንድ ነገርን የመመስጠር ችሎታ ካለ፣ ሚስጥረቢስ (Decrypt) የማድረግ ማለት የተመሰጠረውን ወደ ነበረበት የመቀልበስ ችሎታ አለ ማለት ነው፡፡ በተቃራኒው፣ አንድ መሕለፈቃል እንዲከተፍ የማስላቱ ዋናው ምክንያት፣ ፍጹም ወደነበረበት የማይመለስ እንዲሆን ነው፤ ስለሆነም ዋናውን የመሕለፈቃል ከፍጪው ለማግኘት ማስላቱ ፍጹም አስቸጋሪ ነው። በሌላ አማርኛ ፍጪውን አስልቶ ኦርጅናሉን መሕለፈቃል ለማገኘት ከመጣር ይልቅ ግመልን በመርፌ ቀዳዳ ማሳለፉ ይቀላል። ለዚህም ነው አባባሉ ትክክል ያልሆነው። (ለክቡር አንባቢ አቶ አንዲ ፊሊፕስ ይህንን የተሳሳተ አባባል እንዳስተካክል ስላበረከቱልኝ አስተያየት በጣም አመሰግናለሁ።)

21. በሆነ ምክንያት የሆነ ችግር ከተከሰተ፣ ውሂበጎታውን እንደሚከተለው አድርጋችሁ እንደ አዲስ ማስጀመር ትችላላችሁ:-

  1. መጀመሪያ ሰሌዳውን ማቆም፣
  2. ከዚያ ውሂበጎታውን ለማስወገድ፣ የ‘በግድ ማበልጸጊያ.ቀመቋ3‘ን አስወግድ ($ rm -f development.sqlite3) ትእዛዝን በማዘዥያ መስመሩ ላይ ማስኬድ፣ (በነገራችን ላይ ይህንን ለማድረግ ከዚህ የበለጠ ዘዴ ምዕራፍ 7 ላይ እንማራለን፡፡)
  3. ከዚያ የሬይልስ ውጎ፡አፍልስ ($ rails db:migrate) ዘዴን በመጠቀም፣ እንደ አዲስ ፍልሰቱን ማስኬድ
  4. እና መጨረሻ ላይ ሰሌዳውን እንደገና ማስጀመር ይሆናል፡፡
22. ሀ ብሎ ሲሰራ፣ የቢክሪፕቲ ቤተኮድ ስልተ-ቀመር (አልጎሪዝም)፣ ከሁለቱ ማለት የመዝገበ ቃላት ጥቃት (Dictionary Attack) እና የቀስተ-ደመና ጠረጴዛ ጥቃት (Rainbow Table Attack) ከተባሉት ዓበይት የደህንነት ጥቃት መሕለፈቃሉን ለመከላከል፣ የተመሰጠረ ነገር ላይ፣ የበለጠ ለመመስጠር የሚያገለግለውን፣ ጨው ማድረግ የተባለውን ዘዴ በመጠቀም፣ መሕለፈቃሉ ላይ ተጨማሪ ምስጠራን ያክላል።