በምዕራፍ 8 ላይ የበለጸገው መሰረታዊ የመግቢያ ስርዓት ሙሉ በሙሉ የሚሰራ ነው፤ ነገር ግን አብዛኛዎቹ ዘመናዊ ድረጣቢያዎች ተጠቃሚዎች ጣቢያቸውን ጎብኝተው አሳሻቸውን ለጊዜው ቢዘጓቸውም እንኳ፤ የነበሩበትን ጣቢያ እንደገና ተመልሰው ሲጎበኙ አሳሹ ተጠቃሚዎቹን ማስታወስ የሚችል አንድ “የመዘከር” ችሎታን በአሳሹ ላይ ያካትታሉ፡፡ በዚህ ምዕራፍ ውስጥ ይህንን ባህሪ ለመተግበር ቛሚ ብስኩቶችን እንጠቀማለን፡፡ ተጠቃሚዎች ልክ ሲገቡ መለያቸውን በራስሰር በማስታወስ ስራችንን እንጀምራለን(ክፍል 9.1)፤ ይህም እንደ ቢትባኬት እና ጊትሃብ በመሳሰሉ ጣቢያዎች ላይ ጥቅም ላይ የዋለ አንድ የተለመደ ቅድ ነው፡፡ ከዚያ በመቀጠልም አንድ የ“ዘክረኝ” አመልካችሳጥንን በመጠቀም ተጠቃሚዎች በምርጫቸው መለያቸው በአሳሹ ላይ እንዲቆይ የሚፈልጉ ከሆነ፣ አሳሹ መለያቸውን እንዲያዘካክራቸው የሚያደርግ አንድ ችሎታን እናክላለን፤ ይህም እንደ ትዊተር እና ፌስቡክ በመሳሰሉ ጣቢያዎች ላይ ጥቅም ላይ የዋለ አንድ የተለመደ ቅድ ነው፡፡
በምዕራፍ 8 ላይ የተሰራው የድሩ የመግቢያ ስርዓት ራሱን ችሎ የሚሰራ እና ሙሉ በሙሉ የተሟላ ስለሆነ፣ የማሳያ አፕልኬሽኑ ዋና አካል “ዘክረኝ” ሳይጨመርበትም በጥሩ ሁኔታ ይሰራል፤ ስለዚህ ካስፈለገ በቀጥታ ወደ ምዕራፍ 10 ከዚያም ካስፈለገ ወደ ምዕራፍ 13 ዘላችሁ ማለፍ ትችላላችሁ፡፡ በሌላ በኩል ደግሞ የ“ዘክረኝ” ባህሪን እንዴት ተግባራዊ ማድረግ እንደሚቻል መማሩ ራሱ፣ እጅግ አስተማሪ እና ቀጥለን ለምንመለከታቸው ማለት ለመለያ ግባሬ (ምዕራፍ 11) እና ለመሕለፈቃል ዳግመጅማሬ (ምዕራፍ 12) ስራ ላይ በጣም አስፈላጊ የሆነ አንድ መሰረትን ያስቀምጣል። ከዚህ በላይም ውጤቱ አንድ የላቀ የኮምፒዩተር አስማት ምሳሌ ይሆናል፤ በቢሊዮን በሚቆጠሩ የድሮች የመግቢያ ቅጽ ላይ “ዘክረኝ (remember me)” የሚለውን ጽሑፍ አይታችኋል፣ አሁን ደግሞ እናንተ ይህንን አጋጣሚ በመጠቀም ይህንኑ ገጸባህሪ በድራችሁ ላይ እንዴት አድርጋችሁ እንደምትሰሩ ለመማር እድሉን ይሰጣችኋል።
በዚህ ክፍል ውስጥ ተጠቃሚዎቻችን በድራችን ውስጥ ከገቡ በኋላ አሳሻቸውን ዘግተው እንደገና ተመልሰው አሳሻቸውን ቢከፍቱም እንኳ፣ በድራችን ውስጥ ከድሮውም እንደገቡ የሚዘክር አንድ ችሎታን በአፕልኬሽናችን ላይ እናክላለን፡፡ ይህ የ “ዘክረኝ” ባህሪ በራስሰር ይከናወናል፤ እናም የድሩ ተጠቃሚዎች እራሳቸው ሆን ብለው ከድሩ እስካልወጡ ድረስ በራስሰር እንደገቡ ይቆያሉ፡፡ ለወደፊቱ እንደምናየው፣ ከዚህ የሚገኘው ፋብሪካ የ “ዘክረኝ” ን አማራጫዊ የአመልካችሳጥን ባህሪን በአፕልኬሽኑ ላይ ለማከል ቀላል ያደርገዋል (ክፍል 9.2)፡፡
ከመቀጠላችሁ በፊት እንደተለመደው፣ አንድ ርእስ ቅርንጫፍ እንድትፈጥሩ ምክሬን ከወዲሁ እለግሳለሁ፡-
$ git checkout -b የላቀ-መግቢያ
በክፍል 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
) ቅርንጫፍ ላይ ይገኛል፡፡
እነዚህን የንድፍ እና የጥበቃ ጉዳዮች በግምት ውስጥ በማስገባት፣ ቋሚ ክፍለጊዜወችን ለመፍጠር ያስቀመጥነው እቅድ እንደሚከተለው ይቀርባል:-
አምስተኛው ሂደት፣ አንድ ተጠቃሚን ወደ ጣቢያችን ለማስገባት ከምንጠቀምበት ሂደት ጋር ምን ያህል ተመሳሳይ እንደሆነ ልብ በሉ፤ ማለት ተጠቃሚውን በኤመልእክት አድራሻው ፈልገን ከምናመጣበት እና ከዚያ (የ‘አረጋግጥ (authenticate
) ዘዴን በመጠቀም) የተረከበው መሕለፈቃል ከመሕለፈቃል ፈጪው ጋር የሚዛመድ መሆኑን (ዝርዝር 8.7) ለማወቅ የሰራንበት ጋር ማለት ነው። በዚህም ምክንያት ትግበራችን ከ‘ጥብቅ_መሕለፈቃል_አለው (has_secure_password
) ጋር ትይዩ የሆነ ገጽታዎችን ይይዛል።
በምስል 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 ላይ የሚታየውን አንድ ነባሪ ፍልሰት አመንጪቶልናል።
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 ላይ የተጠቃሚ ቅርጸት ውስጥ ይታያል፡፡
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
) ዘዴን ይሰጣል፡፡
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
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
teteqami
) በተባለ ዋጋ መድቡ፣ ከዚያ የ‘ዘክር (zekr
) ዘዴን ቀጥታ በተጠቃሚ (teteqami
) ቁሱ ላይ በመጥራት ዘዴው እንደሚሰራ አረጋግጡ፡፡ ዝክረ_ይስሙላ‘ን (zkre_ysmula
) ከ‘ዝክረ_ፈጪ (zkre_fech
) ጋር ስታነጻጽሩ፣ ምን ዓይነት ልዩነት ተገነዘባችሁ?
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” ቁስ ቅርፅን ማመላከት መሆኑን ልትገነዘቡት ይገባል፡፡ ይህ ነገር እነዚህን ነገሮች ግራ የሚያጋባ ከሚያደርጋቸው ነገሮች ውስጥ አንዱ ነው፡፡)
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
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
.
.
.
አንድ የሚሰራ የ‘ተጠቃሚ.ዘክር (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
) እንዲሆን አድርጎ በራስሰር እንዲያዘጋጅ ያደርገዋል።
ክፍል 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 ላይ እንጠቃልለዋለን፡፡)
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
) የተባለ ረጅ ዘዴን በክፍለጊዜወች ረጅ ፋይል ውስጥ እናክላለን፡፡
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 ላይ ይታያል፡፡
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 ውስጥ ወደሚታየው ትግበራ ያመራናል።
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 ዓመት ከማስጠበቅ ሌላ ምንም ዓይነት አማራጪ አያቀርብላቸውም፡፡ ይህንን ዓይነት ችግር የፈተና ስብስቡ መያዝ ያለበት ነገር ነው፤ በርግጥም ይዞት ቀይሁኗል።
$ rails test
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
teregagtualn?
) ዘዴ በትክክል እንደሚሰራ በሰሌዳችሁ ውስጥ አረጋግጡ፡፡
ተጠቃሚዎች ከድሩ ዘግተው የሚወጡበትን ችሎታ ለማቅረብ፣ ተጠቃሚዎችን ለመዘከር ዘዴወችን እንደበየንን ሁሉ፣ አሁን ደግሞ ተመሳሳይ በሆነ መልኩ እነሱን ለመርሳት አንዳንድ ዘዴወችን እንበይናለን፡፡
በዝርዝር 9.11 ላይ እንደሚታየው፣ የ‘ተጠቃሚ.እርሳ (teteqami.ersa
) ዘዴ ውጤት ዝክረ ፈጪን በ‘ምንም (nil
) በማዘመን ተጠቃሚ.ዘክር‘ን (teteqami.zekr
) ይቀለብሳል፡፡
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
) ብስኩቶችን ያጠፋል፡፡
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
በዚህ ጊዜ የፈተና ስብስቡ አረንጓዴመሆን አለበት:-
$ rails test
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
መፍትሄ የሚሹ ሁለት በጣም ተቀራራቢ የሆኑ ስውር ሳንካወች አሉ፡፡ የመጀመሪያው ስውር ሳንካ:- አንድ ተጠቃሚ በጣቢያው ከገባ በኋላ፣ ሌላ ሁለተኛ የአሳሽ መስኮት ከፈተ እንበል፤ ከሁለተኛው የአሳሽ መስኮት፣ የጣቢያውን የ “ይውጡ” አገናኝ ተጠቅሞ ከጣቢያው ወጣ እንበል፤ ከዚያ በመቀጠል፣ ከመጀመሪያው የአሳሽ መስኮት የጣቢያውን የ “ይውጡ” አገናኝ ተጠቅሞ፣ ከጣቢያው በሚወጣበት ጊዜ፣ አፕልኬሽኑ ይበላሻል። ይህ ማለት ተጠቃሚው ከአንዱ መስኮት በሚወጣበት ጊዜ፣ የ‘ዓሁን_ተጠቃሚ (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 ያለውን የውህደት ፈተና ቀይበማድረግ እንጀምራለን።
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
) ባለመኖሩ ምክንያት አንድ ስህተትን ስለሚያስነሳ የፈተና ስብስቡ ቀይ መሆን አለበት:-
$ rails test
በዝርዝር 9.16 ላይ እንደሚታየው፣ የአፕልኬሽን ኮዱ ውጣ (wta
) እውነት ከሆነ ብቻ ገብቷልን?‘ን (gebtual?
) መጥራትን ብቻ ያሳትፋል (ይህ ማለት ተጠቃሚው ከገባ ብቻ ያስወጣል ማለት ነው)።
app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
.
.
.
def destroy
wta if gebtual?
redirect_to root_url
end
end
ሁለተኛው ጉዳይ፣ በሁለት የተለያዩ አሳሾች ላይ የሚያጋጥም አንድ ሁኔታን ያሳትፋል፣ ይህን ከአንድ የውህደት ፈተና ጋር ማስመሰሉ በጣም ከባድ ይሁን እንጅ፤ እሱን በተጠቃሚ ቅርጸት ፈተና ውስጥ በቀጥታ መፈተሹ ግን ቀላል ነው። በዝርዝር 9.17 ላይ እንደሚታየው፣ የሚያስፈልገን ነገር ቢኖር፣ አንድ ዝክረ ፈጪ የለለው ተጠቃሚ ላይ የ‘ተረጋግጧልን? (teregagtualn?
) ዘዴን መጥራት ብቻ ነው (በርግጥ በ‘አዘጋጅ (setup
) ዘዴ ላይ የተበየነው የ‘@ተጠቃሚ (@teteqami
) ቅርፀ ተለዋዋጪ፣ ምንም የዝክረ ፈጪ ባሕሪ ስለለለው ለፈተናው ብቁ ይሆናል)፡፡ (እዚህ ላይ አስተውሉ:- የዝክረ ይስሙላን ዋጋ ባዶ አድርገነዋል፤ ምክንያቱም አፕልኬሽኑ ዋጋውን ከመጠቀሙ በፊት፣ ስህተቱ ስለሚከሰት ዋጋው ምንም ይሁን ምን ግድ ስለማይሰጥ ነው።)
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)
) ፣ አንድ ስህተትን ያስነሳል፣ ስለዚህ የፈተና ስብስቡ ቀይመሆን አለበት:-
$ rails test
በዝርዝር 9.19 ላይ እንደሚታየው፣ ስህተቱን ለማስተካከል እና አረንጓዴ‘ን ለማግኘት ማድረግ የሚገባን አንድ ነገር ቢኖር፣ ዝክረ ፈጪው ምንም (nil
) ከሆነ ሃሰት‘ን (false
) መመለስ ብቻ ነው።
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 ውስጥ ካለው ኮድ ጋር፣ ሙሉው የፈተና ስብስባችን አረንጓዴመሆን እና ሁለቱም ጥቃቅን ሰንኮች አሁን መፍትሄ ማግኘት አለባቸው:-
$ rails test
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
ክፍል 9.1.3 ውስጥ ካለው ኮድ ጋር፣ አሁን አፕልኬሽናችን አንድ የተሟላ እና ሞያዊ-ደረጃ ያለው የማረጋገጫ ስርዓት አለው፡፡ የመጨረሻ ሂደት ይሆነን ዘንድ፣ አንድ “ዘክረኝ” የተባለ አመልካችሳጥንን በመጠቀም፣ ገብቶ መቆየትን እንዴት ምርጫዊ እንደምናደርግ እናያለን። እንደዚህ ዓይነቱ አንድ አመልካችሳጥን ከመግቢያ ቅጹ ጋር፣ በምስል 9.3 ላይ ባለው ስእላዊ መግለጫ ላይ ይታያል፡፡
ትግበራውን ለመጻፍ፣ ዝርዝር 8.4 ላይ ባለው የመግቢያ ቅጽ ላይ፣ አንድ አመልካችሳጥንን በማከል እንጀምራለን፡፡ ልክ እንደ:- መሰየሚያወች፣ የጽሑፍ መስኮች፣ የመሕለፈቃል መስኮች፣ እና የማስረከቢያ አዝራሮች፣ የአመልካችሳጥኖችም፣ የሬይልስ ረጅ ዘዴን በመጠቀም መፍጠር ይቻላል። የቅጥ አሰራሩን ትክክለኛ ለማድረግ፣ በመሰየሚያው ውስጥ አመልካችሳጥኑን እንደሚከተለው አድርገን ማስታቀፍ አለብን:-
<%= f.label :ዘክረኝ, class: "አመልካችሳጥን ውስጠመስመር" do %>
<%= f.check_box :ዘክረኝ %>
<span>በዚህ ኮምፕዩተር ላይ ዘክረኝ</span>
<% end %>
ይህንን በመግቢያ ቅጹ ላይ ማስገባት በዝርዝር 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 ላይ ይታያል፡፡
app/assets/stylesheets/bju.scss
.
.
.
/* ቅጾች */
.
.
.
.አመልካችሳጥን {
margin-top: -10px;
margin-bottom: 10px;
span {
margin-left: 20px;
font-weight: normal;
}
}
#session_ዘክረኝ {
width: auto;
margin-left: 0;
}
የመግቢያ ቅጹን አርመን ስለጨረስን፣ አሁን ተጠቃሚዎች የአመልካችሳጥኑ ላይ ምልክት ካደረጉ፣ እነሱን ለመዘከር ካልሆነ ደግሞ ለመርሳት ዝግጁ ነን፡፡ ባሳለፍናቸው ክፍሎች ውስጥ፣ በሰራናቸው ስራውች ምክንያት፤ ይህ የአሁኑ ስራ እጅግ በጣም በሚገርም ሁኔታ፣ አተገባበሩ በአንድ መስመር ላይ፣ ሊጠቃለል የሚችል ኮድ ሊሆን ይችላል። የመግቢያ ቅጹ ውሂብ በሚያስረክብበት ጊዜ፣ የ‘ሰሚአሴቶች (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
) ተለዋዋጪን ለመበየን የተጠቀመበትን የሶስቲት ስሌትን መረዳት የምትችሉበት አቛም ላይ ደርሳችኋል።)
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 ውስጥ ባለው ትግበራ አሁን የመግቢያ ስርዓቱ ተጠናቋል።
“በዓለም ላይ ሁለትዮሽን የሚረዱ እና የማይረዱ፣ 10 ዓይነት ሰዎች አሉ።” የሚል የድሮ ተረት አለ (ያው 10 ማለት በሁለትዮሽ 2 ማለት ነው)። በዚህ ተረት አኳያ፣ በዓለም ላይ ሶስቲት ስሌትን የሚወዱ፣ የማይወዱ እና ገና ስለነሱ የማያውቁ፣ 10 ዓይነት ሰዎች አሉ ማለት እንችላለን (ገና ስለነሱ ከማያውቁት ውስጥ ከሆናችሁ፣ በቅርቡ ከአባልነቱ ትሰናበታላችሁ።)
በተደጋጋሚ የሆነ አፕልኬሽንን በምትሰሩበት ጊዜ፣ በጣም የተለመደው የከሆነ ሁናቴ ተቆጣጣሪ የአሰራር ሂደት፣ የሚከተለውን ዓይነት የአሰራር ሂደትን እንደሚከተል በፍጥነት ትገነዘባላችሁ:-
if ቡልየን? አንድ_ነገር_አድርግ else ካልሆነ_ሌላ_ነገር_አድርግ end
ሩቢ፣ ልክ እንደሌሎቹ ብዙ ቋንቋዎች (ሲ/ሲ++ ፣ ፐርል ፣ ፒኤችፒ እና ጃቫን ጨምሮ)፣ የሶስቲት ስሌትን በመጠቀም ይህንን ኮድ፣ በተጠቀጠቀ ሂሳበሃረግ እንድትተኩ ያስችላችኋል (“ሶስቲት ስሌት” ተብሎ የተጠራበት ምክንያት ኮዱ ለሶስት የተከፋፈለ ክፍል ስላለው ነው)፡፡
ቡልየን? ? አንድ_ነገር_አድርግ : ካልሆነ_ሌላ_ነገር_አድርግ
እንዲሁም፣ ምደባን ለመተካት የሶስቲት ስሌትን መጠቀምም ትችላላችሁ፤ ስለዚህ የሚከተለው ኮድ:-
if ቡልየን? ተለዋ = አስቴር else ተለዋ = ተሸመ end
የሶስቲት ስሌትን በመጠቀም እንደሚከተለው ሊጻፍ ይችላል:-
ተለዋ = ቡልየን? ? አስቴር : ተሸመ
በመጨረሻም፣ አንድ ዋጋን የሚመልስ ሥልት ውስጥ የሶስቲት ስሌትን መጠቀሙ ብዙ ጊዜ አመች ነው:-
def አስቴር መዓት_ነገር_አድርግ ቡልየን? ? "ደስታ" : "ጆሲ" end
ሩቢ ሁል ጊዜ፣ በአንድ ዘዴ ውስጥ የመጨረሻውን የሂሳበሃረግ ዋጋ ይመልሳል፤ እዚህ ላይ የ አስቴር
ዘዴ በ ቡልየኑ?
የእውነት (true)
ወይም የሃሰት (false)
ዋጋ ላይ በመመርኮዝ "ደስታ"
‘ን ወይ ደግሞ "ጆሲ"
‘ን ይመልሳል።
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
ምንም እንኳን፣ የ“ዘክረኝ” ተግባሩ አሁን እንደሚገባው እየሰራ ቢሆንም፣ ባህሪውን ለማረጋገጥ አንዳንድ ፈተናወችን መጻፉ ግን በጣም ጠቃሚ ነው። አንዱ ምክንያት፣ አሁን ከዚህ ቀጥለን እንደምናየው ዓይነት፣ ማለት ኮዱን በመጻፍ ላይ የሚገኙ የአተገባበር ስህተቶችን ለመያዝ ስለሚረዳ ይሆናል፡፡ ከሁሉ በላይ ይበልጥ አስፈላጊ የሆነው ነገር ግን፣ ዋናው የ “ teteqami” ቁስ ውስብስብ ኮድ፣ በአሁኑ ጊዜ ሙሉ በሙሉ ያልተፈተነ መሆኑን መገንዘቡ ነው፡፡ እንደነዚህ ያሉ ፈታኝ ሁኔታዎችን ለመፈተን አንዳንድ ነግሮችን መሸወድ የሚጠይቅ ሲሆን፣ መጨረሻ ላይ ግን፣ ሃያል የሆነ የፈተና ስብስብ ውጤት ባለቤት ያደርጋል፡፡
በዝርዝር 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
) ረጅወችን ያስገኛል፡፡
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 ላይ ያለው የእቃ ተጠቃሚን እንደሚያመላክት ልታስታውሱ ይገባል፡፡)
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
እኔ ያደረግኩትን አይነት የአተገባበር ስህተት እንዳልፈጸማችሁ በመገመት፣ አሁን ፈተናውቹ አረንጓዴመሆን አለባቸው:-
$ rails test
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
zkre_ysmula
) ምናባዊ ባሕሪ ዋጋ ላይ የሚደርስበት ምንም ዓይነት መንገድ እንደለለው አይተናል፡፡ ቢሆንም ቅሉ፣ አንድ መድብ (assigns
) ተብሎ የሚጠራ ልዩ የፈተና ዘዴን በመጠቀም የ‘ዝክረ_ይስሙላ (zkre_ysmula
) ምናባዊ ባሕሪ ዋጋን መድረስ ግን ይቻላል፡፡ በአንድ ፈተና ውስጥ የ‘መድብ (assigns
) ዘዴን ከሚዛመደው ወካይ ጋር በመጠቀም፣ በመቆጣጠሪያ ውስጥ የተበየኑትን ቅርፀ ተለዋዋጮች መድረስ ትችላላችሁ፡፡ ለምሳሌ:- የ‘ፍጠር (create
) ተግባር፣ @ተጠቃሚ (@teteqami
) የተባለ አንድ ቅርፀ ተለዋዋጪ ቢበየን፣ መድብ(:ተጠቃሚ) (assigns(:teteqami)
) ብለን በመጠቀም በፈተናው ውስጥ ልንደርስበት እንችላለን። በአሁኑ ጊዜ፣ በክፍለጊዜወች መቆጣጠሪያ ውስጥ ያለው የ‘ፍጠር (create
) ተግባር አንድ ተራ ተጠቃሚ (teteqami
) የተባለ ተለዋዋጪን በይኗል (ማለት ቅርፅ ያልሆነ ተለዋዋጪን በይኗል ማለት ነው)፣ ነገር ግን ይህንን ተራ ተለዋዋጪ ወደ አንድ ቅርፀ ተለዋዋጪ ከለውጥን፣ ብስኩቶቹ (cookies
) በውስጣቸው የተጠቃሚውን ዝክረ ይስሙላ በትክክል እንደያዙ እና እንዳልያዙ መፈተን እንችላለን። በዝርዝር 9.27 እና በዝርዝር 9.28 ውስጥ በጥያቄ ምልክት ?
እና በ ይህን_ሙሉ
ቦታ ላይ የሚገቡትን ነገሮች በመሙላት፣ ይህንን የተሻሻለ የ“ዘክረኝ” አመልካችሳጥን ፈተና ጪራሽ የተሟላ አድርጉ፡፡
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
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.1.2 ውስጥ፣ ቀደም ባሉት ክፍሎች የተተገበረው ቋሚ ክፍለጊዜ እየሰራ መሆኑን በእጃችን አረጋግጠናል፣ በእውነቱ ከሆነ ግን በ‘ዓሁን_ተጠቃሚ (ahun_teteqami
) ዘዴ ውስጥ የሚገኘው ቅርንጫፍ በአሁኑ ጊዜ ፈጽሞ አልተፈተነም፡፡ እንደዚህ ዓይነቱን ሁኔታ ለማስተናገድ የምወደው መንገድ በተጠረጠረው ያልተፈተነ የኮድ ጥምር ውስጥ አንድ ልዩነትን ማስነሳት ነው፤ ኮዱ ካልተገኘ፣ ፈተናዎቹ አሁንም ያልፋሉ፤ ኮዱ ከተገኘ ደግሞ፣ የሚፈጠረው ስህተት ተዛማጁን ፈተና ይለየዋል። በአሁኑ ጉዳይ ላይ የተገኘው ውጤት በዝርዝር 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
በዚህ ጊዜ ፈተናዎቹ አረንጓዴናቸው:-
$ 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
የፈተናው ቅደም ተከተሎች ቀላል ናቸው:-
teteqami
) የተባለ ተለዋዋጪን መበየን።
zekr
) ዘዴን መጥራት።
ahun_teteqami
) ከቀረበው ተጠቃሚ ጋር እኩል መሆኑን ማረጋገጥ።
የ‘ዘክር (zekr
) ዘዴው የ‘ክፍለጊዜ[:ተጠቃሚመታወቂያ] ‘ን (session[:teteqami_id]
) ስለማያዘጋጅ ይህ አሰራር የተፈለገውን የ‘ዓሁን_ተጠቃሚ (ahun_teteqami
) (የ “ዘክር”) ቅርንጫፍን ይፈትናል። ውጤቱ በዝርዝር 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 ውስጥ ባለው ኮድ ምክንያት፣ ፈተናው እንደተፈለገው ቀይ ሁኗል:-
$ rails test test/helpers/sessions_helper_test.rb
በዝርዝር 9.33 ላይ እንደተመለከተው፣ የ‘አስነሳ (raise
) ዘዴን በማስወገድ እና ኦርጅናሉን የ‘ዓሁን_ተጠቃሚ (ahun_teteqami
) ዘዴን ወደ ነበረበት በማስመለስ፣ በዝርዝር 9.31 ውስጥ ያሉትን ፈተናወች ማሳለፍ እንችላለን፡፡
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
በዚህ ጊዜ፣ የፈተና ስብስቡ አረንጓዴመሆን አለበት:-
$ rails test
አሁን የ‘ዓሁን_ተጠቃሚ (ahun_teteqami
) “ዘክር” ቅርንጫፍ ተፈትኗል፣ በእጅ መፈተን ሳያስፈልገን (በአንድ አሳሽ ላይ አንድ ባንድ መፈተን ሳያስፈልገን) ምልሰትን እንደምንይዝ መተማመን እንችላለን፡፡
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
teregagtualn?
) ሂሳበሃረግ በማስወገድ፣ በዝርዝር 9.31 ውስጥ ያለው ሁለተኛው ፈተና እንደሚወድቅ አረጋግጡ፡፡ በዚህም ትክክለኛውን ነገር መፈተኑን አረጋገጣችሁ ማለት ነው፡፡
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 ላይ እንተገብራለን፡፡ በመጨረሻም፣ ይህ ኮድ ከጥበቃ ጋር የተዛመደ ስለሆነ፣ በስልጠናው ውስጥ ካሉ ሌሎች ልምምዶች መፍትሄዎች በተቃረነ መልኩ፣ ለወደፊቱ በኮድ ዝርዝሮች እና በማሳያ አፕልኬሽኑ ውስጥ ይካተታል፡፡
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
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
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
ባለፉት ሶስት ምዕራፎች ውስጥ፣ ተስፋ ሰጪ ነገር ግን በቅጡ ያልተስተካከለ አፕልኬሽንን፣ ወደ ሙሉ የመመዝገቢያ እና የመግቢያ አገልግሎቶችን ወደሚያቀርብ አንድ ጣቢያ በመለወጥ ሂደት ውስጥ፣ ብዙ ነገሮችን አሟልተናል፡፡ ሁሉንም የማረጋገጫ ተግባር ለማጠናቀቅ የሚያስፈልገው፣ በግብዓት ሁኔታ እና በተጠቃሚ ማንነት ላይ በመመርኮዝ፣ ተጠቃሚው የማይመለከተውን ገጽ እንዳይደርስ መገደብ ሲሆን፤ ተጠቃሚዎች መረጃቸውን የሚያርሙበትን አንድ ችሎታ በማቅረብ ሂደት ውስጥ ይህንን ተግባር እናከናውናለን፤ ይህንን ከግብ ማድረሱ ደግሞ የምዕራፍ 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)። (ካሁን ወዲያ ስለዚህ ሂደት አንነጋገርም፣ ቢያንስ አንድ ጊዜ ይህንን ነገር ለናንተ ማሳየቱ ግን ጥሩ ነው።) ለተጨማሪ መረጃ የሃረኩ ሰነድ ላይ የስህተት ገጾች የሚለው ላይ መመልከት ትችላላችሁ፡፡
cookies
) ዘዴ አማካይነት፣ ቋሚ ብስኩቶችን በመጠቀም ከአንድ ገጽ ወደ ሌላው ገጽ ሁኔታን ጠብቆ ማቆየት እንደሚችል፣
cookies
) ዘዴን በመጠቀም፣ በአሳሹ ላይ አንድ የቋሚ ዝክረ ይስሙላ ብስኩትን በማስቀመጥ አንድ ቋሚ ክፍለጊዜን እንደፈጠርን፣
has_secure_token
) የተባለ ዘዴ አስተዋውቋል፣ ይህ ዘዴ ያመነጫቸውን ይስሙላወች ሳይከትፍ ዋጋቸውን በቀጥታ በውሂበጎታ ውስጥ ያስቀምጣል፣ ስለሆነም ለአሁኑ ዓላማችን ተስማሚ አይደለም፡፡10. ክቡር አንባቢ ጃክ ፋህኔቶክ፣ በአፕልኬሽኑ ላይ፣ አሁን ባለው ንድፍ ውስጥ ያልተካተተ አንድ (የጠርዝ ጉዳይ) እንዳለ ልብ ብለዋል:-
zkre_fech
) ውስጥ ማስቀመጥ)።
zkre_fech
) ውስጥ ማስቀመጥ፣ ይህም በአሳሽ ሀ ውስጥ የተቀመጠውን ዝክረ ይስሙላ ሀ ይተካል)።
ahun_teteqami
) ዘዴ ለመግባት)።
geb_tual?
) ሃሰትን ይመልሳል)።
ምንም እንኳን ይህ ተጠቃሚን በበርካታ ቦታዎች ከመዘከር የበለጠ አንድ ጥብቅ ንድፍ ቢሆንም፣ ተጠቃሚዎች ከአንድ አሳሽ በላይ፣ ላይ በቋሚነት ሊዘከሩ ይችላሉ የሚለውን ተስፋ ይጥሳል። መፍትሄው ከአሁኑ ንድፍ እጅግ በጣም የተወሳሰበ ነው፤ እያንዳንዱ አምድ አንድ የተጠቃሚ-መታወቂያ እና ፈጪ ያለው አንድ የተለለየ ሰንጠረዥ ውስጥ ዝክረ ፈጪውን እንዲገባ ማድረግ ነው፡፡ ከዚያ የአሁኑተጠቃሚን ለመፈተሽ፣ አንድ የተለየ ዝክረ ይስሙላ ጋር የሚጎዳኝ አንድ ፍጪን በሰንጠረዡ በኩል መመልከት ይሆናል፡፡ በተጨማሪም፣ በዝርዝር 9.11 ውስጥ ያለው የ‘እርሳ (ersa
) ዘዴ፣ ከአሁን አሳሽ ፍጪ ጋር የሚጎዳኘውን አምድ ብቻ ይሰርዛል። ለጥበቃ ሲባል ዘግቶ መውጣት ለዚያ ተጠቃሚ ሁሉንም ፍጪወች ያስወግዳል፡፡
zekr teteqami
) ዘዴን ያለ ቅንፍ አስቀምጠነው ነበር፣ በሶስቲት ስሌት ሲጻፍ ግን፣ የ‘ተጠቃሚ (teteqami
) ቁሱ ግዴታ በቅንፍ ውስጥ መግባት አለበት፤ ካለበለዚያ ግን አንድ የአገባብ ስህተትን ያስከትላል፡፡