ዋናውን የማሳያ አፕልኬሽን በማበልጸግ ሂደት ውስጥ፣ እስከ አሁን ድረስ አራት ሃብቶችን ማለት የተጠቃሚዎች፣ የክፍለጊዜዎች፣ የመለያ ማግበርያዎች እና የመሕለፈቃል ዳግም ማስጀመርያዎች ሃብቶችን አግኝተናል፣ ነገር ግን ከእነዚህ ሁሉ የመጀመሪያው ብቻ አንድ በንቅ መዝገብ ቅርጸት የተደገፈ አንድ የውሂበጎታ ሰንጠረዥ አለው። አሁን ከመጀመሪያው ሃብት ጋር አንድ አይነት የሆነ አንድ ሃብትን ወደ አፕልኬሽናችን የምናክልበት የመጨረሻው ጊዜ መጥቷል፤ እሱም የተጠቃሚ አጪርጽሑፎች ይባላል፣ እነዚህ የተጠቃሚ፣ አጪርጽሑፎችም፣ ከአንድ የተወሰነ ተጠቃሚ ጋር የተዛመዱ አጫጪር መልዕክቶች ናቸው።1 ለመጀመሪያ ጊዜ በምዕራፍ 2 ውስጥ አጪርጽሑፎችን ገና እንጪጪ እያሉ የተመለከትን ሲሆን፣ በዚህ ምዕራፍ ውስጥ ግን የአጪርጽሑፍ የውሂብ ቅድን በመገንባት፣ ብዙ_አለው (has_many
) እና ባለቤት_ነው (belongs_to
) ነው የተባሉ ዘዴወችን ተጠቅመን፣ ከተጠቃሚ ቅርጸቱ ጋር በማዛመድ በክፍል 2.3 ላይ የተነደፉትን እንጪጪ አጪርጽሑፎች ወደ ተሟላ ንድፍ እንቀይራቸዋለን፣ ከዚያ ውጤቶቹን ለማንቀሳቀስ እና ለማሳየት የሚያስፈልጉትን ቅጾች እና ከፊሎች እንሰራለን (እንዲሁም በክፍል 13.4 ላይ የምስሎች ሰቀላን እናካትታለን)፡፡ በምዕራፍ 14 ላይ፣ የነሱን አንድ የአጪርጽሑፎች ቀላቢ ይቀበሉ ዘንድ፣ ተጠቃሚዎችን የመከተል ሃሳብን በማከል ትንሿን የትዊተር መንትያችንን እናጠናቅቃለን።
የአጪርጽሑፎችን አስፈላጊ ባህሪያት የሚይዝ አንድ የአጪርጽሑፍ ቅርጸትን በመፍጠር፣ የአጪርጽሑፎች ሃብትን እንጀምራለን፡፡ ልክ በክፍል 2.3 ላይ እንደገነባነው ቅርጸት፣ አዲሱ የአጪርጽሑፍ ቅርጸታችን የውሂብ ማረጋገጫዎችን እና ከተጠቃሚ ቅርጸቱ ጋር ህብረትን የሚፈጥር አንድ ማሕበርን ያካትታል፡፡ ከእዚያ ቅርጸት በተለየ መልኩ፣ የአሁኑ የአጪርጽሑፍ ቅርጸት ሙሉ በሙሉ የፈተናል፤ እንዲሁም አንድ ነባሪ ቅደም ተከተል እና የነሱ ወላጅ ተጠቃሚ ከተደመሰሰ፣ የቲሞቹን በራስሰር የሚያጠፋ ባህሪ ይኖረዋል።
ጊትን ለስሪት ቁጥጥር እየተጠቀማችሁ ከሆነ፣ በዚህ ጊዜ አንድ የርእስ ቅርንጫፍ እንድትፈጥሩ ሃሳቤን አቀርባለሁ:-
$ git checkout -b የተጠቃሚ-አጪርጽሑፎች
የአጪርጽሑፍ ቅርጸቱ ሁለት ባሕሪያዎችን ብቻ ይፈልጋል፣ እነሱም የአጪርጽሑፍ ይዘቱን የሚይዝ አንድ ይዘት (yizet
) የተባለ ባሕሪ እና አንድ አጪርጽሑፍን ከአንድ የተወሰነ ተጠቃሚ ጋር ለማገናኘት የሚያገለግል አንድ የ‘ተጠቃሚ_መታወቂያ (teteqami_id
) የተባለ ባሕሪዎች ናቸው። ይህን በአንድ ላይ የመቋጨቱ ውጤት በምስል 13.1 ላይ የሚታየውን አንድ የአጪርጽሑፍ ቅርጸትን ከመዋቅሩ ጋር ይሰጣል፡፡
በምስል 13.1 ውስጥ ያለው የውሂብ ቅርጸት ለአጪርጽሑፍ ይዞታ በ‘ሃረግ (string
) ፈንታ የ‘ጽሑፍ (text
) የውሂብ ዓይነትን እንደሚጠቀም ማስተዋሉ ተገቢ ነው፣ ይህም ወሰን የለሽ ጽሑፍን ማከማቸት ይችላል፡፡ ምንም እንኳ የአጪርጽሑፍ ይዘቱ ከ 140 ሆሄወች ያነሰ እንዲሆን ቢደረግም (ክፍል 13.1.2) እናም 255 ሆሄወችን በሚይዘው የ‘ሃረግ (string
) ውሂብ ውስጥ ማከማቸት ቢቻልም፣ የ‘ጽሑፍ (text
) የውሂብ ዓይነትን መጠቀሙ ግን የአጪርጽሑፎችን ባህሪ በተሻለ ሁኔታ ይገልጻል፣ አጪርጽሑፎቹም በተፈጥሮ ልክ እንደ ጽሑፍ ጥምሮች ተደርገው ይታሰባሉ። በእርግጥ፣ በክፍል 13.3.2 ውስጥ አጪርጽሑፎችን ለማስረከብ ከአንድ መስክ ይልቅ አንድ የጽሑፍ ቦታን
እንጠቀማለን፡፡ በተጨማሪም፣ የ‘ጽሑፍ (text
) የውሂብ ዓይነትን መጠቀሙ፣ ለወደፊቱ የአጪርጽሑፉን የእርዝመት ገደብ መጨመር ብንፈልግ፣ ልባችን የፈቀደውን እንድናደርግ እድሉን ይሰጠናል (ለምሳሌ:- ይህንኑ አፕልኬሽን የተለያዩ ቛንቛወችን እንዲደግፍ ከተፈለገ እንዲሁ ማድረግ ይቻላል)። በመጨረሻም፣ በምርት ወቅት በአፕልኬሽናችን ላይ የጽሑፍ (text
) የውሂብ ዓይነትን መጠቀሙ፣ በአፕልኬሽናችን አሰራር ላይ ምንም ልዩነት አያመጣም፣ ስለሆነም እሱን እዚህ ላይ በመጠቀማችን ምክንያት ምንም የምንከስረው ነገር የለም ማለት ነው፡፡2
ልክ የተጠቃሚ ቅርጸትን (ዝርዝር 6.1) ለማመንጨት የቅርጸት-አመንጪ (generate model
) ትእዛዝን እንደተጠቀምን ሁሉ፣ የአጪርጽሑፍ ቅርጸቱን ለማመንጨትም ይህንኑ ትእዛዝ እንጠቀማለን (ዝርዝር 13.1)።
$ rails generate model Achrtshuf yizet:text teteqami:references
ይህ ፍልሰት በዝርዝር 13.2 ላይ ለተመለከተው የአጪርጽሑፍ ቅርጸት መፈጠር ምክንያት ሆኗል፡፡ እንደተለመደው ከ‘አፕልኬሽንመዝገብ (ApplicationRecord
) ውርስ በተጨማሪ (ክፍል 6.1.2)፣ የመነጨው ቅርጸት፣ ተጠቃሚው የአጪርጽሑፉ ባለቤት መሆኑን የሚያመለክት አንድ ባለቤት_ነው (belongs_to
) የተባለ ዘዴን ያካትታል፣ ይህም በዝርዝር 13.1 ውስጥ ባለው በ‘ተጠቃሚን:ያጣቅሳል (teteqami:references
) ነጋሪአሴት ምክንያት የተካተተ ነው፡፡ የዚህን ኮድ አንድምታ በክፍል 13.1.3 ላይ እንቃኛለን፡፡
app/models/achrtshuf.rb
class Achrtshuf < ApplicationRecord
belongs_to :teteqami
end
በዝርዝር 13.1 ውስጥ ያለው የ‘አመንጪ (generate
) ትእዛዝ በውሂበጎታው ውስጥ አንድ የ‘አጪርጽሑፎች (achrtshufs
) ሰንጠረዥን ለመፍጠር የሚያገለግል አንድ ፍልሰትን ይፈጥራል (ዝርዝር 13.3)፤ ይህንን ዝርዝር 6.2 ላይ ካለው የ‘ተጠቃሚዎች (teteqamis
) ሰንጠረዥ ፍልሰት ጋር ብናነጻጽር አንድ የምናየው ትልቅ ልዩነት የ‘ማጣቀሻወች (references
) ዘዴ አጠቃቀም ላይ ነው፤ ይህም በተጠቃሚ እና በአጪርጽሑፍ ማህበር ውስጥ ጥቅም ላይ የሚውል አንድ የ‘ተጠቃሚ-መታወቂያ (teteqami_id
) ረድፍን (ከአንድ መረጃ-ጠቋሚ እና ከአንድ የውጪ ቁልፍ ማጣቀሻ3 ጋር) በውሂበጎታው ላይ በራስሰር ማከሉ ነው። ልክ እንደ Teteqami ቅርጸት ፍልሰት፣ የአጪርጽሑፎች (Achrtshufs) ቅርጸት ፍልሰትም (በክፍል 6.1.1 እንደተጠቀሰው) በምስል 13.1 ላይ የሚታየውን የተፈጠረ_በ (created_at
) እና የተዘመነ_በ (updated_at
) አስማታዊ ረድፎችን የሚያክለውን የሰንጠረዥ.ማህተመጊዜ (t.timestamps
) ኮድን በራስሰር ያካትታል፡፡ (በክፍል 13.1.4 ላይ የ‘ተፈጠረ_በ (created_at
) ረድፍን በስራ ላይ እናውለዋለን፡፡)
db/migrate/[ማህተመጊዜ]_create_achrtshufs.rb
class CreateAchrtshufs < ActiveRecord::Migration[6.1]
def change
create_table :achrtshufs do |t|
t.text :yizet
t.references :teteqami, null: false, foreign_key: true
t.timestamps
end
add_index :achrtshufs, [:teteqami_id, :created_at]
end
end
ከአንድ ከተሰጠ የተጠቃሚ-መታወቂያ ጋር የተዛመዱትን ሁሉንም አጪርጽሑፎች በተገላቢጦሽ ቅደም ተከተል ፈልገን እናወጣለን ብለን ስለምንጠብቅ፣ ዝርዝር 13.3 በ‘ተጠቃሚ-መታወቂያ (teteqami_id
) እና ተፈጠረ_በ (created_at
) መስኮች ላይ አንድ የመረጃ-ጠቋሚን አክሏል (ሳጥን 6.2)፡፡
add_index :achrtshufs, [:teteqami_id, :created_at]
ሁለቱንም ማለት የ‘ተጠቃሚ_መታወቂያ‘ን (teteqami_id
) እና የ‘ተፈጠረ_በ (created_at
) መስኮችን ልክ እንደ እንደ ድርድር በማካተት፣ ሬይልስን በርካታ የመረጃ-ጠቋሚ ቁልፎችን እንዲፈጥር ማዘጋጀት እንችላለን፤ ይህ ማለትም ንቅ መዝገብ ሁለቱንም ቁልፎች በአንድ ጊዜ ይጠቀማል ማለት ነው፡፡
በዝርዝር 13.3 ውስጥ ባለው ፍልሰት፣ እንደተለመደው አድርገን ውሂበጎታውን ማዘመን እንችላለን:-
$ rails db:migrate
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
Achrtshuf.new
) ዘዴን በመጠቀም፣ አንድ አጪርጽሑፍ
የተባለ አዲስ የአጪርጽሑፍ ቁስን ቀርጹ እና ይዘቱን በ “አሳ በልቶ ውሃ” እና የተጠቃሚ-መታወቂያውን ደግሞ ከውሂበጎታው ውስጥ ያለውን የመጀመሪያ ተጠቃሚ ዋጋን ስጡት። የ‘ተፈጠረ_በ (created_at
) እና የ‘ተዘመነ_በ (updated_at
) መስክ ዋጋወች ምንድናቸው?
አጪርጽሑፍ.teteqami
እና የ‘ አጪርጽሑፍ.teteqami.sim
ዋጋወች ምንድናቸው?
አሁን መሰረታዊውን ቅርጸት ፈጥረናል፣ የተፈለጉትን የእገዳ ንድፎች ለማስፈጸም፣ የተወሰኑ ማረጋገጫዎችን እንጨምራለን፡፡ በአጪርጽሑፍ ቅርጸቱ ውስጥ አስፈላጊ ከሆኑት ገጽታዎች ውስጥ አንዱ፣ የትኛው ተጠቃሚ አጪርጽሑፉን እንደፈጠረው ለማወቅ የሚያገለግለው፣ አንድ የተጠቃሚ-መታወቂያ መኖሩ ነው፡፡ ይህንን ስነአጻጻፉ/ስነአነጋገሩ ትክክለኛ በሆነ መንገድ ለመስራት በክፍል 13.1.3 ላይ ተግባራዊ የምናደርገውን የንቅ መዝገብ ማህበሮችን (Associations) በመጠቀም ይሆናል፣ አሁን ግን በ‘አጪርጽሑፍ (Achrtshuf
) ቅርጸቱ ላይ በቀጥታ እንሰራለን።
የመጀመሪያወቹ የአጪርጽሑፉ ፈተናወች፣ ከተጠቃሚ ቅርጸት ፈተናወቹ ጋር ትይዩዎች ናቸው (ዝርዝር 6.7)፡፡ በ‘አዘጋጅ (setup
) ዘዴ ውስጥ፣ አንድ አዲስ አጪርጽሑፍ በመፍጠር ከአንድ ብቁ የእቃ ተጠቃሚ ጋር እናዛምድ እና፣ ከዚያ ውጤቱ ብቁ መሆኑን እንፈትሻለን፡፡ እያንዳንዱ አጪርጽሑፍ የተጠቃሚ-መታወቂያ ሊኖረው ስለሚገባ፣ የ‘ተጠቃሚ_መታወቂያ (teteqami_id
) መኖሩን ለማረጋገጥ፣ አንድ የመኖር ማረጋገጫ ፈተናን እናክላለን፡፡ እነዚህን ነገሮች በአንድ ላይ አሰባስቦ ማሰናዳቱ፣ በዝርዝር 13.4 ውስጥ ያለውን ፈተና ያስገኛል፡፡
test/models/achrtshuf_test.rb
require "test_helper"
class AchrtshufTest < ActiveSupport::TestCase
def setup
@teteqami = teteqamis(:michael)
# ይህ ኮድ በስነአጻጻፉ/በስነአነጋገሩ ትክክል አይደለም፡፡
@achrtshuf = Achrtshuf.new(yizet: "አሳ በልቶ ውሃ", teteqami_id: @teteqami.id)
end
test "ብቁ መሆን አለበት" do
assert @achrtshuf.valid?
end
test "የተጠቃሚ-መታወቂያ መኖር አለበት" do
@achrtshuf.teteqami_id = nil
assert_not @achrtshuf.valid?
end
end
በ‘አዘጋጅ (setup
) ዘዴ ውስጥ ባለው አስተያየት ላይ እንደተመለከተው፣ አጪርጽሑፍን ለመፍጠር የተጠቀምንበት ኮድ ስነአጻጻፉ/ስነአነጋገሩ ትክክለኛ አይደለም፣ ይህንንም በክፍል 13.1.3 ላይ እናስተካክለዋለን፡፡
ልክ እንደ መጀመሪያው የተጠቃሚ ቅርጸት ፈተና (ዝርዝር 6.5)፣ በዝርዝር 13.4 ውስጥ ያለው የመጀመሪያ ፈተና የእውነታ ማረጋገጫ ብቻ ሲሆን፣ የሁለተኛው ፈተና ግን የተጠቃሚው መታወቂያ መኖሩን የሚፈትን ነው፣ ለዚህም በዝርዝር 13.5 ውስጥ የሚታየውን የመኖር ማረጋገጫን እናክላለን፡፡
teteqami_id
) መኖሩን ማረጋገጥ። አረንጓዴ app/models/achrtshuf.rb
class Achrtshuf < ApplicationRecord
belongs_to :teteqami
validates :teteqami_id, presence: true
end
በነገራችን ላይ፣ ከአምስተኛው የሬይልስ እትም ጀምሮ በዝርዝር 13.4 ውስጥ ያሉ ፈተናዎች በርግጥ ያለ ዝርዝር 13.5 ማረጋገጫ ያልፋሉ፣ ይህ የሚሆነው ግን በዝርዝር 13.4 ውስጥ ስነአጻጻፉ/ስነአነጋገሩ ትክክለኛ ያልሆነውን በደማቅ ቀለም የተሰመረበት ኮድን ስትጠቀሙ ብቻ መሆኑን ልትገነዘቡ ይገባል፡፡ በዝርዝር 13.12 ላይ ስነአጻጻፉ/ስነአነጋገሩ ትክክለኛ ወደሆነ ኮድ ከተቀየረ በኋላ፣ የተጠቃሚ-መታወቂያ ማረጋገጫ አስፈላጊ ስለሆነ፣ እኛም ያንን ለማመቻቸት ስንል እዚህ ጋር አክለነዋል፡፡
በዝርዝር 13.5 ውስጥ ካለው ኮድ ጋር ፈተናዎቹ (አሁንም) አረንጓዴመሆን አለባቸው:-
$ rails test:models
በመቀጠል፣ (የክፍል 2.3.2 ምሳሌን በመከተል) ለአጪርጽሑፍ የ‘ይዘት (yizet
) ባሕሪ ማረጋገጫዎችን እናክላለን፡፡ ልክ እንደ ተጠቃሚ_መታወቂያ‘ው (teteqami_id
) ሁሉ የ‘ይዘት (yizet
) ባሕሪውም ግዴታ መኖር አለበት፣ ከ 140 ሆሄወች የበለጠ እንዳይሆንም ይገደባል፣ ይህ ባህሪም አጪር ለሆነ መጣጥፍነት ማለት አጪርጽሑፍነት ብቁ እንዲሆን ያበቃዋል፡፡
የተጠቃሚ ቅርጸት ማረጋገጫዎች ላይ እንዳደረግነው ሁሉ (ክፍል 6.2)፣ የአጪርጽሑፍ ይዘት ማረጋገጫዎችን ለማከልም ፈተና-መሬ ብልጸጋን እንጠቀማለን። በዝርዝር 13.7 ላይ እንደሚታየው፣ የተገኙት የፈተና ውጤቶች በአጠቃላይ የተጠቃሚ ቅርጸት ማረጋገጫ ፈተናዎች ምሳሌዎችን ይከተላሉ፡፡
test/models/achrtshuf_test.rb
require "test_helper"
class AchrtshufTest < ActiveSupport::TestCase
def setup
@teteqami = teteqamis(:michael)
@achrtshuf = Achrtshuf.new(yizet: "አሳ በልቶ ውሃ", teteqami_id: @teteqami.id)
end
test "ብቁ መሆን አለበት" do
assert @achrtshuf.valid?
end
test "የተጠቃሚ-መታወቂያ መኖር አለበት" do
@achrtshuf.teteqami_id = nil
assert_not @achrtshuf.valid?
end
test "ይዘት መኖር አለበት" do
@achrtshuf.yizet = " "
assert_not @achrtshuf.valid?
end
test "ይዘት ቢበዛ 140 ሆሄወች መሆን አለበት" do
@achrtshuf.yizet = "ሀ" * 141
assert_not @achrtshuf.valid?
end
end
ልክ እንደ ክፍል 6.2 ዝርዝር 13.7 ውስጥ ያለው ኮድም፣ የአጪርጽሑፍ እርዝመት ማረጋገጫውን ለመፈተን የሃረግ ማባዛትን ይጠቀማል:-
$ rails console
>> "ነ" * 10
=> "ነነነነነነነነነነ"
>> "ነ" * 141
=> "ነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነ
ነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነነ"
በዝርዝር 13.8 ላይ እንደሚታየው፡ ይህ ኮድ ከተጠቃሚዎች የ‘ስም (sim
) ማረጋገጫ ኮድ ጋር በጣም ተመሳሳይ ነው (ዝርዝር 6.16)፡፡
app/models/achrtshuf.rb
class Achrtshuf < ApplicationRecord
belongs_to :teteqami
validates :teteqami_id, presence: true
validates :yizet, presence: true, length: { maximum: 140 }
end
በዚህ ጊዜ፣ የፈተና ስብስቡ ሙሉ በሙሉ አረንጓዴመሆን አለበት:-
$ rails test
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
ለድር አፕልኬሽኖች የውሂብ ቅዶችን በሚሰሩበት ጊዜ፣ በእያንዳንዱ ቅርጸት መካከል ማሕበር እንዲኖር ማድረጉ በጣም አስፈላጊ ነው፡፡ አሁን ባለበት ሁኔታ እያንዳንዱ አጪርጽሑፍ ከአንድ ተጠቃሚ ጋር የተዛመደ ሲሆን፣ እያንዳንዱ ተጠቃሚ ደግሞ ከበርካታ አጪርጽሑፎች ጋር ይዛመዳል፣ ይህንን ትስስርም በክፍል 2.3.3 ላይ በግልጽ አይተነዋል፣ አሁን ደግሞ በምስል 13.2 እና በምስል 13.3 ላይ በንድፋዊ መልኩ ይታያል። እነዚህን ማሕበሮች ተግባር ላይ ለማዋል በምናደርገው ሂደት ላይ፣ ለአጪርጽሑፍ ቅርጸቱ አንዳንድ ፈተናዎችን ስንጽፍ፣ በተጠቃሚ ቅርጸቱ ላይ ደግሞ አንዳንድ ፈተናዎችን እናክላለን፡፡
በዚህ ክፍል ውስጥ የተበየነውን የ‘ባለቤት_ነው (belongs_to
) እና የ‘ብዙ_አለው (has_many
) ማሕበርን በመጠቀም፣ ሬይልስ በሰንጠረዥ 13.1 ላይ የተመለከቱትን ዘዴወች ይገነባል፡፡ ይህንን ዘዴ እንደዚህ አድርጎ ከመጠቀም:-
Achrtshuf.create
Achrtshuf.create!
Achrtshuf.new
በሰንጠረዥ 13.1 ላይ ያለውን ዘዴ ስራ ላይ በማዋል፤ እንደዚህ አድርገን የመጠቀም ችሎታን ማግኘት እንደምንችል አስተውሉ:-
teteqami.achrtshufs.create
teteqami.achrtshufs.create!
teteqami.achrtshufs.build
እነዚህ የኋለኞቹ ዘዴወች፣ በአንድ ተጠቃሚ ማሕበር በኩል (through) አንድ አጪርጽሑፍን ለመስራት፣ ስነአጻጻፉ/ስነአነጋገሩ ትክክለኛ የሆነውን መንገድ ያስማማሉ፡፡ በዚህ መንገድ አንድ አዲስ አጪርጽሑፍ ሲሰራ፣ የ‘ተጠቃሚ_መታወቂያ‘ው (teteqami_id
) ከተዛማጁ አጪርጽሑፍ ጋር በራስሰር ይዘጋጃል። ስለዚህ በዝርዝር 13.4 ላይ ያለውን የ‘ተጠቃሚ_መታወቂያ (teteqami_id
) በማጥፋት:-
@teteqami = teteqamis(:michael)
# ይህ ኮድ በስነአጻጻፉ/በስነአነጋገሩ ትክክል አይደለም፡፡
@achrtshuf = Achrtshuf.new(yizet: "አሳ በልቶ ውሃ", teteqami_id: @teteqami.id)
በዚህ ኮድ መተካት እንችላለን:-
@teteqami = teteqamis(:michael)
@achrtshuf = @teteqami.achrtshufs.build(yizet: "አሳ በልቶ ውሃ")
(ልክ እንደ አዲስ (new
) ዘዴ የ‘ገንባ (build
) ዘዴም፣ አንድ ቁስን በማህደረ-ትውስታ (Memory) ላይ ፈጥሮ ይመልሳል፣ ይሁን እንጂ ውሂበጎታውን ጪራሽ አይቀይርም።)4 ተገቢወቹን ማሕበሮች ከበየንን በኋላ፣ የሚገኘው የ‘@አጪርጽሑፍ (@achrtshuf
) ተለዋዋጪ፣ ከተዛማጁ ተጠቃሚ-መታወቂያ ጋር እኩል የሆነ አንድ የ‘ተጠቃሚ_መታወቂያ (teteqami_id
) በራስሰር ይኖረዋል። ይህ በኮድ ሲጻፍ ምን እንደሚመስል በአጪር ጊዜ የምናየው ይሆናል።
ዘዴ | ጥቅም |
achrtshuf.teteqami |
ከአጪርጽሑፉ ጋር የሚዛመደውን የተጠቃሚ ቁስ መመለስ |
teteqami.achrtshufs |
የተጠቃሚውን የአጪርጽሑፎች ክምችት መመለስ |
teteqami.achrtshufs.create(arg) |
ከተጠቃሚው (teteqami ) ጋር የተዛመደ አንድ አጪርጽሑፍን መፍጠር |
teteqami.achrtshufs.create!(arg) |
ከተጠቃሚው (teteqami ) ጋር የተዛመደ አንድ አጪርጽሑፍን መፍጠር (በውድቀት ጊዜ ልዩነትን ያስነሳል) |
teteqami.achrtshufs.build(arg) |
ከተጠቃሚው (teteqami ) ጋር የተዛመደ አንድ አዲስ የአጪርጽሑፍ ቁስን መመለስ |
teteqami.achrtshufs.find_by(id: 1) |
የአጪርጽሑፉ መታወቂያው 1 ፣ እና የ‘ተጠቃሚ-መታወቂያው (teteqami.id ) ከ‘ተጠቃሚ_መታወቂያ‘ው (teteqami_id ) ጋር እኩል የሆነ አጪርጽሑፍን መፈለግ |
ልክ እንደ @ተጠቃሚ.አጪርጽሑፎችን.ገንባ (@teteqami.achrtshufs.build
) ያለው ኮድ እንዲሰራ ለማድረግ፣ ማለት የተጠቃሚ እና የአጪርጽሑፍ ቅርጸቱን ለማዛመድ፣ እነሱን በኮድ ማዘመን ይኖርብናል፡፡ በዝርዝር 13.10 ላይ እንደሚታየው፣ ከነዚህ ውስጥ የመጀመሪያው፣ ማለት ባለቤት_ነው :ተጠቃሚ (belongs_to :teteqami
) የተባለው ኮድ፣ በዝርዝር 13.3 ውስጥ ባለው ፍልሰት በኩል በራስሰር ተካቷል፡፡ ሁለተኛውን ማሕበር ማለት ብዙ_አለው :አጪርጽሑፎች‘ን
(has_many :achrtshufs
) ደግሞ በዝርዝር 13.11 ላይ እንደሚታየው፣ እኛው እራሳችን በእጃችን ማከል ይኖርብናል፡፡
belongs_to
)፡፡ አረንጓዴ app/models/achrtshuf.rb
class Achrtshuf < ApplicationRecord
belongs_to :teteqami
validates :teteqami_id, presence: true
validates :yizet, presence: true, length: { maximum: 140 }
end
has_many
) አጪርጽሑፎች አሉት፡፡ አረንጓዴ app/models/teteqami.rb
class Teteqami < ApplicationRecord
has_many :achrtshufs
.
.
.
end
በዝርዝር 13.12 ላይ እንደሚታየው፣ በሁለቱ መካከል ያለው ማሕበር ከተመሰረተ በኋላ፣ አንድ አዲስ አጪርጽሑፍን ለመገንባት ስነአጻጻፉ/ስነአነጋገሩ ትክክለኛ የሆነውን መንገድ በመከተል፣ በዝርዝር 13.4 ውስጥ ያለውን የ‘አዘጋጅ (setup
) ዘዴ ማዘመን እንችላለን።
test/models/achrtshuf_test.rb
require "test_helper"
class AchrtshufTest < ActiveSupport::TestCase
def setup
@teteqami = teteqamis(:michael)
@achrtshuf = @teteqami.achrtshufs.build(yizet: "አሳ በልቶ ውሃ")
end
test "ብቁ መሆን አለበት" do
assert @achrtshuf.valid?
end
test "የተጠቃሚ-መታወቂያ መኖር አለበት" do
@achrtshuf.teteqami_id = nil
assert_not @achrtshuf.valid?
end
.
.
.
end
በእርግጥ፣ ከዚህ ትንሽ የኮድ ማጣራት ስራ በኋላም፣ የፈተና ስብስቡ አረንጓዴመሆን ይኖርበታል:-
$ rails test
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
ተጠቃሚ
ሰይሙ። ይህንን:- achrtshuf = ተጠቃሚ.achrtshufs.create(yizet: "አሳ በልቶ ውሃ")
ትእዛዝ ስትፈጽሙ ምን ተፈጠረ?
ተጠቃሚ.achrtshufs.find(achrtshuf.id)
ትእዛዝ በማስኬድ አረጋግጡ፡፡ በ‘አጪርጽሑፍ.መታወቂያ (achrtshuf.id
) ፈንታ አጪርጽሑፍ‘ን (achrtshuf
) ብትጠቀሙስ?
ተጠቃሚ == achrtshuf.ተጠቃሚ
ውጤት/ዋጋ ምንድነው? የዚህ ኮድ:- ተጠቃሚ.achrltfs.first == achrtshuf
ውጤትስ/ዋጋስ?
በዚህ ክፍል ውስጥ የተጠቃሚ/የአጪርጽሑፍ ማሕበር ላይ አስፈላጊ የሆኑ ሁለት ማጣሪያዎችን እናክላለን። በተለይም፣ የአንድ ተጠቃሚ አጪርጽሑፎች በአንድ የተወሰነ ቅደም ተከተል ተፈልገው እንዲወጡ እናዘጋጃቸዋለን፣ እንዲሁም ከአጪርጽሑፎቹ ጋር ተዛማጁ ተጠቃሚ፣ ከውሂበጎታው ሲጠፋ አጪርጽሑፎቹም በራስሰር አብረው ይጠፉ ዘንድ፣ አጪርጽሑፎቹን የተጠቃሚዎቹ ጥገኛ (Dependent) እናደርጋቸዋለን።
በነባሪነት የ‘ተጠቃሚ.አጪርጽሑፎች (teteqami.achrtshufs
) ዘዴው ስለ ቅምጦቹ ቅደም ተከተል ምንም ዓይነት ዋስትናን አይሰጥም፤ ይሁን እንጂ አጪርጽሑፎቹ ከተፈጠሩ በኋላ፣ (የብሎጎችና የትዊተር ደንብን በመከተል) በተገላቢጦሽ ቅድም ተከተል ከውሂበጎታው እንዲወጡ እንፈልጋለን፡፡5 ስለሆነም፣ ወቅታዊው ቅምጥ መጀመሪያ ላይ መሆን አለበት ማለት ነው፡፡ ይህንን አሰራር ተግባራዊ ለማድረግ አንድ ነባሪ ክልልን እናዘጋጃለን።
ይህ በትክክል ወደ አንድ አታላይ የፈተና እልፈት ሊያመራ የሚችል ገጸባህሪ ስለሆነ (ማለትም የአፕልኬሽን ኮዱ የተሳሳተ ቢሆንም እንኳ የሚያልፍ ፈተና ነው)፣ ስለሆነም፣ ትክክለኛውን ነገር እየፈተን መሆናችንን ለማረጋገጥ፣ ፈተና-መሬ ብልጸጋን መጠቀሙን እንቀጥላለን። በዝርዝር 13.14 ላይ እንደሚታየው በተለይ ደግሞ፣ በውሂበጎታ ውስጥ ያለው የመጀመሪያው አጪርጽሑፍ የቅርብ_ጊዜ (yeqrb_gizei
) ብለን ከምንጠራው አንድ የእቃ አጪርጽሑፍ ጋር አንድ ዓይነት እንደሆነ ለማረጋገጥ አንድ ፈተናን እንጽፋለን፡፡
test/models/achrtshuf_test.rb
require "test_helper"
class AchrtshufTest < ActiveSupport::TestCase
.
.
.
test "ቅደም ተከተሉ ወቅታዊው በመጀመሪያ መሆን አለበት" do
assert_equal achrtshufs(:yeqrb_gizei), Achrtshuf.first
end
end
ዝርዝር 13.14 የአጪርጽሑፍ እቃወች መኖር ላይ ጥገኛ ነው፤ ይህንንም በዝርዝር 11.5 ላይ እንደታየው፣ ልክ የተጠቃሚ እቃዎችን እንደበየነው አድርገን ልንበይነው እንችላለን። በክፍል 13.1.1 ላይ ከተበየነው የ‘ይዘት (yizet
) ባሕሪ በተጨማሪ፣ ከይዘቱ ጋር የሚዛመድ አንድ ተጠቃሚ‘ንም (teteqami
) መበየን ይኖርብናል፡፡ ሬይልስም እቃዎች ውስጥ ማሕበርን ለመገንባት ይህንን የመሰለ አንድ መንገድን በሚመች ሁኔታ አካቷል:-
weba:
yizet: "ወባ ፊት የነሳው ሰውየ ቡዳ እንዳይበላኝ አለ።"
created_at: <%= 10.minutes.ago %>
teteqami: michael
ተጠቃሚውን (teteqami
) ማይክል (michael
) ብለን በማስተዋወቅ፣ ሬይልስ ይህንን አጪርጽሑፍ ከተጠቃሚዎች እቃ ውስጥ ካለው ተጓዳኝ ተጠቃሚ ጋር እንዲያዛምድ እንነግረዋለን:-
michael:
sim: Micheal Abnet
emelekt: michael@misalei.com
.
.
.
የተሟሉት የአጪርጽሑፉ እቃወች በዝርዝር 13.15 ላይ ይታያሉ፡፡
test/fixtures/achrtshufs.yml
weba:
yizet: "ወባ ፊት የነሳው ሰውየ ቡዳ እንዳይበላኝ አለ።"
created_at: <%= 10.minutes.ago %>
teteqami: michael
tau_manifesto:
yizet: "በ @mhartl የ @tauday ጣቢያን ተመልከቱ https://tauday.com"
created_at: <%= 3.years.ago %>
teteqami: michael
yedmet_video:
yizet: "የሚያሳዝኑ ድመቶች አሳዛኞች ናቸው: https://youtu.be/PKffm2uI4dk"
created_at: <%= 2.hours.ago %>
teteqami: michael
yeqrb_gizei:
yizet: "አንድ አጪር ፈተና እየጻፍኩ ነው።"
created_at: <%= Time.zone.now %>
teteqami: michael
ዝርዝር 13.15 ክት ሩቢን በመጠቀም የተፈጠረ_በ (created_at
) መስክን በግልጽ እንደሚያዘጋጅ ልብ በሉ፡፡ ይህ መስክ በሬይልስ በራስሰር የሚዘምን አንድ “የአስማት” መስክ ስለሆነ፣ ይህንን መስክ በተለምዶ በእጅ ማዘጋጀት አይቻልም፣ በእቃወች ውስጥ ግን ይቻላል።6
በዝርዝር 13.14 እና በዝርዝር 13.15 ውስጥ ባሉት ኮዶች የፈተና ስብስቡ ቀይመሆን አለበት፡-
$ rails test test/models/achrtshuf_test.rb
አንድ ነባሪ_ክልል (default_scope
) ተብሎ የሚጠራ የሬይልስ ዘዴን በመጠቀም ፈተናው እንዲያልፍ እናደርገዋለን፣ ይህም ሌሎች ከሚሰጣቸው ጥቅሞች ውስጥ፣ የትኞቹ አባላቶች ከውሂበጎታው ተፈልገው ማውጣት እንዳለባቸው፣ አንድ ነባሪ ቅደም ተከተልን ለማዘጋጀት ሊጠቅም ይችላል። አንድ የተወሰነ ቅደም ተከተልን ለማስከበር፣ በ‘ነባሪ_ክልል (default_scope
) ውስጥ የ‘ቅደም-ተከተል (order
) ነጋሪአሴትን አናክላለን፣ ይህም እንደሚከተለው፣ በ‘ተፈጠረ_በ (created_at
) መስክ መሰረት ቅደም ተከተል እንድናደርግ ያስችለናል፡-
order(:created_at)
አለመታደል ሆኖ፣ ይህ ቅደም ተከተል ውጤቱን በሽቅብታ (Ascending) ቅደም ተከተል፣ ከትንሽ ቁጥር ወደ ትልቅ ቁጥር ቅደም ተከተል በማድረግ ያቀርባል፣ ይህ ማለት በጣም የድሮዎቹ አጪርጽሑፎች መጀመሪያ ላይ ይመጣሉ ማለት ነው፡፡ ውጤቱን በተገላቢጦሽ ለማግኘት፣ ማለት እኛ የፈለገውን ውጤት ለማግኘት፣ ትንሽ ጥሬ ተ.መ.ቋን ከአንድ ሃረግ ጋር እንጨምራለን:-
order('created_at DESC')
እዚህ ላይ “አቆልቋይ (descending)” ማለት DESC
የሚለው ቃል ሙሉ አባባል ሲሆን ይህም ተ.መ.ቋ ነው፣ አቆልቋይ (Descending) ቅደም ተከተል ማለት ቅደም ተከተሉ ከአዲሱ ወደ አሮጌው/ወደቆየው ማለት ነው።7 በቀድሞዎቹ የሬይልስ ስሪቶች ውስጥ የሚፈለገውን ባህሪ ለማግኘት ይህንን ጥሬ ተ.መ.ቋ መጠቀሙ አንዱ እና ብቸኛው አማራጪ ሆኖ ያገለግል ነበር፣ ከሬይልስ 4.0 በኋላ ግን አንድ የበለጠ ተፈጥሮዋዊ የሆነ ጥሬ-የሩቢ አገባብን በመጠቀም እንደሚታየው አድርገን ልንጽፈው እንችላለን:-
order(created_at: :desc)
ይህንን አንድ ነባሪ ክልል በአጪርጽሑፍ ቅርጸቱ ውስጥ ማከሉ፣ ዝርዝር 13.17 ‘ን ይሰጣል።
default_scope
) ቅደም ተከተል ማስያዝ፡፡ አረንጓዴ app/models/achrtshuf.rb
class Achrtshuf < ApplicationRecord
belongs_to :teteqami
default_scope -> { order(created_at: :desc) }
validates :teteqami_id, presence: true
validates :yizet, presence: true, length: { maximum: 140 }
end
ዝርዝር 13.17 አንድ የአሰራ (የአሰራር) (Proc (procedure)) ወይም የላምዳ (lambda) የተባለ ቁስን ለመጥራት ይሄን “->
” ያስተዋውቃል፣ ይህ ምልክት “ስታቢ ላምዳ” ይባላል፣ ይህም ስም አልባ ሥልት (Anonymous Function) ነው (አንድ ያለ ስም የተፈጠረ ሥልት ማለት ነው)። ስታቢ ላምዳ አንድ ጥምርን (ክፍል 4.3.2) ይወስድ እና አንድ አሰራርን (ፕሮክን) ይመልሳል፣ ከዚያ በኋላም በ‘ጥሪ (call
) ዘዴ ሊገመገም ይችላል። ይህ እንዴት እንደሚሰራ በሰሌዳው ውስጥ ማየት እንችላለን:-
>> -> { puts "turye" }
=> #<Proc:0x007fab938d0108@(irb):1 (lambda)>
>> -> { puts "hani" }.call
hani
=> nil
(ይህ ትንሽ ላቅ ያለ የሩቢ ርዕስ ስለሆነ፣ እንዴት እንደሚሰራ ወድያውኑ ካልገባችሁ ብዙ ልትጨነቁ አይገባም።)
ዝርዝር 13.17 ካለው ኮድ ጋር ፈተናው አረንጓዴመሆን አለበት:-
$ rails test
ትክክለኛውን ቅደም ተከተል ከመጨመር ባሻገር፣ በአጪርጽሑፎች ላይ አንድ ማከል የምንፈልገው ሁለተኛ ማጣሪያ አለ፡፡ በክፍል 10.4 ትምህትታችን ላይ፣ የጣቢያው አስተዳዳሪዎች ተጠቃሚዎችን የማጥፋት ስልጣን እንዳላቸው ታስታውሳላችሁ፡፡ ይህም አንድ ተጠቃሚ ከጠፋ፣ የተጠቃሚው አጪርጽሑፎችም መጥፋት አለባቸው ለሚለው እውነታ ምክንያት ይሆናል።
በዝርዝር 13.19 ላይ እንደተመለከተው፣ አንድ አማራጪን ወደ ብዙ_አለው (has_many
) የማሕበር ዘዴ በማሳለፍ ይህንን ባህሪ ማዘጋጀት እንችላለን:-
app/models/teteqami.rb
class Teteqami < ApplicationRecord
has_many :achrtshufs, dependent: :destroy
.
.
.
end
እዚህ ላይ የ‘ጥገኛ: :አጥፋ (dependent: :destroy
) አማራጩ፣ ተጠቃሚው ራሱ ሲጠፋ ከተጠቃሚው ጋር ጥገኛ የሆኑት አጪርጽሑፎችም አብረው እንዲጠፉ ያዘጋጃል፡፡ ይህም አስተዳዳሪዎች፣ ተጠቃሚዎችን ከውሂበጎታው ሲያጠፏቸው፣ ተጠቃሚ አልባ የሆኑ አጪርጽሑፎች በውሂበጎታው ውስጥ እንዳይቀሩ ይከለክላል፡፡
የተጠቃሚ ቅርጸቱን በመፈተን በዝርዝር 13.19 ውስጥ ያለው ኮድ እንደሚሰራ ማረጋገጥ እንችላለን። ይህንን ለማረጋገጥ ማድረግ ያለብን ነገር ቢኖር፣ ተጠቃሚውን ማስቀመጥ (በዚህ ጊዜ አንድ መታወቂያን ያገኛል) እና ከዚያ ከሱ ጋር የሚዛመድ አንድ አጪርጽሑፍን መፍጠር ይሆናል። ከዚያ ተጠቃሚውን በማጥፋት የአጪርጽሑፎቹ ብዛት በ 1 እንደቀነሰ ማረጋገጥ ይሆናል፡፡ ውጤቱም በዝርዝር 13.20 ውስጥ ይታያል፡፡ (ይህን በዝርዝር 10.62 ውስጥ የ “ሰርዝ” አገናኞችን ከሚፈትነው የውህደት ፈተና ጋር አነጻጽሩ፡፡)
dependent: :destroy
) ማከል። አረንጓዴ 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
.
.
.
test "ተዛማጅ አጪርጽሑፎች መጥፋት አለባቸው" do
@teteqami.save
@teteqami.achrtshufs.create!(yizet: "አሳ በልቶ ውሃ")
assert_difference 'Achrtshuf.count', -1 do
@teteqami.destroy
end
end
end
በዝርዝር 13.19 ውስጥ ያለው ኮድ በትክክል እየሰራ ከሆነ፣ የፈተና ስብስቡ አሁንም አረንጓዴመሆን አለበት:-
$ rails test
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
Achrtshuf.first.created_at
) ዋጋ እና በ‘አጪርጽሑፍ.መጨረሻ.ተፈጠረ (Achrachrtshuf.last.created_at
) ዋጋ መካከል ምን ልዩነት አለ?
ተጠቃሚ
‘ን በውሂበጎታው ላይ ያለው የመጀመሪያ ተጠቃሚን እናድርገው እንበል፤ የሱ የመጀመሪያ የአጪርጽሑፍ መታወቂያ ስንት ነው? የ‘አጥፋ (destroy
) ዘዴን በመጠቀም የመጀመሪያውን ተጠቃሚ ከውሂበጎታው አጥፉ፣ ከዚያ አጪርጽሑፍ.ፈልግ (Achrtshuf.find
) ዘዴን በመጠቀም፣ የተጠቃሚው የመጀመሪያው አጪርጽሑፍም አብሮ ከሱ ጋር እንደጠፋ አረጋግጡ፡፡
ምንም እንኳን እስከ አሁን ድረስ፣ በድር በኩል የአጪርጽሑፍ መፍጠሪያ ቅጽን ተጠቅመን አጪርጽሑፎችን የምንፈጥርበት አንድ መንገድ ባይኖርም፣ ድሩ እነሱን ለማሳየት ግን አያግደንም (በክፍል 13.3.2 ውስጥ አንድ ቅጽን በመጠቀም አጪርጽሑፎችን መፍጠር እንጀምራለን)። የትዊተርን አሰራር በመከተል፣ የተጠቃሚውን አጪርጽሑፎች በአንድ የተለየ የአጪርጽሑፎች ማውጫ (index
) ገጽ ላይ ከማሳየት ይልቅ፣ በምስል 13.4 ስእላዊ መግለጫ ላይ እንደሚታየው፣ የተጠቃሚውን አጪርጽሑፎች፣ በቀጥታ በተጠቃሚው መገለጫ ማሳያ (show
) ገጽ ላይ ለማሳየት አቅደናል፡፡ በተጠቃሚው መገለጫ ላይ አንድ የአጪርጽሑፍ ማሳያን ለማከል፣ ቀላል በሆኑ የክ.ሩ (ERb) ዝግጁገጽታዎች እንጀምራለን፣ ከዚያ በተጠቃሚው መገለጫ ገጽ ላይ የሚታዩ አጪርጽሑፎች ይኖሩን ዘንድ፣ ክፍል 10.3.2 ላይ ካለው የውሂብ ዘር ላይ ጥቂት አጪርጽሑፎችን እናክላለን፡፡
ዓላማችን፣ ለእያንዳንዱ ተጠቃሚ የሰራውን አጪርጽሑፍ እና የአጪርጽሑፎቹን ብዛት በራሱ መገለጫ ገጽ ላይ (አሳይ.ሃጽመቋ.ክሩ (show.html.erb
)) ማሳየት ነው፣ ከዚህ በኋላ እንደምናየው፣ አብዛኞቹ ሃሳቦች በክፍል 10.3 ላይ ካለው ማለት፣ ሁሉንም ተጠቃሚዎች በማሳየት ስራ ላይ ከሰራናቸው ስራወች ጋር ተመሳሳዮች ናቸው፡፡
መልመጃ ስትሰሩ በውሂበጎታው ውስጥ የፈጠራችኋቸው አንዳንድ አጪርጽሑፎች ካሉ፣ በዚህ ጊዜ ውሂበጎታውን እንደገና ለማስጀመር እና እንደገና ለመዝራት፣ የሚከተሉትን ትእዛዛት አስኪዱ:-
$ rails db:migrate:reset
$ rails db:seed
ምንም እንኳን እስከ ክፍል 13.3 የአጪርጽሑፎች መቆጣጠሪያ የማያስፈልገን ቢሆንም፣ የትይታ ማውጫ ግን ላሁኑ ያስፈልገናል፣ ስለዚህ መቆጣጠሪያውን አሁን እናመንጪ:-
$ rails generate controller Achrtshufs
በዚህ ክፍል ውስጥ ዋናው ዓላማችን ለእያንዳንዱ ተጠቃሚ ሁሉንም አጪርጽሑፎች በመገለጫ ገጹ ላይ ማቅረብ ይሆናል፡፡ በክፍል 10.3.5 ውስጥ እንዳየነው ይህ ኮድ:-
<ul class="አጪርጽሑፎች">
<%= render @teteqamis %>
</ul>
የ‘ _ተጠቃሚ.ሃጽመቋ.ክሩ (_teteqami.html.erb
) ከፊልን በመጠቀም በ@ተጠቃሚዎች (@teteqamis
) ተለዋዋጪ ውስጥ የለ ተጠቃሚን አንድባንድ ለቃቀሞ በራስሰር እንደሚያቀርብ አይተናል። ይህንን መሰረት በማድረግ አንድ ተመሳሳይ የ‘ _አጪርጽሑ.ሃጽመቋ.ክሩ (_achrtshuf.html.erb
) ከፊልን እንበይናለን፣ ስለሆነም አንድ ዓይነት ስልትን፣ በአንድ አጪርጽሑፎች ክምችት ውስጥ እንደሚከተለው እናደርጋለን መጠቀም እንችላለን:-
<ol class="አጪርጽሑፎች">
<%= render @achrtshufs %>
</ol>
እዚህ ላይ የባለ-ቁጥር ዝርዝር (ol
) መለያን ተጠቅመናል፣ ይህንን የተጠቀምንበት ምክንያትም አጪርጽሑፎቹን በአንድ የተወሰነ ቅደም ተከተል ለመዘርዘር ስለሚጠቅመን ነው፤ (የቁጥር-አልባ ዝርዝር (ul
) መለያ ከባለ-ቁጥር ዝርዝር (ol
) መለያ አንጻር በሆነ መልኩ ይሰራል)። ተዛማጁ ከፊል በዝርዝር 13.22 ውስጥ ይታያል፡፡
app/views/achrtshufs/_achrtshuf.html.erb
<li id="achrtshuf-<%= achrtshuf.id %>">
<%= link_to amsaya_le(achrtshuf.teteqami, meten: 50), achrtshuf.teteqami %>
<span class="ተጠቃሚ"><%= link_to achrtshuf.teteqami.sim,
achrtshuf.teteqami %></span>
<span class="ይዘት"><%= achrtshuf.yizet %></span>
<span class="ማህተመጊዜ">
ከ <%= time_ago_in_words(achrtshuf.created_at) %> በፊት ተለጠፈ።
</span>
</li>
ይህ ምን እንደሚያደርግ ለማወቅ ግልጽ የሆነውን እና አበርክቶውን በክፍል 13.2.2 ላይ የምናየውን ምርጡን የ‘ጊዜ_በፊት_በቃላት (time_ago_in_words
) ረጅ ዘዴን ይጠቀማል። ዝርዝር 13.22 እንዲሁ ለእያንዳንዱ አጪርጽሑፍ አንድ የቅ.ቋ መለያን በመጠቀም ይህንን ያክላል:-
<li id="achrtshuf-<%= achrtshuf.id %>">
ለወደፊቱ አጪርጽሑፍችን በተናጠል ለማንቀሳቀስ (ለምሳሌ ያህል ጃቫስክሪፕትን በመጠቀም) አንድ እድልን ስለሚከፍት፣ ይህንን የቅ.ቋ መለያ አስቀድሞ ማድረጉ በአጠቃላይ በጣም ጥሩ ልምድ ነው፡፡
ቀጣዩ ሂደት ብዙ አጪርጽሑፎችን ለማሳየት የሚያጋጥመውን ችግር መፍታት ነው፡፡ ይህንን ችግር፣ በክፍል 10.3.3 ውስጥ በተጠቃሚዎች ላይ ገጸቁጥርን በመጠቀም በፈታንበት ተመሳሳይ መንገድ እንፈታዋለን፡፡ አሁንም እንደበፊቱ የ‘ዊል_ገጽቁጥርስጥ (will_paginate
) ዘዴን እንጠቀማለን (የገጸቁጥሩ ገጽ መቀየሪያ በአማርኛ ይሆንል ዘንድ፣ ለ previouslabel
አማራጪ ቀዳሚ
እና ለ nextlabel
አማራጪ ደግሞ ቀጣይ
የተባለ ሃረግን እንዳሳለፍን ልትገነዘቡ ይገባል)፡-
<%= will_paginate @achrtshufs, :previous_label => "ቀዳሚ", :next_label => "ቀጣይ" %>
ዝርዝር 10.45 ላይ ብትመለከቱ፣ የነበረን ኮድ ይህንን ይመስላል:-
<%= will_paginate :previous_label => "ቀዳሚ", :next_label => "ቀጣይ" %>
እዚህ ላይ የ‘ዊል_ገጽቁጥርስጥ (will_paginate
) ዘዴ በተጠቃሚዎች መቆጣጠሪያ አውድ ውስጥ አንድ የ‘@ተጠቃሚዎች (@teteqamis
) ተለዋዋጪ መኖሩን ስለሚገምት እና ስላለም ሊሰራ ችሏል (በክፍል 10.3.3 ላይ እንዳየነው የ‘ንቅመዝገብ::ዝምድና (ActiveRecord::Relation
) ክፍል መሆን አለበት)፡፡ አሁን ባለው ሁኔታ ላይ በተጠቃሚዎች መቆጣጠሪያ ውስጥ ሁነን፣ ነገር ግን በአጪርጽሑፎች ላይ ገጸቁጥርን ማድረግ እንፈልጋለን፤ ስለዚህ ለ‘ዊል_ገጽቁጥርስጥ (will_paginate
) ዘዴ አንድ የ‘@አጪርጽሑፎች (@achrtshufs
) ተለዋዋጪን በቁም ነገር ማሳለፍ ይኖርብናል። እሱንም ያለ ጥርጥር፣ በተጠቃሚ አሳይ (show
) ተግባር ውስጥ መበየን ይኖርብናል ማለት ነው (ዝርዝር 13.23)፡፡
show
) ተግባር ውስጥ አንድ @አጪርጽሑፎች (@achrtshufs
) ቅርፀ ተለዋዋጪን ማከል። app/controllers/teteqamis_controller.rb
class TeteqamisController < ApplicationController
.
.
.
def show
@teteqami = Teteqami.find(params[:id])
@achrtshufs = @teteqami.achrtshufs.paginate(page: params[:page])
end
.
.
.
end
እዚህ ላይ የ‘ገጽቁጥርስጥ (paginate
) ዘዴ ምን ያህል አስደናቂ ስራ እንዳከናወነ አስተውሉ፤ ወደ አጪርጽሑፎች (achrtshufs)
ሰንጠረዥ በመግባት እና የሚፈለጉትን የአጪርጽሑፎች ገጾችን ጎትቶ ለማውጣት፣ በአጪርጽሑፎች ማሕበር በኩል (through) ሳይቀር እንኳን ይሰራል፡፡
የመጨረሻው ስራችን የእያንዳንዱን ተጠቃሚ የአጪርጽሑፎች ብዛት ለተጠቃሚው ማሳየት ነው፣ ይህንንም በ‘ቁጠር (count
) ዘዴ እንዲህ አድርገን ልንሰራው እንችላለን:-
teteqami.achrtshufs.count
ገጽቁጥርስጥ‘ን (paginate
) በማሕበሩ በኩል እንደተጠቀምንበት ሁሉ፣ የ‘ቁጠር (count
) ዘዴንም በዛው መልኩ ልንመጠቀምበት እንችላለን፡፡ በተለይ ደግሞ፣ የ‘ቁጠር (count
) ዘዴ የአጪርጽሑፎቹን ብዛት ለማግኘት፣ ከውሂበጎታው ውስጥ ያሉትን አጪርጽሑፎች ከውሂበጎታው ካወጣ በኋላ፣ በተገኘው ድርድር ላይ የ‘እርዝመት (length
) ዘዴን አይጠራም (ምክንያቱም ይህ አሰራር የአጪርጽሑፎቹ ብዛት እየጨመረ ሲሄድ ውጤታማ ስለማይሆን ነው)። በምትኩ፣ በተሰጠው የ‘ተጠቃሚ_መታወቂያ (teteqami_id
) መሰረት ውሂበጎታው አጪርጽሑፎቹን እንዲቆጥርለት በመጠየቅ፣ እዛው ውሂበጎታው ውስጥ ስሌቱን በቀጥታ ያካሂዳል (ይህ ሁሉም ውሂበጎታዎች በጣም የሚተቡበት (optimize) ክዋኔ ነው)።8 (የ‘ቁጠር (count
) ዘዴን ስትጠቀሙ አፕልኬሽናችሁን ባልተጠበቀ ሁኔታ የሚዘገይ ከሆነ፣ የበለጠ ቀልጣፋ እንዲሆን ለማድረግ ካውንተር ካሽ የተባለውን እንቁ መጠቀም ትችላላችሁ፡፡)
በዝርዝር 13.24 ላይ እንደሚታየው፣ ከላይ የዘረዘርናቸውን ሁሉ ባንድ ላይ በማስቀመጥ፣ አሁን በተጠቃሚው መገለጫ ገጽ ላይ አጪርጽሑፎችን ለማከል የሚያስችል አንድ አቋም ይኖረናል፡፡ @ተጠቃሚ.አጪርጽሑፎች.ማንኛውም? ካሉት (if @teteqami.achrtshufs.any?
) የሚለው ኮድ ጥቅምን አስተውሉ፣ ይህ (ከዚህ በፊት በዝርዝር 7.21 ውስጥ ያየነው ግንባታ) ተጠቃሚው አጪርጽሑፎች ከሌሉት ባዶ ዝርዝር አለመታየቱን ያረጋግጣል፡፡
show
) ገጽ ላይ ማከል። app/views/teteqamis/show.html.erb
<% provide(:title, @teteqami.sim) %>
<div class="row">
<aside class="col-md-4">
<section class="የተጠቃሚ_መረጃ">
<h1>
<%= amsaya_le @teteqami %>
<%= @teteqami.sim %>
</h1>
</section>
</aside>
<div class="col-md-8">
<% if @teteqami.achrtshufs.any? %>
<h3>(<%= @teteqami.achrtshufs.count %>) አጪርጽሑፎች</h3>
<ol class="አጪርጽሑፎች">
<%= render @achrtshufs %>
</ol>
<%= will_paginate @achrtshufs, :previous_label => "ቀዳሚ",
:next_label => "ቀጣይ" %>
<% end %>
</div>
</div>
በዚህ ጊዜ፣ የተዘመነውን የተጠቃሚ መገለጫ ገጻችንን በምስል 13.5 ላይ ማየት እንችላለን፡፡ የሚያሳዝነው ግን ለማየት የጓጓነው ነገር አለመኖሩ ነው፣ በእርግጥ ይህ የሆነበት ምክንያት፣ በአሁኑ ጊዜ ምንም አይነት አጪርጽሑፍ በገጹ ላይ ስለለለ ነው። አሁን ይህን አሳዛኝ ሁኔታ የመቀየሪያ ጊዜ ነው።
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
time_ago_in_words
) ያሉ ረጅ ዘዴወች በሬይልስ ሰሌዳ ውስጥ ረጅ (helper
) በተባለው ቁስ በኩል ይገኛሉ፡፡ ረጅ‘ን (helper
) ከ‘ጊዜ_በፊት_በቃላት (time_ago_in_words
) ጋር በመጠቀም የ‘ከ3.ሳምንታት.በፊት (3.weeks.ago
) እና የ‘ከ6.ወራት.በፊት (6.months.ago
) ዋጋን አግኙ። ጠቃሚ ምክር:- የሚከተለውን ምሳሌ ተጠቀሙ helper.time_ago_in_words(1.year.ago)
።
helper.time_ago_in_words(1.year.ago)
ውጤትስ ምንድነው?
paginate
) ላይ ‘ገጽ: ምንም (page: nil
) የሚል ነጋሪአሴትን በማሳለፍ የ‘ክፍል (class
) ዘዴን ጥሩ፡፡
በክፍል 13.2.1 ውስጥ የተጠቃሚውን አጪርጽሑፎች ለማሳየት ያሁሉ ዝግጁገጽታዎችን የመስራቱ ድካም መጨረሻ ላይ ካሳው አመርቂ አልነበረም፡፡ ክፍል 10.3.2 ላይ የተገኘው የውሂብ ዘር ላይ ጥቂት አጪርጽሑፎችን በማከል ይህንን አሳዛኝ ሁኔታ ማስተካከል እንችላለን፡፡
ሁሉም ተጠቃሚዎች ላይ የአጪርጽሑፎች ናሙናን ማከሉ በጣም ጊዜ ስለሚወስድ፣ የ‘ውሰድ (take
) ዘዴን በመጠቀም መጀመሪያ ላይ የሚገኙትን ስድስት ተጠቃሚዎች ብቻ በመምረጥ፣ ለነሱ የአጪርጽሑፎች ናሙናዎችን እናክልላቸዋለን (ማለትም፣ አንዱ ተጠቃሚ ነባሪ አምሳያ ሲኖረው፣ አምስቱ ተጠቃሚዎች ደግሞ ብጁ አምሳያ ይደረግላቸዋል):-
Teteqami.order(:created_at).take(6)
የቅደም-ተከተል (order
) ጥሪ መጀመሪያ ላይ የተፈጠሩትን ስድስት ተጠቃሚዎችን ማግኘታችንን ያረጋግጥልናል፡፡
ለእያንዳንዱ ምርጥ ተጠቃሚ፣ 50 አጪርጽሑፎችን እንሰራለን (በአንድ ገጽ ውስጥ ከ 30 አጪርጽሑፎች በላይ ስለሚኖር፣ የገጸቁጥር ተግባርን ለማስጀመር በቂ ነው)። የናሙናውን ይዘት ለእያንዳንዱ አጪርጽሑፍ ለማመንጨት የአስመሳይ እንቁ የሰጠንን ምቹ የ‘ሎረም.ዓረፍተነገር (Lorem.sentence)
ዘዴን እንጠቀማለን።9 አዲሱ የውሂብ ዘር ዘዴ ውጤት በዝርዝር 13.25 ውስጥ ይታያል፡፡ (በዝርዝር 13.25 ላይ በምልልሱ ውስጥ ቅደም ተከተል የተደረገበት ምክንያት፣ በሁኔታ ቀላቢ ውስጥ ጥቅም ላይ የሚውሉ አጪርጽሑፎችን ለማደባለቅ ነው (ክፍል 14.3)፡፡ በመጀመሪያው ተጠቃሚ ላይ በተሰጠ አንድ አጪርጽሑፍ ላይ መመላለሱ፣ ለሁሉም ተጠቃሚ፣ ከመጀመሪያው ተጠቃሚ ጋር ፍጹም አንድ አይነት የሆነ ሁኔታ ቀላቢን ስለሚሰጥ ለአይን የሚስብ አይሆንም።)
db/seeds.rb
.
.
.
# ለክፍለንዑስ ተጠቃሚዎች አጪርጽሑፎችን ያመነጫል።
teteqamis = Teteqami.order(:created_at).take(6)
50.times do
yizet = Faker::Lorem.sentence(word_count: 5)
teteqamis.each { |teteqami| teteqami.achrtshufs.create!(yizet: yizet) }
end
በዚህ ጊዜ፣ እንደተለመደው የብልጸጋ ውሂበጎታውን እንደገና መዝራት እንችላለን:-
$ rails db:migrate:reset
$ rails db:seed
የሬይልስ ብልጸጋ አገልጋያችሁን አቁማችሁ እንደ አዲስ ማስጀመር ይኖርባችኋል፡፡
በክፍል 13.2.1 ላይ ላፈሰስነው ላብ፣ አሁን የእያንዳንዱን የአጪርጽሑፍ መረጃ በተጠቃሚው የመገለጫ ገጽ ላይ በማሳየት በላባችን ዋጋ የምንደሰትበት ሁኔታ ላይ እንገኛለን።10 የመባቻ ውጤቱ በምስል 13.6 ላይ ይታያል፡፡
በምስል 13.6 ላይ የሚታየው ገጽ፣ አጪርጽሑፍ ተኮር ቅጥ የለውም፣ ስለሆነም እስኪ ጥቂት ቅጥ እናክልበት እና የተገኙትን ገጾች እንመልከት (ዝርዝር 13.26)፡፡11
app/assets/stylesheets/bju.scss
.
.
.
/* አጪርጽሑፎች */
.አጪርጽሑፎች {
list-style: none;
padding: 0;
li {
padding: 10px 0;
border-top: 1px solid #e8e8e8;
}
.ተጠቃሚ {
margin-top: 5em;
padding-top: 0;
}
.ይዘት {
display: block;
margin-left: 60px;
img {
display: block;
padding: 5px 0;
}
}
.ማህተመጊዜ {
color: $gray-light;
display: block;
margin-left: 60px;
}
.አምሳያ {
float: left;
margin-right: 10px;
margin-top: 5px;
}
}
aside {
textarea {
height: 100px;
margin-bottom: 5px;
}
}
span.image {
margin-top: 10px;
input {
border: 0;
}
}
ምስል 13.7 የመጀመሪያውን ተጠቃሚ የመገለጫ ገጽ ሲያሳይ፣ ምስል 13.8 ደግሞ የሁለተኛውን ተጠቃሚ የመገለጫ ገጽ ያሳያል፡፡ በመጨረሻም፣ ምስል 13.9 ለመጀመሪያው ተጠቃሚ የአጪርጽሑፎቹ ሁለተኛ ገጽን ከግርጌው ላይ የገጸቁጥር አገናኞቹን ጨምሮ ያሳያል፡፡ በሶስቱም ሁኔታወች ላይ እያንዳንዱ የአጪርጽሑፍ ማሳያ፣ ከተፈጠረበት ጊዜ ጀምሮ ያለውን ጊዜ የሚያመለክት መሆኑን ተገንዘቡ (ምሳሌ፣ “ከ 6 ሰዓት በፊት ተለጠፈ”)፡፡ ይህ ከዝርዝር 13.22 የተገኘ የ‘ጊዜ_በፊት_በቃላት (time_ago_in_words
) ዘዴ ስራ ውጤት ነው፡፡ ለጥቂት ደቂቃወች ቆይታችሁ እንደገና ገጾቹን ብትጫኑ፣ በአዲሱ ጊዜ ላይ በመመስረት ጽሑፉ በራስሰር እንዴት እንደሚዘምን ልታዩ ትችላላችሁ።
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
(1..10).to_a.take(6)
ኮድ ማስኬዱ ምን ውጤት እንደሚያመጣ መገመት ትችላላችሁን? ግምታችሁ ትክክል መሆኑን ለማረጋገጥ ይህንኑ ኮድ ሰሌዳችሁ ላይ አስኪዱት።
to_a
) ዘዴን መጠቀሙ አስፈላጊ ነውን?
አዲስ የነቁ ተጠቃሚዎች ወደ መገለጫ ገጾቻቸው ሲዟዟሩ፣ የመገለጫ ገጹ በትክክል መቅረቡን የሚያረጋግጥ አንድ ፈተና ቀድሞውኑ ስላለን (ዝርዝር 11.33)፣ በዚህ ክፍል ውስጥ፣ በመገለጫ ገጹ ላይ ላሉ አንዳንድ ነገሮች እና በዚህ ክፍል ውስጥ ለሰራናቸው ነገሮች የሚሆን፣ አንድ አጪር የውህደት ፈተናን እንጽፋለን። የጣቢያችን ተጠቃሚዎች መገለጫወችን ለመፈተን፣ አንድ የውህደት ፈተናን በማመንጨት እንጀምራለን:-
$ rails generate integration_test teteqamis_glemahder
invoke test_unit
create test/integration/teteqamis_glemahder_test.rb
የአጪርጽሑፍ ገጸቁጥርን ለመፈተን፣ በዝርዝር 10.47 ውስጥ ተጨማሪ ተጠቃሚዎችን ለመፍጠር የተጠቀምንበትን ማለት የክት ሩቢ ስልትን በመጠቀም፣ የተወሰኑ ተጨማሪ የአጪርጽሑፎች እቃዎችን እናመነጫለን:-
<% 30.times do |n| %>
achrtshuf_<%= n %>:
yizet: <%= Faker::Lorem.sentence(word_count: 5) %>
created_at: <%= 42.days.ago %>
teteqami: michael
<% end %>
ዝርዝር 13.15 የነበረው ኮድ ላይ የላይኛውን ኮድ ማከሉ፣ በዝርዝር 13.27 ውስጥ የዘመነውን የአጪርጽሑፍ እቃዎችን ይሰጣል።
test/fixtures/achrtshufs.yml
weba:
yizet: "ወባ ፊት የነሳው ሰውየ ቡዳ እንዳይበላኝ አለ።"
created_at: <%= 10.minutes.ago %>
teteqami: michael
tau_manifesto:
yizet: "በ @mhartl የ @tauday ጣቢያን ተመልከቱ https://tauday.com"
created_at: <%= 3.years.ago %>
teteqami: michael
yedmet_video:
yizet: "የሚያሳዝኑ ድመቶች አሳዛኞች ናቸው: https://youtu.be/PKffm2uI4dk"
created_at: <%= 2.hours.ago %>
teteqami: michael
yeqrb_gizei:
yizet: "አንድ አጪር ፈተና እየጻፍኩ ነው።"
created_at: <%= Time.zone.now %>
teteqami: michael
<% 30.times do |n| %>
achrtshuf_<%= n %>:
yizet: <%= Faker::Lorem.sentence(word_count: 5) %>
created_at: <%= 42.days.ago %>
teteqami: michael
<% end %>
ከዚህ የፈተና ውሂብ ተዘጋጅቶ መቅረብ በኋላ፣ የሚደረገው ፈተና በትክክል ግልጽ ነው፤ የተጠቃሚውን የመገለጫ ገጽ እንጎበኝ እና በገጹ ላይ የገጹ አርዕስት፣ የተጠቃሚው ስም፣ የተጠቃሚው አምሳያ፣ የተጠቃሚው አጪርጽሑፎች ብዛት እና ገጸቁጥር ያለው አጪርጽሑፍ መኖሩን እንፈትሻለን። ውጤቱ በዝርዝር 13.28 ውስጥ ይታያል፡፡ የገጹን አርዕስት ለመፈተን ዝርዝር 4.2 ላይ ያለውን የ‘ሙሉ_አርዕስት (mulu_arest
) ረጅን እንደተጠቀምን አስተውሉ፤ ይህ ረጅ በዚህ ፈተና ውስጥ እንዲደረስ ለማድረግ፣ የአፕልኬሽን ረጅ ክፍለክፍሉን (Module)፣ በፈተናው ውስጥ ማካተት ይኖርብናል፡፡ 12
test/integration/teteqamis_glemahder_test.rb
require "test_helper"
class TeteqamisGlemahderTest < ActionDispatch::IntegrationTest
include ApplicationHelper
def setup
@teteqami = teteqamis(:michael)
end
test "የመገለጫ ማሳያ" do
get teteqami_path(@teteqami)
assert_template 'teteqamis/show'
assert_select 'title', mulu_arest(@teteqami.sim)
assert_select 'h1', text: @teteqami.sim
assert_select 'h1>img.አምሳያ'
assert_match @teteqami.achrtshufs.count.to_s, response.body
assert_select 'div.pagination'
@teteqami.achrtshufs.paginate(page: 1).each do |achrtshuf|
assert_match achrtshuf.yizet, response.body
end
end
end
በዝርዝር 13.28 ውስጥ የአጪርጽሑፎች ብዛት ማረጋገጫው የ‘መልስ.አካል (response.body
) ዘዴን ይጠቀማል፣ ይህንንም በምዕራፍ 12 መልመጃዎች ውስጥ በግልጽ አይተነዋል (ክፍል 12.3.3.1)፡፡ ምንም እንኳ ስሙ ባይገልጸውም፣ የ‘መልስ.አካል (response.body
) ዘዴ የገጹን ሙሉ የሃ.ጽ.መ.ቋ ምንጪ ሳይቀር ያጠቃልላል (የገጹን አካል ብቻ አይደለም፡፡) ይህ ማለት እኛ የምንፈልገው ነገር የአጪርጽሑፎቹ ብዛት በገጹ ላይ መታየቱን ብቻ ከሆነ፣ ይሄንኑ የሚያዛመድ አንድ ተዛማጅ እንዳለ እንደሚከተለው አድርገን መመልከት እንችላለን ማለት ነው:-
assert_match @teteqami.achrtshufs.count.to_s, response.body
ይሄ ልክ እንደ መለያ_አረጋግጥ (assert_select
) በጣም ንጹር ነገር ላይ የተወሰነ ማረጋገጫ አይደለም፤ በተለይ ደግሞ፣ የ‘አቻነት_አረጋግጥ (assert_match
) ማረጋገጫን መጠቀሙ፣ ልክ እንደ መለያ_አረጋግጥ (assert_select
) ማረጋገጫ የሃ.ጽ.መ.ቋ መለያን እንድናስገባ አይፈቅድልንም።
ዝርዝር 13.28 እንዲሁ፣ የ‘መለያ_አረጋግጥ (assert_select
) የእቅፍቅፍ አገባብን ያስተዋውቃል:-
assert_select 'h1>img.አምሳያ'
ይህ ፈተና በገጹ ላይ አንድ የ‘ምስል (img
) መለያ ከ‘ አምሳያ
ክፍል ጋር በአንድ ራስጌ1 (h1
) አብይ-ደረጃ አርእስት ውስጥ መኖሩን ያረጋግጣል፡፡
የአፕልኬሽን ኮዱ እየሰራ ስለነበር፣ የፈተና ስብስቡ አረንጓዴመሆን ይኖርበታል፡-
$ rails test
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
'h1'
መለያወችን ከ አረንጓዴ ወደ ቀይለመቀየር የሚያስችለው የአፕልኬሽን ኮድ ላይ አስተያየት አድርጉ፡፡
will_paginate
) በገጹ ላይ አንድ ጊዜ ብቻ እንዲታይ የሚያስችል አንድ ፈተናን በማከል ዝርዝር 13.28 ‘ን አዘምኑ፡፡ ጠቃሚ ምክር:- ሰንጠረዥ 5.2 ላይ ይመልከቱ፡፡
የውሂብ ቅዱን እና ለአጪርጽሑፎች ማሳያ የሚሆኑ ዝግጁገጽታዎችን ስለጨረስን፣ አሁን እነሱን በድር በኩል ለመፍጠር ትኩረታችንን ወደ በይነገጹ እናዞራለን። በዚህ ክፍል ውስጥ፣ በምዕራፍ 14 ውስጥ ሙሉ በሙሉ ፍጻሜ ላይ ይደርሳል ተብሎ ተስፋ የተደረገበትን፣ የሁኔታ ቀላቢ አሰራርን ለመጀመሪያ ጊዜ እንመለከታለን። በመጨረሻም፣ ልክ እንደ ተጠቃሚዎች፣ አጪርጽሑፎችንም በድር በኩል ማጥፋት እንደሚቻል እናደርጋለን።
እዚህ ላይ ካለፈው ተለምዷዊ አሰራር የተለየ አንድ ነገር እንዳለ ልብ ሊባል ይገባል፤ ለልዩነቱ ዋናው ምክንያት፣ የአጪርጽሑፎች ሃብት በይነገጹ ተፈጻሚነት የሚኖረው በተጠቃሚው የመገለጫ ገጽ እና በመነሻ ገጹ ላይ መሆኑ ነው፤ ስለሆነም የ‘አዲስ (new
) እና የ‘አርትዕ (edit
) ተግባሮች በአጪርጽሑፎች መቆጣጠሪያ ውስጥ አያስፈልጉንም፤ የ‘ፍጠር (create
) እና የ‘አጥፋ destroy
ተግባሮች ግን ያስፈልጉናል፡፡ ይህ በዝርዝር 13.30 ውስጥ ወደሚታየው፣ የአጪርጽሑፎች ሃብት ማዘዋወሪያዎች ይመረናል፡፡ በዝርዝር 13.30 ውስጥ ያለው ኮድ በሰንጠረዥ 13.2 ላይ የሚታየውን ሙሉየው.ሁ.ማ ማዘዋወሪያዎችን ይሰጣል፣ ይህም ሙሉ የማዘዋወሪያዎች ስብስብ ካሉት ሰንጠረዥ 2.3 ጋር ሲነጻጸር፣ የሙሉ ማዘዋወሪያዎቹን ስብስብ አነስተኛ ንዑስ-ስብስብን ይይዛል። ልክ ነው፣ ይህ ማለት ነገሮችን በቀላሉ የመስራት ጥበብን መጠቀማችን ምን ያህል በነገሩ እንደተካንን የሚያሳይ አንድ ምልክት ነው ማለት ነው፣ በእርግጥ ምዕራፍ 2 ውስጥ የመወጣጫ ስልት ላይ ተመርኩዘን አንዳንድ ነገሮችን ከሰራን ጀምሮ እስካሁን ያለው ጊዜ አጪር ጊዜ አይደለም፣ ከዚህ በኋላ የሱን የተወሳሰበ አሰራር አንፈልግም።
config/routes.rb
Rails.application.routes.draw do
root 'quami_getss#menesha'
get '/erdata', to: 'quami_getss#erdata'
get '/silegna', to: 'quami_getss#silegna'
get '/agignun', to: 'quami_getss#agignun'
get '/temezgeb', to: 'teteqamis#new'
get '/gba', to: 'sessions#new'
post '/gba', to: 'sessions#create'
delete '/wta', to: 'sessions#destroy'
resources :teteqamis
resources :meleya_magberyas, only: [:edit]
resources :meda_masjemers, only: [:new, :create, :edit, :update]
resources :achrtshufs, only: [:create, :destroy]
end
የሃ.ጽ.ማ.ስ መጠይቅ | ዓ.አ.ሃ.አ | ተግባር | ስዩም ማዘዋወርያ |
POST |
/achrtshufs | create |
achrtshufs_path |
DELETE |
/achrtshufs/1 | destroy |
achrtshuf_path(achrtshuf) |
በአጪርጽሑፎች መቆጣጠሪያ ውስጥ አንዳንድ የመዳረሻ መቆጣጠሪያዎችን በማከል፣ የአጪርጽሑፎች ሃብት ብልጸጋችንን እንጀምራለን፡፡ በተለይም፣ አጪርጽሑፎችን በተዛማጅ ተጠቃሚዎቻቸው በኩል ስለምንደርስ የ‘ፍጠርም (create
) ሆነ የ‘አጥፋ (destroy
) ተግባር ተጠቃሚዎች ግዴታ እንዲገቡ ሊጠይቅ ይገባል፡፡
የመግባት ሁኔታን የሚያስገድደው ፈተና፣ ካሁን በፊት ለተጠቃሚዎች መቆጣጠሪያ ከጻፍነው ፈተና ጋር ይመሳሰላል (ዝርዝር 10.20 እና ዝርዝር 10.61)። በዝርዝር 13.31 ላይ እንደሚታየው፣ ትክክለኛውን መጠይቅ ለእያንዳንዱ ተግባር በመስጠት፣ የአጪርጽሑፉ ብዛት እንዳልጨመረ እና ውጤቱም ወደ መግቢያ ዓ.አ.ሃ.አው ማዟዟር መሆኑን እናረጋግጣለን።
test/controllers/achrtshufs_controller_test.rb
require "test_helper"
class AchrtshufsControllerTest < ActionDispatch::IntegrationTest
def setup
@achrtshuf = achrtshufs(:weba)
end
test "ባልገባበት ጊዜ መፍጠር ማዟዟር አለበት" do
assert_no_difference 'Achrtshuf.count' do
post achrtshufs_path, params: { achrtshuf:
{ yizet: "ወባ ፊት የነሳው ሰውየ ቡዳ እንዳይበላኝ አለ።" } }
end
assert_redirected_to gba_url
end
test "ባልገባበት ጊዜ ማጥፋት ማዟዟር አለበት" do
assert_no_difference 'Achrtshuf.count' do
delete achrtshuf_path(@achrtshuf)
end
assert_redirected_to gba_url
end
end
በዝርዝር 13.31 ውስጥ ያሉት ፈተናዎች ለማለፍ የሚያስፈልጋቸውን ኮድ ለመጻፍ፣ መጀመሪያ በአፕልኬሽኑ ኮድ ላይ አንድ ትንሽ የኮድ ማጣርት ስራን ይጠይቃል። በክፍል 10.2.1 ላይ የ‘ግብ_ተጠቃሚ (gb_teteqami
) ዘዴ የሚጠራውን አንድ ቅድመአጣሪ በመጠቀም የግባት መስፈርቱን እንዳስገደድን አስታውሱ (ዝርዝር 10.15)፡፡ በዚያን ጊዜ ይህን ዘዴ በተጠቃሚዎች መቆጣጠሪያ ውስጥ ብቻ ፈልገነው ነበር፣ አሁን ግን በአጪርጽሑፎች መቆጣጠሪያ ውስጥም ያስፈልገናል፣ ስለሆነም የሁሉም መቆጣጠሪያዎች መሰረተ ክፍል ወደሆነው ማለት ወደ አፕልኬሽን መቆጣጠሪያው እናሻግረዋለን (ክፍል 4.4.4)።13 ውጤቱ ደግሞ በዝርዝር 13.32 ውስጥ ይታያል፡፡
gb_teteqami
) ዘዴን ወደ አፕልኬሽን መቆጣጠሪያ ማሸጋገር። ቀይ app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
include SessionsHelper
private
# አንድ የገባ ተጠቃሚን ያረጋግጣል።
def gb_teteqami
unless gebtual?
adrasha_askemtie
flash[:danger] = "እባክዎትን ይግቡ"
redirect_to gba_url
end
end
end
በዚህ ጊዜ የኮድ ድግግሞሽን ለማስወገድ፣ የ‘ግብ_ተጠቃሚ (gb_teteqami
) ዘዴን ከተጠቃሚዎች መቆጣጠሪያው ማስወገድ ይኖርባችኋል (ዝርዝር 13.33)።
gb_teteqami
) ዘዴን ከተጠቃሚዎች መቆጣጠሪያ ማስወገድ። ቀይ app/controllers/teteqamis_controller.rb
class TeteqamisController < ApplicationController
before_action :gb_teteqami, only: [:index, :edit, :update, :destroy]
.
.
.
private
def teteqami_negariaseitoch
params.require(:teteqami).permit(:sim, :emelekt, :password,
:password_confirmation)
end
# ቅድመአጣሪወች
# ትክክለኛውን ተጠቃሚ ያረጋግጣል።
def tkklegna_teteqami
@teteqami = Teteqami.find(params[:id])
redirect_to(root_url) unless ahun_teteqami?(@teteqami)
end
# አስተዳዳሪ ተጠቃሚን ያረጋግጣል።
def astedadari_teteqami
redirect_to(root_url) unless ahun_teteqami.astedadari?
end
end
በዝርዝር 13.32 ውስጥ ካለው ኮድ ጋር፣ የ‘ግብ_ተጠቃሚ (gb_teteqami
) ዘዴ አሁን በአጪርጽሑፎች መቆጣጠሪያ ውስጥ ይገኛል፣ ይህ ማለት ዝርዝር 13.34 ላይ እንደሚታየው፣ የ‘ፍጠር (create
) እና የ‘አጥፋ destroy
ተግባሮችን መቆጣጠሪያው ውስጥ ማከል እና አንድ ቅድመአጣሪን በመጠቀም በነሱ ላይ የመዳረሻ ግደባን ማስቀመጥ እንችላለን ማለት ነው፡፡
app/controllers/achrtshufs_controller.rb
class AchrtshufsController < ApplicationController
before_action :gb_teteqami, only: [:create, :destroy]
def create
end
def destroy
end
end
በዚህ ጊዜ ፈተናው ማለፍ አለበት:-
$ rails test
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
gb_teteqami
) ዘዴን በተጠቃሚዎች መቆጣጠሪያ ውስጥ መተው፣ መጥፎ የሆነበት ምክንያት ለምንድን ነው?
በምዕራፍ 7 ውስጥ፣ በተጠቃሚዎች መቆጣጠሪያ ውስጥ ለ‘ፍጠር (create
) ተግባር አንድ የሃ.ጽ.ማ.ስ ዓስቀምጥ (HTTP POST)
መጠይቅን የሚሰጥ የሃ.ጽ.መ.ቋ ቅጽን በማቅረብ የተጠቃሚ ምዝገባን ተግባራዊ አድርገናል፡፡ አጪርጽሑፍን ለመፍጠር የሚደረገው የአሰራር ሂደትም ከዚሁ ጋር ተመሳሳይ ይሆናል፤ እዚህ ላይ ያለው ዋናው ልዩነት፣ አጪርጽሑፎቹን ለመፍጠር የተለየ አንድ ገጽን አጪርጽሑፎች/አዲስ (/achrtshufs/new) ላይ ከማድረግ ፈንታ በመነሻ ገጹ (ማለትም፣ በስር መንገዱ “/”) ላይ ይህንኑ ማድረጋችን ብቻ ነው፡፡ ይህም በምስል 13.10 ላይ በስእላዊ መግለጫ ላይ ቁልጪ ብሎ ይታያል፡፡
የመነሻ ገጹን መጨረሻ ላይ ስንሰናበተው፣ በምስል 5.8 ላይ እንደሚታየው፣ በአንድ አዝራር ውስጥ “ይመዝገቡ” የሚል ጽሑፍ ብቻ እንደያዘ ነበር። በአንድ የአጪርጽሑፍ መፍጠርያ ቅጽ አውድ ውስጥ፣ አንድ የገባ ተጠቃሚን ብቻ የሚመለከት ስለሆነ፣ የዚህ ክፍል አንዱ ግብ፣ በአንድ ጎብኝ የአገባብ ሁኔታ ላይ በመመርኮዝ የተለያዩ የመነሻ ገጽ ስሪቶችን ማስተናገድ ይሆናል፡፡ ይህንን ከዚህ በታች በዝርዝር 13.37 ላይ ተግባራዊ እናደርጋለን፡፡
ከተጠቃሚ አፈጣጠር ጋር ተመሳሳይ የሆነውን የአጪርጽሑፍ አፈጣጠር ለመጀመር፣ በአጪርጽሑፎች የፍጠር (create
) ተግባር እንጀምራለን (ዝርዝር 7.26)፡፡ በዝርዝር 13.36 ላይ እንደሚታየው፣ ዋናው ልዩነት አጪርጽሑፉን ለ‘መፍጠር/ለ‘መገንባት (build
) የተጠቃሚ እና የአጪርጽሑፉ ማሕበርን መጠቀሙ ላይ ነው፡፡ እዚህ ላይ በ‘አጪርጽሑፎች_ነጋሪአሴቶች (achrtshuf_negariaseitoch
) በኩል የጠንካራ ሰሚአሴት አጠቃቀምን አስተውሉ፤ ይህ የአጪርጽሑፍ የይዘት (yizet
) ባሕሪ ብቻ በድር በኩል እንዲሻሻል ይፈቅዳል፡፡
create
) ተግባር። app/controllers/achrtshufs_controller.rb
class AchrtshufsController < ApplicationController
before_action :gb_teteqami, only: [:create, :destroy]
def create
@achrtshuf = ahun_teteqami.achrtshufs.build(achrtshuf_negariaseitoch)
if @achrtshuf.save
flash[:success] = "አጪርጽሑፍ ተፈጥሯል!"
redirect_to root_url
else
render 'quami_getss/menesha'
end
end
def destroy
end
private
def achrtshuf_negariaseitoch
params.require(:achrtshuf).permit(:yizet)
end
end
አጪርጽሑፎችን ለመፍጠር አንድ ቅጽን ለመገንባት፣ በዝርዝር 13.37 ውስጥ ያለውን ኮድ እንጠቀማለን፣ ይህም የጣቢያው ጎብኝ፣ በጣቢያው ውስጥ በመግባቱ እና ባለመግባቱ ላይ በመመርኮዝ የተለያየ ሃ.ጽ.መ.ቋን በማቅረብ ያስተናግዳል።
app/views/quami_getss/menesha.html.erb
<% if gebtual? %>
<div class="row">
<aside class="col-md-4">
<section class="የተጠቃሚ_መረጃ">
<%= render 'gru/teteqami_mereja' %>
</section>
<section class="የአጪርጽሑፍ_ቅጽ">
<%= render 'gru/achrtshuf_qts' %>
</section>
</aside>
</div>
<% else %>
<div class="center jumbotron">
<h1 id="እንኳን"> እንኳን ወደ ማሳያ አፕልኬሽን በደህና መጡ! </h1>
<h2>
ይህ <a href="https://www.railstutorial.org/">
የሩቢ ኦን ሬይልስ ስልጠና ትምህርት</a>
ማሳያ ለተባለው አፕልኬሽን፡ የመነሻ ገጽ ነው፡፡
</h2>
<%= link_to "ይመዝገቡ", temezgeb_path, class: "btn btn-lg btn-primary" %>
</div>
<%= link_to image_tag("rails.svg", alt: "የሬይልስ አርማ", width: "200"),
"https://rubyonrails.org/" %>
<% end %>
(በከሆነ-ካልሆነ (if
-else
) የሁኔታ ማጣሪያ መሃል በዛ ያሉ ኮዶችን በአንድ ቦታ መቆለሉ ደስ አይልም፣ እናም አንድ ከፊልን በመፍጠር ይህንን ማስዋቡ፣ ልክ እንደ አንድ መልመጃ ይሆናችሁ ዘንድ ለናንተ ተትቷል (ክፍል 13.3.2.1))።
በዝርዝር 13.37 ውስጥ የተበየነው ገጽ ስራውን እንዲጀምር፣ ሁለት ከፊሎችን መፍጠር እና እነሱን በሚገባቸው ኮድ መሙላት ይኖርብናል፡፡ በዝርዝር 13.38 ላይ እንደሚታየው፣ የመጀመሪያው የመነሻ ገጹ አዲሱ የጎን-አሞሌ ነው።
app/views/gru/_teteqami_mereja.html.erb
<%= link_to amsaya_le(ahun_teteqami, meten: 50), ahun_teteqami %>
<h1><%= ahun_teteqami.sim %></h1>
<span><%= link_to "መገለጫዎን ይመልከቱ", ahun_teteqami %></span>
<span><%= abza(ahun_teteqami.achrtshufs.count, "achrtshuf") %></span>
የመገለጫ የጎን-አሞሌው፣ የአጪርጽሑፎቹን አጠቃላይ ብዛት ለተጠቃሚው እንደሚያሳይ ሁሉ (ዝርዝር 13.24)፣ በዝርዝር 13.38 ውስጥ ያለው የተጠቃሚ መረጃ ከፊልም እንደዛው እንደሚያደርግ አስተውሉ፡፡ ይሁን እንጅ በሁለቱ ገጾች ትይታ ላይ አንድ ትንሽ ልዩነት አለ፤ በመገለጫ የጎን-አሞሌው ውስጥ ያለው “አጪርጽሑፎች” የሚለው ጽሑፍ መለያ ስለሆነ 1 አጪርጽሑፍ ቢኖር “(1) አጪርጽሑፍ” ብሎ ገጹ ላይ ማሳየቱ ትርጉም ይሰጣል። በአሁኑ ሁኔታ ላይ ግን፣ የተጠቃሚው መረጃን የያዘው ከፊል ላይ አንድ አጪርጽሑፍ ብቻ ሲኖር “1 አጪርጽሑፎች” ብሎ ማሳየቱ ትክክል ያልሆነ አረፍተ ነገር ስለሚሆን፣ አንድ አጪርጽሑፍ ሲኖር “1 አጪርጽሑፍ” እና ሁለት አጪርጽሑፎች ሲኖሩ ደግሞ “2 አጪርጽሑፎች” ብሎ በገጹ ላይ እንዲያሳይ፣ ካሁን በፊት በክፍል 7.3.3 ላይ ያየነውን የ‘አብዛ (abza
) ዘዴን እንጠቀማለን።
ቀጥለን፣ በዝርዝር 13.39 ውስጥ ከተጠቃሚ የምዝገባ ቅጽ ጋር ተመሳሳይ የሆነውን (ዝርዝር 7.15)፡ የአጪርጽሑፎች መፍጠርያ ቅጽን እንበይናለን።
app/views/gru/_achrtshuf_qts.html.erb
<%= form_with(model: @achrtshuf, local: true) do |ቅ| %>
<%= render 'gru/shtet_melektoch', object: ቅ.object %>
<div class="መስክ">
<%= ቅ.text_area :yizet, placeholder: "አዲስ አጪርጽሑፍ አዘጋጅ..." %>
</div>
<%= ቅ.submit "አስቀምጥ", class: "btn btn-primary" %>
<% end %>
በዝርዝር 13.39 ውስጥ ያለው ቅጽ ስራ ላይ ከመዋሉ በፊት ሁለት ለውጦችን ማድረግ አለብን፡፡ መጀመሪያ ማድረግ ያለብን ነገር፣ በማሕበሩ በኩል (ከዚህ በፊት እንዳደረግነው) አንድ @አጪርጽሑፍ (@achrtshuf
) የተባለ ቅርፀ ተለዋዋጪን መበየን ይሆናል:-
@achrtshuf = ahun_teteqami.achrtshufs.build
ውጤቱም በዝርዝር 13.40 ውስጥ ይታያል፡፡
menesha
) ተግባሩ ውስጥ አንድ የአጪርጽሑፍ ቅርፀ ተለዋዋጪን ማከል። app/controllers/quami_getss_controller.rb
class QuamiGetssController < ApplicationController
def menesha
@achrtshuf = ahun_teteqami.achrtshufs.build if gebtual?
end
def erdata
end
def silegna
end
def agignun
end
end
በእርግጥ፣ የ‘ዓሁን_ተጠቃሚ (ahun_teteqami
) የሚኖረው ከገባ ብቻ ነው፣ ስለሆነም ምክንያቱ ይሄ ከሆነ ብቻ የ‘@አጪርጽሑፍ (@achrtshuf
) ተለዋዋጪን መበየን ይኖርበታል ማለት ነው።
በዝርዝር 13.39 ውስጥ ያለው ቅጽ ስራ ላይ ከመዋሉ በፊት፣ ሁለተኛ ማድረግ ያለብን ነገር ደግሞ፣ ካሁን በፊት የሰራነውን የስህተት መልእክቶች ከፊልን እንደሚከተለው አድርገን እንዳዲስ መበየን ነው:-
<%= render 'gru/shtet_melektoch', object: ቅ.object %>
በዝርዝር 7.20 ውስጥ የስህተት መልእክቶች ከፊሉ የ‘@ተጠቃሚ (@teteqami
) ተለዋዋጪን በግልጽ እንደሚያመላክት ታስተውሱ ይሆናል፣ አሁን ባለው ሁኔታ ላይ በምትኩ ያለን ግን አንድ የ‘@አጪርጽሑፍ (@achrtshuf
) ተለዋዋጪ ነው፡፡ እነዚህ ሁኔታዎች ላይ አንድ የጋራ መፍትሄን ለመፍጠር ቅ
የተባለውን የቅጹን ተለዋዋጪ ወደ ከፊሉ ማሳለፍ እና የሚዛመደውን ቁሱ በ‘ቅ.ቁስ (ቅ.object
) በኩል መድረስ ይሆናል፣ ስለዚህ በዚህ ውስጥ:-
form_with(model: @teteqami, local: true) do |ቅ|
የ‘ቅ.ቁስ (ቅ.object
) ቁሱ @ተጠቃሚ (@teteqami
) ይሆናል፡፡ በ:-
form_with(model: @achrtshuf, local: true) do |ቅ|
ውስጥ ደግሞ የ‘ቅ.ቁስ (ቅ.object
) ቁሱ @አጪርጽሑፍ (@achrtshuf
) ይሆናል፣ እና ሌላውም በዚሁ መልኩ ይቀጥላል (ወዘተረፈ)።
ቁሱን ወደ ከፊሉ ለማሳለፍ፣ የቁሱ ዋጋን እና ከፊሉ እንዲባል የሚፈለገውን የተለዋዋጪ ስምን እንደ ቁልፍ አድርጎ የያዘ አንድ ተርታን እንጠቀማለን፣ ዝርዝር 13.39 ውስጥ ያለው ሁለተኛው መስመር የሚያከናውነውም ይህንኑ ነው፡፡ በሌላ አማርኛ፣ ቁስ: ቅ.ቁስ (object: ቅ.object
) የሚለው ኮድ አንድ ቁስ (object
) የተባለ ተለዋዋጪን በ‘ስህተት_መልእክቶች (shtet_melektoch
) ከፊል ውስጥ ይፈጥራል ማለት ነው፡፡ እናም በዝርዝር 13.41 ላይ እንደሚታየው፣ አንድ ብጁ የስህተት መልእክትን ለመገንባት ልንጠቀምበት እንችላለን ማለት ነው፡፡
app/views/gru/_shtet_melektoch.html.erb
<% if object.errors.any? %>
<div id="ስህተት_ማብራሪያ">
<div class="alert alert-danger">
ቅጹ <%= abza(object.errors.count, "shtet") %> ስህተት/ቶች ይዟል።
</div>
<ul>
<% object.errors.full_messages.each do |melekt| %>
<li><%= melekt %></li>
<% end %>
</ul>
</div>
<% end %>
በዚህ ጊዜ፣ የፈተና ስብስቡ ቀይመሆኑን ማረጋገጥ ይኖርባችኋል:-
$ rails test
ይህ እያንዳንዱ የስህተት መልእክቶች ከፊልን የሚጠቀም ቅጽን ማዘመን እንዳለብን የሚጠቁም አንድ ፍንጪ ነው፣ እኛም ይህንን ተጠቃሚዎችን ለመመዝገብ (ዝርዝር 7.20)፣ መሕለፈቃሎችን ዳግም ለማስጀመር (ዝርዝር 12.14) እና ተጠቃሚዎችን ለማረም (ዝርዝር 10.2) ተጠቅመንበታል። የዘመኑት ቅጾች በዝርዝር 13.43፣ በዝርዝር 13.45 እና በዝርዝር 13.44 ላይ ይታያሉ፡፡
app/views/teteqamis/new.html.erb
<% provide(:title, 'ይመዝገቡ') %>
<h1 class="ራስጌ1">ይመዝገቡ</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: @teteqami, local: true) do |ቅ| %>
<%= render 'gru/shtet_melektoch', object: ቅ.object %>
<%= ቅ.label :sim, 'ስም' %>
<%= ቅ.text_field :sim, class: 'form-control' %>
<%= ቅ.label :emelekt, 'ኤመልእክት' %>
<%= ቅ.email_field :emelekt, class: 'form-control' %>
<%= ቅ.label :password, 'መሕለፈቃል' %>
<%= ቅ.password_field :password, class: 'form-control' %>
<%= ቅ.label :password_confirmation, "አረጋግጥ" %>
<%= ቅ.password_field :password_confirmation, class: 'form-control' %>
<%= ቅ.submit "ለኔ መለያ ፍጠር", class: "btn btn-primary" %>
<% end %>
</div>
</div>
app/views/teteqamis/edit.html.erb
<% provide(:title, "የተጠቃሚ እርማት") %>
<h1 class="ራስጌ1">መገለጫዎን ያዘምኑ</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: @teteqami, local: true) do |ቅ| %>
<%= render 'gru/shtet_melektoch', object: ቅ.object %>
<%= ቅ.label :sim, 'ስም' %>
<%= ቅ.text_field :sim, class: 'form-control' %>
<%= ቅ.label :emelekt, 'ኤመልእክት' %>
<%= ቅ.email_field :emelekt, class: 'form-control' %>
<%= ቅ.label :password, 'መሕለፈቃል' %>
<%= ቅ.password_field :password, class: 'form-control' %>
<%= ቅ.label :password_confirmation, "አረጋግጥ" %>
<%= ቅ.password_field :password_confirmation, class: 'form-control' %>
<%= ቅ.submit "ለኔ መለያ ፍጠር", class: "btn btn-primary" %>
<% end %>
<div class="amsaya_artot">
<%= amsaya_le @teteqami %>
<a href="http://gravatar.com/emails" target="_blank" rel="noopener">ቀይር</a>
</div>
</div>
</div>
app/views/meda_masjemers/edit.html.erb
<% provide(:title, 'መሕለፈቃል ዳግም ማስጀመርያ') %>
<h1 class="ራስጌ1">መሕለፈቃል ዳግም ማስጀመርያ</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_with(model: @teteqami, url: meda_masjemer_path(params[:id]),
local: true) do |ቅ| %>
<%= render 'gru/shtet_melektoch', object: ቅ.object %>
<%= hidden_field_tag :emelekt, @teteqami.emelekt %>
<%= ቅ.label :password, 'መሕለፈቃል' %>
<%= ቅ.password_field :password, class: 'form-control' %>
<%= ቅ.label :password_confirmation, "አረጋግጥ" %>
<%= ቅ.password_field :password_confirmation, class: 'form-control' %>
<%= ቅ.submit "መሕለፈቃልዎን ያዘምኑ", class: "btn btn-primary" %>
<% end %>
</div>
</div>
በዚህ ጊዜ፣ የፈተና ስብስቡ አረንጓዴመሆን ይኖርበታል:-
$ rails test
በተጨማሪም፣ በዚህ ክፍል ውስጥ የሰራናቸው ሁሉም የሃ.ጽ.መ.ቋ ኮዶች ማለት በምስል 13.11 ላይ እንደሚታየው፣ አንድ አዲስ የአጪርጽሑፍ መፍጠሪያ ቅጽ እና በምስል 13.12 ላይ እንዳለው፣ ማለት ቅጹ አንድ የማስረከብ ስህተት እንዳለው የሚያመለክት የመሳሰሉትን በትክክል ማቅረብ አለባቸው፡፡14
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
if
-else
) ዓረፍተሐሳብ መሃል ላሉት ሁለት ቅርንጫፎች የተለያዩ ከፊሎችን ይጠቀም ዘንድ፣ ኮዱን አጣሩ።
ምንም እንኳን የአጪርጽሑፍ ቅጹ አሁን እየሰራ ቢሆንም፣ ተጠቃሚወች የአንድ የተሳካ ርክብ ውጤትን ግን ወዲያውኑ ማየት አይችሉም፣ ምክንያቱም አሁን የመነሻ ገጹ ምንም ዓይነት አጪርጽሑፍን ስለማያሳይ ነው፡፡ ተጠቃሚዎች ውጤቱን ለማየት ከፈለጉ፣ አንድ ያላቸው አማራጪ ዝርዝር 13.11 ላይ አንድ ብቁ አጪርጽሑፍን ካስረከቡ በኋላ፣ ከዚያ ቅምጡን ለማየት የመገለጫ ገጻቸውን መጎብኘት ይሆናል፣ ይህ ደግሞ ፍጹም የማይመች አሰራር ነው፡፡ በምስል 13.13 ስእላዊ መግለጫ ላይ እንደሚታየው፣ አንድ የተጠቃሚውን ቅምጦች የሚያካትት የአጪርጽሑፎች ቀላቢ ቢኖር በጣም የተሻለ ይሆናል። (በምዕራፍ 14 ውስጥ፣ የአሁኑን ተጠቃሚ፣ የሚከተሉት ተጠቃሚዎች አጪርጽሑፎችን ለማካተት፣ ይህንን ቀላቢ በማጠቃለል ትዊተርን እናስመስለዋለን።)
እያንዳንዱ ተጠቃሚ አንድ ቀላቢ ሊኖረው ስለሚገባ፣ በተጠቃሚ ቅርጸቱ ውስጥ አንድ ቀላቢ (qelabi
) የተባለ ዘዴን እናክላለን፣ ይህም የአሁኑ ተጠቃሚ የሆኑትን ሁሉንም አጪርጽሑፎች መጀመሪያ ላይ ብቻ የሚመርጥ ይሆናል፡፡ በዝርዝር 13.46 ላይ እንደሚታየው፡ በ‘አጪርጽሑፍ (Achrtshuf
) ቅርጸት ላይ የ‘የት (where
) ዘዴን በመጠቀም (ከዚያ በፊት በክፍል 11.3.3.1 ውስጥ ባየነው መሰረት) ይህንን ነገር እናሳካለን፡፡15
app/models/teteqami.rb
class Teteqami < ApplicationRecord
.
.
.
# አንድ ቀደምት-ቀላቢን ይበይናል።
# ለተሟላ ትግበራ "ተጠቃሚዎችን መከተል" ላይ ተመልከቱ፡፡
def qelabi
Achrtshuf.where("teteqami_id = ?", id)
end
private
.
.
.
end
እዚህ ላይ ያለው የጥያቄ ምልክት:-
Achrtshuf.where("teteqami_id = ?", id)
የተ.መ.ቋ መጠይቁ ከመካተቱ በፊት፣ መታወቂያው (id
) በስር በትክክል ማምለጡን ያረጋግጣል፣ በዚህም የተ.መ.ቋ ውግያ (SQL injection) ተብሎ የሚጠራውን አንድ ከባድ የጥበቃ ቀዳዳን ያስወግዳል፡፡ እዚህ ያለው የ‘መታወቂያ (id
) ባሕሪ የያዘው የውሂብ ዓይነት አንድ ሙሉ ቁጥር ነው፣ (ማለትም ራሥ.መታወቂያ (self.id
) ማለት ለተጠቃሚው ብቻ የተሰጠ ልዩ መታወቂያ ማለት ነው)፣ ስለሆነም በዚህ ሁኔታ ላይ የተ.መ.ቋ ውግያ ምንም አይነት አደጋ አያደርስም፣ ይሁን እንጂ ይህን ማድረጉ ምንም የማይጎዳ እና በተ.መ.ቋ ዓረፍተሐሳቦች ውስጥ የተወጉ/የገቡ ተለዋዋጮችን ሁል ጊዜ ማስመለጡ ከወዲሁ የሚደገፍ አንድ ጥሩ የሆነ ልምድ ነው።
አንዳንድ አስታዋይ አንባቢዎች በዚህን ጊዜ፣ በዝርዝር 13.46 ላይ ያለው ኮድ፣ የሚከተለው ኮድን ከመጻፍ ጋር አንድ ዓይነት ውጤት እንደሚሰጥ ሊያስተውሉ ይችሉ ይሆናል:-
def qelabi
achrtshufs
end
በምዕራፍ 14 ላይ የሚያስፈልገውን ሙሉ የሁኔታ ቀላቢ ተፈጥሮዋዊ በሆነ መልኩ የበለጠ አጠቃላይ ያደርግልን ዘንድ፣ በምትኩ በዝርዝር 13.46 ውስጥ ያለውን ኮድ እንጠቀማለን፡፡
በአፕልኬሽኑ ውስጥ ቀላቢውን ለመጠቀም፣ በዝርዝር 13.47 ላይ እንደሚታየው፣ ለአሁኑ ተጠቃሚ መቀለቢያ አንድ ወሬ_ቀላቢ (@werie_qelabi
) የተባለ ቅርፀ ተለዋዋጪን እናክል እና ከዚያ አንድ የሁኔታ ቀላቢ ከፊልን (ዝርዝር 13.48)፣ በመነሻ ገጹ ላይ እናክለለን (ዝርዝር 13.49)፡፡ አሁን ተጠቃሚው ገብቶ እያለ መሄድ የሚያስፈልጋቸው ሁለት መስመር ኮዶች መኖራቸውን እዚህ ላይ አስተውሉ፣ ይህንን ለማድረግም ዝርዝር 13.47 ይህንን ኮድ:-
@achrtshuf = ahun_teteqami.achrtshufs.build if gebtual?
ከዝርዝር 13.40 ወደ ሚከተለው ይቀየራል :-
if gebtual?
@achrtshuf = ahun_teteqami.achrtshufs.build
@werie_qelabi = ahun_teteqami.qelabi.paginate(page: params[:page])
end
በዚህም ሁለቱን መስመሮች በ‘ከሆነ (if
) እና በ‘ጨርስ (end
) ዓረፍተሐሳብ ውስጥ ያሻግራል፡፡
menesha
) ተግባር ውስጥ አንድ የቀላቢ ቅርፀ ተለዋዋጪን ማከል። app/controllers/quami_getss_controller.rb
class QuamiGetssController < ApplicationController
def menesha
if gebtual?
@achrtshuf = ahun_teteqami.achrtshufs.build
@werie_qelabi = ahun_teteqami.qelabi.paginate(page: params[:page])
end
end
def erdata
end
def silegna
end
def agignun
end
end
app/views/gru/_qelabi.html.erb
<% if @werie_qelabi.any? %>
<ol class="አጪርጽሑፎች">
<%= render @werie_qelabi %>
</ol>
<%= will_paginate @werie_qelabi, :previous_label => "ቀዳሚ",
:next_label => "ቀጣይ" %>
<% end %>
የሁኔታ ቀላቢ ከፊሉ አቅርቦቱን በዝርዝር 13.22 ውስጥ ለተበየነው የአጪርጽሑፍ ከፊል ያስተላልፋል:-
<%= render @werie_qelabi %>
እዚህ ላይ እያንዳንዱ የ‘ወሬ_ቀላቢ (@werie_qelabi
) አባል የ‘አጪርጽሑፍ (Achrtshuf
) ክፍል ስላለው፣ ሬይልስ የአጪርጽሑፍ ከፊሉን እንደሚጠራ ጠንቅቆ ያውቃል፡፡ ይህም ሬይልስን በተሰጠው የትይታዎች ማውጫ ምንጪ ውስጥ፣ አንድ ተዛማጅ ስም ያለው ከፊልን እንዲመለከት ያደርገዋል:-
app/views/achrtshufs/_achrtshuf.html.erb
እንደተለመደው የቀላቢ ከፊሉን በማቅረብ፣ ቀላቢውን በመነሻ ገጹ ውስጥ ማከል እንችላለን (ዝርዝር 13.49)፡፡ ይህን በማከናወን የተገኘው ውጤትም እንደተፈለገው በመነሻ ገጹ ላይ የሚያገለግል አንድ የቀላቢ ማሳያ ነው (ምስል 13.14)።
app/views/quami_getss/menesha.html.erb
<% if gebtual? %>
<div class="row">
<aside class="col-md-4">
<section class="የተጠቃሚ_መረጃ">
<%= render 'gru/teteqami_mereja' %>
</section>
<section class="የአጪርጽሑፍ_ቅጽ">
<%= render 'gru/achrtshuf_qts' %>
</section>
</aside>
<div class="col-md-8">
<h3>አጪርጽሑፍ ቀላቢ</h3>
<%= render 'gru/qelabi' %>
</div>
</div>
<% else %>
.
.
.
<% end %>
በዚህ ጊዜ፣ በምስል 13.15 ላይ እንደሚታየው፣ አንድ አዲስ አጪርጽሑፍን መፍጠሩ እንደተጠበቀው ይሰራል፡፡
እዚህ ላይ አንድ እንከን አለ፣ ይህም አንድ ብቁ ያልሆነ አጪርጽሑፍ በሚረከብበት ጊዜ፣ የመነሻ ገጹ አንድ ወሬ_ቀላቢ (@werie_qelabi
) ቅርፀ ተለዋዋጪን ይጠብቃል፡፡ ይህ ተለዋዋጪ ባለመኖሩ ምክንያት፣ በአሁኑ ወቅት ብቁ ያልሆነ አጪርጽሑፍን በምናስረክብ ጊዜ፣ አፕልኬሽኑ ይሰበራል። በዝርዝር 13.50 ውስጥ እንደተመለከተው፣ የዚህ መፍትሄ በአጪርጽሑፎች መቆጣጠሪያ የ‘ፍጠር (create
) ተግባር ውስጥ፣ ያልተሳኩ ርክቦችን የሚያስተናግድ አስፈላጊ የቀላቢ ተለዋዋጪን በቅርንጫፉ ውስጥ መፍጠር ነው፡፡
create
) ተግባር ውስጥ አንድ (ባዶ) የ‘ወሬ_ቀላቢ (@werie_qelabi
) ቅርፀ ተለዋዋጪን ማከል። app/controllers/achrtshufs_controller.rb
class AchrtshufsController < ApplicationController
before_action :gb_teteqami, only: [:create, :destroy]
def create
@achrtshuf = ahun_teteqami.achrtshufs.build(achrtshuf_negariaseitoch)
if @achrtshuf.save
flash[:success] = "አጪርጽሑፍ ተፈጥሯል!"
redirect_to root_url
else
@werie_qelabi = ahun_teteqami.qelabi.paginate(page: params[:page])
render 'quami_getss/menesha'
end
end
def destroy
end
private
def achrtshuf_negariaseitoch
params.require(:achrtshuf).permit(:yizet)
end
end
አለመታደል ሆኖ፣ ገጸቁጥሩ አሁንም በትክክል አይሰራም። ይህ ለምን እንደዛ እንደሆነም አንድ ርዝመቱ ረጅም የሆነ አጪርጽሑፍን በማስረከብ መየት እንችላለን (ምስል 13.16)፡፡
የመነሻ ገጹን ወደታች ስንሸበልል፣ የገጸቁጥር አገናኞችን ማለት “2” እና “ቀጣይ” የሚሉ አገናኞችን እናያለን (ምስል 13.17)፡፡ እዚህ ላይ የ‘ፍጠር (create
) ተግባር በአጪርጽሑፎች መቆጣጠሪያ ውስጥ (ዝርዝር 13.50)፣ ዓ.አ.ሃ.አው /አጪርጽሑፎች?ገጽ=2 (/achrtshufs?page=2) ነው፣ ይህም ጪራሽ ወዳልተፈጠረው የአጪርጽሑፎች ማውጫ (index
) ተግባር ለመሄድ ይሞክራል። በዚህ ምክንያትም፣ ከሁለቱ አገናኞች ውስጥ ማንኛውንም ጠቅ ማድረጉ አንድ የማዟዟር ስህተትን ይሰጣል (ምስል 13.18)፡፡
ከመነሻ ገጹ ጋር የሚዛመዱ ግልጽ የ‘መቆጣጠርያ (controller
) እና ግልጽ የ‘ተግባር (action
) ሰሚአሴቶችን ለ‘ዊል_ገጽቁጥርስጥ (will_paginate
) በመስጠት ይህንን ችግር መፍታት እንችላለን፡፡ ይህ ማለት መቆጣጠሪያ‘ው ተጠቃሚ_ገጾች (quami_getss
) ሲሆን፣ ተግባሩ ደግሞ መነሻ (menesha
) ይሆናል ማለት ነው፡፡16 ውጤቱ በዝርዝር 13.51 ላይ ይታያል፡፡
app/views/gru/_qelabi.html.erb
<% if @werie_qelabi.any? %>
<ol class="አጪርጽሑፎች">
<%= render @werie_qelabi %>
</ol>
<%= will_paginate @werie_qelabi, params: { controller: :quami_getss,
action: :menesha }, :previous_label => "ቀዳሚ", :next_label => "ቀጣይ" %>
<% end %>
በዝርዝር 13.19 ላይ እንደሚታየው፣ በዝርዝር 13.17 ውስጥ አሁን ከሁለቱ አገናኞች ውስጥ ማንኛውንም ጠቅ ማድረጉ የተጠበቀውን ሁለተኛውን ገጽ ያስገኛል።
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
INSERT
) ትእዛዝ ይዘቶች ምንድናቸው?
ተጠቃሚ
ተለዋዋጪን ውሂበጎታው ላይ ከሚገኘው የመጀመሪያ ተጠቃሚ ጋር አዘጋጁ። ከዚያ ይህ:- Achrtshuf.where("teteqami_id = ?", ተጠቃሚ.id)
ከዚህ:- ተጠቃሚ.achrtshufs
እና ከዚህ:- ተጠቃሚ.qelabi
ጋር አንድ መሆኑን አረጋግጡ፡፡ ጠቃሚ ምክር:- በቀጥታ ይህንን:- ==
በመጠቀም ማነጻጸሩ ቀላል ሊሆን ይችላል።
የአጪርጽሑፎች ሃብትን ለመጨረስ የቀረ አንድ ተግባር ቢኖር፣ ቅምጦችን የማጥፋት ችሎታን ማከል ብቻ ነው፡፡ ልክ ተጠቃሚን ለማጥፋት (ክፍል 10.4.2) እንደተጠቀምነው ሁሉ፣ በምስል 13.20 ስእላዊ መግለጫ ላይ እንደሚታየው፣ የ “ሰርዝ” አገናኝን በመጠቀም ይህንን ተግባር እናከናውናለን፡፡ ከዛ ተጠቃሚን ለመሰረዝ ለአስተዳዳሪ ተጠቃሚዎች ብቻ ከተገደበው ስልጣን በተቃራነ መልኩ፣ የመሰረዣ አገናኞቹ በአሁኑ ተጠቃሚ ለተፈጠሩ አጪርጽሑፎች ብቻ የሚሰሩ ይሆናሉ።
የመጀመሪያ ደረጃ ሂደታችን በዝርዝር 13.22 የአጪርጽሑፍ ከፊል ውስጥ አንድ የመሰረዝ አገናኝን ማከል ይሆናል፡፡ ውጤቱ በዝርዝር 13.52 ውስጥ ይታያል፡፡
app/views/achrtshufs/_achrtshuf.html.erb
<li id="achrtshuf-<%= achrtshuf.id %>">
<%= link_to amsaya_le(achrtshuf.teteqami, meten: 50), achrtshuf.teteqami %>
<span class="ተጠቃሚ"><%= link_to achrtshuf.teteqami.sim,
achrtshuf.teteqami %></span>
<span class="ይዘት"><%= achrtshuf.yizet %></span>
<span class="ማህተመጊዜ">
ከ <%= time_ago_in_words(achrtshuf.created_at) %> በፊት ተለጠፈ።
<% if ahun_teteqami?(achrtshuf.teteqami) %>
<%= link_to "ሰርዝ", achrtshuf, method: :delete,
data: { confirm: "እርግጠኛ ነዎት?" } %>
<% end %>
</span>
</li>
ቀጣዩ ሂደት፣ በአጪርጽሑፎች መቆጣጠሪያ ውስጥ አንድ የ‘አጥፋ (destroy
) ተግባርን መበየን ነው፤ ይህም ከዝርዝር 10.58 ውስጥ የተጠቃሚ ስረዛ አሰራር ጋር ተመሳሳይ ነው፡፡ ዋናው ልዩነቱ አንድ ተጠቃሚን በቀጥታ በ‘ተጠቃሚ.ፈልግ (Teteqami.find
) ከመፈለግ ይልቅ፣ በተጠቃሚው ማሕበር በኩል አጪርጽሑፉን መፈለጋችን ነው:-
@achrtshuf = ahun_teteqami.achrtshufs.find_by(id: params[:id])
አንድ ተጠቃሚ የሌላ ተጠቃሚ አጪርጽሑፍን ለመሰረዝ ቢሞክር፣ ይህም በራስሰር ባለመሳካት ላይ ተጨማሪ (ምንም‘ን (nil
) የሚመልስ) የጥብቅ/የደህንነት ጥቅም አለው።
ከውጤቱ የተገኘውን ፍለጋ (find
) በአንድ ትክክለኛ_ተጠቃሚ (tkklegna_teteqami
) ቅድመአጣሪ ውስጥ እናስቀምጠዋለን፣ ይህም የአሁኑ ተጠቃሚ ከተሰጠው መታወቂያ ጋር አንድ አጪርጽሑፍ በትክክል እንዳለው ያረጋግጣል (እና ከሌለው ወደ ስር ዓ.አ.ሃ.አው ያዟዙረዋል)። ውጤቱ በዝርዝር 13.53 ውስጥ ይታያል፡፡
app/controllers/achrtshufs_controller.rb
class AchrtshufsController < ApplicationController
before_action :gb_teteqami, only: [:create, :destroy]
before_action :tkklegna_teteqami, only: :destroy
.
.
.
private
def achrtshuf_negariaseitoch
params.require(:achrtshuf).permit(:yizet)
end
def tkklegna_teteqami
@achrtshuf = ahun_teteqami.achrtshufs.find_by(id: params[:id])
redirect_to root_url if @achrtshuf.nil?
end
end
ትክክለኛውን የአጪርጽሑፍ ስረዛን ለማከናወን፣ በአጠቃላይ የዝርዝር 10.58 ተጠቃሚ አሰራረዝ ጥለትን እንከተላለን፣ እሱም ይህንን ይመስላል:-
def destroy
Teteqami.find(params[:id]).destroy
flash[:success] = "ተጠቃሚው ተሰርዟል"
redirect_to teteqamis_url
end
በ‘ተጠቃሚ.ፈልግ(ሴሚአሴቶች[፡መታወቂያ]) (Teteqami.find(params[:id])
) ምትክ @ተጠቃሚ (@teteqami
) (በዝርዝር 13.53 ውስጥ በ‘ትክክለኛ_ተጠቃሚ (tkklegna_teteqami
) ማጣሪያ የተበየነ) ይኖረናል፤ የብልጪችታ መልእክቱ በተመሳሰለ መልኩ አንድ አይነት ነው፣ ማለት በ “አጪርጽሑፉ” ምትክ “ተጠቃሚው” ን መተካት ነው። ውጤቱም እንደሚከተለው ሁኖ ይታያል:-
def destroy
@achrtshuf.destroy
flash[:success] = "አጪርጽሑፉ ተሰርዟል"
# ማዟዟሩ ይወሰናል።
end
በተጠቃሚ እና በአጪርጽሑፉ ክፍል ሁኔታ መካከል ያለው ትልቁ ልዩነት በማዟዟር ሂደቱ ላይ ነው፡፡ ተጠቃሚዎች አጪርጽሑፉቸውን መገለጫ ገጹ ላይም ሆነ፣ መነሻ ገጹ ላይ ሁነው መሰረዝ ስለሚችሉ፣ ተጠቃሚዎችን መጠይቁ ወደ ቀረበበት (referring) ገጽ ማዟዟሩ ምቹ የሆነ አሰራር ነው፤ ስለሆነም ተጠቃሚዎች ሁልጊዜ መጠይቅ ወዳቀረቡበት ገጽ ይዟዟራሉ፡፡ ይህንንም የመጠይቅ.አቅራቢ (request.referrer
) ዘዴን በመጠቀም ማከናወን እንችላለን:-17
redirect_to request.referrer
ይህ ዘዴ በወዳጃዊ ትልልፍ (ክፍል 10.2.3) ውስጥ ጥቅም ላይ ከዋለው የ‘ጠይቅ.የመጀመሪያው_ዓአሃአ (request.original_url
) ተለዋዋጪ ጋር ይዛመዳል፣ እናም በዚህ ሁኔታ ላይ የቀድሞው ዓ.አ.ሃ.አ ማለት ነው።18
ምናልባት በሚገርም ሁኔታ፣ እዚህ ላይ ማስተናገድ የሚገባን ሁለት የጠርዝ ጉዳዮችም አሉ። የመጀመሪያው የማቅረቢያው ዓ.አ.ሃ.አ አንዳንድ ጊዜ በፈተናዎች ውስጥ ምንም (nil
) የመሆኑ ጉዳይ ነው፣ ስለሆነም በዚያ ጉዳይ ላይ ወደ አንድ ነባሪ ዓ.አ.ሃ.አ ማዟዟር ይኖርብናል፡፡ ለዛም የስር ዓ.አ.ሃ.አው እንዲህ እንዲሆን እንመርጣለን:-
if request.referrer.nil?
redirect_to root_url
else
redirect_to request.referrer
end
ሁለተኛው የጠርዝ ጉዳይ በይበልጥ ረቀቅ/ሰወር ያለ ነው፣ እናም አንድ ብቁ ያልሆነ አጪርጽሑፍ ካስረከቡ በኋላ አንድ አጪርጽሑፉን ከመነሻ ገጹ ላይ ለመሰረዝ የመሞከር ጉዳይን ያሳትፋል፡፡19 አንድ አዲስ አጪርጽሑፍን ለመፍጠር ሲሞከር (ዝርዝር 13.39)፣ አፕልኬሽኑ የ‘ዓስቀምጥ (POST)
መጠይቅን ወደ አጪርጽሑፎች_ዓአሃአ (achrtshufs_url
) ይልካል (ሰንጠረዥ 2.3)፡፡ አጪርጽሑፉ ብቁ ካልሆነ አፕልኬሽኑ የመነሻ ገጹን እንዳዲስ ያቀርባል (ዝርዝር 13.36)፣ አለመታደል ሆኖ፣ ተጠቃሚው በዚያ ገጽ ላይ ሆኖ አንድ አጪርጽሑፍን ለመሰረዝ ቢሞክር፣ የሚቀርበው ዓ.አ.ሃ.አ የ‘አጪርጽሑፎች_ዓአሃአ (achrtshufs_url
) ነው፣ እናም ወደኋላ ማዟዟሩ አይሳካም/ይወድቃል (ይህም አንድ መደበኛ የ‘ዓግኝ (GET)
መጠይቅ ነው)፣ የሚወድቅበት ምክንያትም፣ በአሁኑ ጊዜ ከ‘ዓግኝ /አጪርጽሑፎች (GET /achrtshufs
) ጋር የሚዛመድ መዞርያ ስለለለ (ዝርዝር 13.30) ነው።
ቀራቢው ዓ.አ.ሃ.አ ከ‘አጪርጽሑፎች_ዓአሃአ (achrtshufs_url
) ጋር እኩል መሆኑን ለማየት በግልጽ በመሞከር፣ ይህንን ጉዳይ እንፈታዋለን፣ ጉዳዩ ይህ በሚሆን ጊዜም ወደ ስር ዓ.አ.ሃ.አው እናዟዙራለን። አቅራቢው ምንም (nil
) በሚሆንበት ጊዜ ይህ ባህሪ አንድ አይነት ስለሆነ፣ ሁለቱን ጉዳዮች በአንድ ነጠላ የ‘ከሆነ (if
) ውስጥ ማካተት እንችላለን:-
if request.referrer.nil? || request.referrer == achrtshufs_url
redirect_to root_url
else
redirect_to request.referrer
end
ከላይ ያለውን ውይይት ከዝርዝር 13.53 ጋር በአንድ ላይ ማስቀመጡ በዝርዝር 13.54 ውስጥ የተመለከተውን የ‘አጥፋ (destroy
) ተግባር ይሰጣል፡፡
destroy
) ተግባር። app/controllers/achrtshufs_controller.rb
class AchrtshufsController < ApplicationController
before_action :gb_teteqami, only: [:create, :destroy]
before_action :tkklegna_teteqami, only: :destroy
.
.
.
def destroy
@achrtshuf.destroy
flash[:success] = "አጪርጽሑፉ ተሰርዟል"
if request.referrer.nil? || request.referrer == achrtshufs_url
redirect_to root_url
else
redirect_to request.referrer
end
end
private
def achrtshuf_negariaseitoch
params.require(:achrtshuf).permit(:yizet)
end
def tkklegna_teteqami
@achrtshuf = ahun_teteqami.achrtshufs.find_by(id: params[:id])
redirect_to root_url if @achrtshuf.nil?
end
end
በዝርዝር 13.54 ውስጥ ባለው ኮድ፣ የመነሻ ገጹ አሁን የሚሰሩ የመሰረዣ አገናኞች አሉት (ምስል 13.21)፣ ይህንንም ሁለተኛውን ቅምጥ በመሰረዝ ልታረጋግጡ ትችላላችሁ (ምስል 13.22)።
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
DELETE
) ትእዛዝ ይዘቶች ምንድን ናቸው?
redirect_to request.referrer || root_url
አድራሻ (ዓ.አ.ሃ.አ) የ redirect_back(fallback_location: root_url)
አድራሻን (ዓ.አ.ሃ.አን) እንደሚተካ አሳሻችሁን በመጠቀም አረጋግጡ፡፡ (ይህ ዘዴ በሬይልስ 5 የታከለ ዘዴ ነው፡፡)
በክፍል 13.3.4 ውስጥ ካለው ኮድ ጋር፣ የአጪርጽሑፍ ቅርጸቱ እና በይነገጹ ተጠናቋል፡፡ የቀረ ነገር ቢኖር፣ ፈቀዳውን ለማረጋገጥ እና አንድ የአጪርጽሑፍ ውህደት ፈተናውን ማለት ሁሉንም በአንድ ላይ ለመቋጨት አንድ አጪር የአጪርጽሑፍ መቆጣጠሪያ ፈተናን መጽፍ ነው፡፡
በዝርዝር 13.55 ላይ እንደሚታየው፣ ከተለያዩ የአጪርጽሑፍ ባለቤቶች ጋር ጥቂት አጪርጽሑፎችን፣ በአጪርጽሑፎች እቃዎች ውስጥ በማከል እንጀምራለን፡፡ (ለአሁኑ አንዱን እቃ ብቻ እንጠቀማለን፣ ነገር ግን ለወደፊት ማጣቀሻ እንዲሆኑን በማለት ሌሎችንም አክለናል፡፡)
test/fixtures/achrtshufs.yml
.
.
.
gundan:
yizet: "ጉንዳን ደም፣ ዝንብ ቤት የለውም።"
created_at: <%= 2.years.ago %>
teteqami: ermias
tekula:
yizet: "ተኩላ እንደ አንበሳ እጮህ ብላ ተተረተረች።"
created_at: <%= 3.days.ago %>
teteqami: ermias
anbesa:
yizet: "አንበሳ ሳይገድሉ ቆዳውን ያስማማሉ።"
created_at: <%= 10.minutes.ago %>
teteqami: gerie
shiro:
yizet: "አነሰ ስትይ ሽሮ ስትጨምሪ፡ ወፈረ ስትይ ወሃ ስትጨምሪ ሞላ ገነፈለ ወዴት ታማስይ።"
created_at: <%= 4.hours.ago %>
teteqami: gerie
ከዚህ በመቀጠልም፣ በዝርዝር 13.56 ውስጥ እንደሚታየው፣ አንድ ተጠቃሚ የሌሎች ተጠቃሚዎች አጪርጽሑፍን መሰረዝ እንደማይችል እና ትክክለኛ መዟዟርን የሚያረጋግጥ አንድ አጪር ፈተናን እንጽፋለን፡፡
test/controllers/achrtshufs_controller_test.rb
require "test_helper"
class AchrtshufsControllerTest < ActionDispatch::IntegrationTest
def setup
@achrtshuf = (:weba)achrtshufs
end
test "ባልገባበት ጊዜ መፍጠር ማዟዟር አለበት" do
assert_no_difference 'Achrtshuf.count' do
post achrtshufs_path, params: { achrtshuf:
{ yizet: "ወባ ፊት የነሳው ሰውየ ቡዳ እንዳይበላኝ አለ።" } }
end
assert_redirected_to gba_url
end
test "ባልገባበት ጊዜ ማጥፋት ማዟዟር አለበት" do
assert_no_difference 'Achrtshuf.count' do
delete achrtshuf_path(@achrtshuf)
end
assert_redirected_to gba_url
end
test "ለተሳሳተ አጪርጽሑፍ ማጥፋት ማዟዟር አለበት" do
gba_ende(teteqamis(:michael))
achrtshuf = achrtshufs(:gundan)
assert_no_difference 'Achrtshuf.count' do
delete achrtshuf_path(achrtshuf)
end
assert_redirected_to root_url
end
end
በመጨረሻም፣ የሚከተለውን አንድ የውህደት ፈተና እንጽፋለን:- ከገባን በኋላ የአጪርጽሑፍ ገጸቁጥሩ መኖሩን እናረጋግጣለን፤ (ሀ) ብቁ ያልሆነ አጪርጽሑፍን እናስረክባለን፤ (ለ) ብቁ አጪርጽሑፍን እናስረክባለን፤ (ሐ) አንድ ቅምጥን እንሰርዛለን፤ (መ) ከዚያ የሌላውን ተጠቃሚ መገለጫ ገጽን በመጎብኘት የ “ሰርዝ” አገናኝ እንደለለ እናረጋግጣለን፡፡ ይህንን ተግባር ላይ ለመዋል እንደተለመደው፣ አንድ ፈተናን በማመንጨት እንጀምራለን:-
$ rails generate integration_test achrtshufs_beynegets
invoke test_unit
create test/integration/achrtshufs_beynegets_test.rb
ፈተናው በዝርዝር 13.57 ውስጥ ይታያል፡፡ እስኪ ከላይ ከተገለጸው የፈተና አሰራር ሂደት ጋር በዝርዝር 13.12 ውስጥ ያሉት ኮዶችን ማገናኘት ትችሉ እንደሆን ሞክሩ፡፡
test/integration/achrtshufs_beynegets_test.rb
require "test_helper"
class AchrtshufsBeynegetsTest < ActionDispatch::IntegrationTest
def setup
@teteqami = teteqamis(:michael)
end
test "የአጪርጽሑፍ በይነገጽ" do
gba_ende(@teteqami)
get root_path
assert_select 'div.pagination'
# (ሀ) ብቁ ያልሆነ ርክብ
assert_no_difference 'Achrtshuf.count' do
post achrtshufs_path, params: { achrtshuf: { yizet: "" } }
end
assert_select 'div#ስህተት_ማብራሪያ'
assert_select 'a[href=?]', '/?page=2' # ትክክለኛ የገጸቁጥር አገናኝ
# (ለ) ብቁ ርክብ
yizet = "በእውነቱ ይህ አጪርጽሑፍ ሁሉን ነገር አጠቃሎ ያቀርባል"
assert_difference 'Achrtshuf.count', 1 do
post achrtshufs_path, params: { achrtshuf: { yizet: yizet } }
end
assert_redirected_to root_url
follow_redirect!
assert_match yizet, response.body
# (ሐ) ቅምጥን መሰረዝ
assert_select 'a', text: 'ሰርዝ'
first_achrtshuf = @teteqami.achrtshufs.paginate(page: 1).first
assert_difference 'Achrtshuf.count', -1 do
delete achrtshuf_path(first_achrtshuf)
end
# (መ) ሌላ ተጠቃሚን መጎብኘት (የመሰረዣ አገናኞች የሉም)
get teteqami_path(teteqamis(:ermias))
assert_select 'a', text: 'ሰርዝ', count: 0
end
end
በመጀመሪያ የሚሰራ የአፕልኬሽን ኮድን ስለጻፍን፣ ያለምንም ጥርጥር የፈተና ስብስቡ አረንጓዴመሆን አለበት:-
$ rails test
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
test/integration/achrtshufs_beynegets_test.rb
require "test_helper"
class AchrtshufsBeynegetsTest < ActionDispatch::IntegrationTest
def setup
@teteqami = teteqamis(:michael)
end
.
.
.
test "የአጪርጽሑፍ የጎን-አሞሌ ቆጠራ" do
gba_ende(@teteqami)
get root_path
assert_match "#{ይህን_ሙሉ} achrtshufs", response.body
# ተጠቃሚ ከዜሮ አጪርጽሑፍ ጋር
lela_teteqami = teteqamis(:abeba)
gba_ende(lela_teteqami)
get root_path
assert_match "0 achrtshufs", response.body
lela_teteqami.achrtshufs.create!(yizet: "አንድ አጪርጽሑፍ")
get root_path
assert_match ይህን_ሙሉ, response.body
end
end
አሁን ለሁሉም ማለት ከአጪርጽሑፍ ተግባሮች ጋር የሚዛመዱትን ድጋፎች አክለን ስለጨመርን፣ በዚህ ክፍል ውስጥ አጪርጽሑፎች ምስሎችን እና እነዚሁም ጽሑፍን እንደሚያካትቱ እናደርጋቸዋለን፡፡ አንድ ለብልጸጋ አገልግሎት በቂ በሆነ መሰረታዊ ስሪት እንጀምራር እና ከዚያ የምስል ሰቀላው ለምርት ዝግጁ እንዲሆን ለማድረግ፣ አመርቂ የሆኑ ተከታታይ መሻሽሎችን እናክላለን፡፡
ምስል ሰቀላን ለማከል፤ ሁለት የሚታዩ ዋና ነገሮችን ማከልን ያሳትፋል፤ እነሱም አንድ የምስል መስቀያ የቅጽ መስክን እና እራሳቸው የአጪርጽሑፍ ምስሎች ናቸው፡፡ ይህንን በማድረግ የተገኘው የ “Upload image” አዝራር እና የአጪርጽሑፍ ምስል ውጤት፣ በምስል 13.23 ላይ በስእላዊ መግለጫ መልክ ይታያል፡፡
በሬይልስ ውስጥ ፋይሎችን ለመስቀል በጣም አመችው መንገድ፣ ንቅ ማከማቻ የተባለውን አንድ አብሮገነብ ገጸባህሪን መጠቀም ነው፡፡20 ንቅ ማከማቻ አንድ የተሰቀለ ምስልን ለማስተናገድ እና ምስሉን ከመረጥነው አንድ ቅርጸት (ለምሳሌ:- የአጪርጽሑፍ ቅርጸት) ጋር ለማዛመድ ሁኔታዎችን እጅግ ቀላል ያደርጋል። ምንም እንኳን እኛ ንቅ ማከማቻን ምስሎችን ለመስቀል ብቻ የምንጠቀምበት ቢሆንም፣ በውነቱ እሱ ብዙነገሮችን ያጠቃልላል፣ እናም ጥሬ ጽሑፍን እና በርካታ የሁለትዮሽ ፋይሎችንም ሳይቀር ማስተናገድ ይችላል (ለምሳሌ፣ እንደ የድምጽ ፋይሎች እና እንደ የተ.ሰ.ቅ (PDF) ሰነዶች የመሳሰሉ ፋይሎችንም ማስተናገድ ይችላል)።
በንቅ ማከማቻ ሰነድ ላይ እንደተገለጸው፣ ንቅ ማከማቻን ወደ አፕልኬሽናችን ማከሉ፣ አንድ ነጠላ ትእዛዝን የማከል ያህል ቀላል ነገር ነው:-
$ rails active_storage:install
ይህ ትእዛዝ፣ የተያያዙ ፋይሎችን ለማከማቸት አንድ የውሂብ ቅድን የሚፈጥር አንድ የውሂበጎታ ፍልሰትን ይፈጥራል፡፡ እሱ የፈጠራቸውን ነገሮች በሙሉ መመልከት ትችላላችሁ፣ ነገር ግን ይሄ የትኞቹን በጥልቅ ማወቁ አስፈላጊ እና አላስፈላጊ መሆኑን ለይቶ ለማወቅ፣ ቴክኒካዊ ብልሃትን ተግባር ላይ ለማዋል የሚያግዝ አንድ ጥሩ የሆነ ምሳሌ ይሆናል፡፡ በዚህ ሁኔታ ላይ፣ አስፈላጊው ነገር፣ ከንቅ ማከማቻ ጋር የአ.ፕ.በ መተገባበር ነው፣ ይህንንም በአጪር ጊዜ የምናየው ይሆናል፤ እንዴት አድርጎ ይህንን ስራ እንደሚሰራ፣ በዝርዝር ማወቁ በዚህ ጊዜ ለኛ አስፈላጊ ነገር ስላልሆነ፣ ስለሱ ብዙ ልታስቡበት አይገባም። እሱን ለማዘጋጀት አንድ ማድረግ ያለብን ነገር ቢኖር፣ ፍልሰቱን ማካሄድ ብቻ ይሆናል (የትም ፍጪው ዱቄቱን አምጪው ነው ነገሩ):-
$ rails db:migrate
ከንቅ ማከማቻ አ.ፕ.በ የምንፈልገው የመጀመሪያው ክፍል የ‘አንድ_ተያያዝ_አለው (has_one_attached
) ዘዴን ሲሆን፣ ይህም አንድ የተሰቀለ ፋይልን ከአንድ ከተሰጠ ቅርጸት ጋር እንድናዛምድ ያስችለናል፡፡ እናም በእኛ ሁኔታ ይህንን ተግባር ላይ ለማዋል፣ በዝርዝር 13.60 ላይ እንደሚታየው፣ ምስል (msl
) ብለን እንጠራው እና ከአጪርጽሑፍ ቅርጸቱ ጋር እናዛምደዋለን፡፡
app/models/achrtshuf.rb
class Achrtshuf < ApplicationRecord
belongs_to :teteqami
has_one_attached :msl
default_scope -> { order(created_at: :desc) }
validates :teteqami_id, presence: true
validates :yizet, presence: true, length: { maximum: 140 }
end
አፕልኬሽናችንን ለአንድ አጪርጽሑፍ አንድ ምስል ብቻ እንዲቀበል አድርገን እንነድፈዋለን፣ ነገር ግን ንቅ ማከማቻ ብዙ_ተያያዝ_አለው (has_many_attached
) የተባለ አንድ ሁለተኛ አማራጪንም ይሰጣል፣ ይህም በርካታ ፋይሎችን ወደ አንድ ንቅ ማከማቻ ቁስ ለማያያዝ ያገለግላል፡፡
በምስል 13.23 ላይ እንደሚታየው፣ በመነሻ ገጹ ላይ ምስል ሰቀላን ለማካተት፣ በዝርዝር 13.61 ውስጥ እና በምስል 13.24 ላይ እንደሚታየው፣ በአጪርጽሑፍ ቅጽ ውስጥ አንድ የፋይል_መስክ (file_field
) መለያን ማካተት ይኖርብናል፡፡
app/views/gru/_achrtshuf_qts.html.erb
<%= form_with(model: @achrtshuf, local: true) do |ቅ| %>
<%= render 'gru/shtet_melektoch', object: ቅ.object %>
<div class="መስክ">
<%= ቅ.text_area :yizet, placeholder: "አዲስ አጪርጽሑፍ አዘጋጅ..." %>
</div>
<%= ቅ.submit "አስቀምጥ", class: "btn btn-primary" %>
<span class="ምስል">
<%= ቅ.file_field :msl %>
</span>
<% end %>
በመጨረሻም፣ ምስሉን አዲስ ወደተፈጠረው የአጪርጽሑፍ ቁስ ለማከል፣ የአጪርጽሑፎች መቆጣጠሪያውን ማዘመን ይኖርብናል፡፡ በአጪርጽሑፎች መቆጣጠሪያ የ‘ፍጠር (create
) ተግባር ውስጥ የተጫነውን ምስል፣ ከ‘@አጪርጽሑፍ (@achrtshuf
) ቁስ ጋር የሚያያይዘውን፣ ማለት በንቅ ማከማቻ አ.ፕ.በ የተሰጠውን የ‘አያይዝ (attach
) ዘዴን በመጠቀም፣ ይህንን በይነገጽ ተግባራዊ ማድረግ እንችላለን፡፡ ሰቀላው እንዲያልፍ ለመፍቀድ፣ በድር በኩል እንዲሻሻሉ በተፈቀደላቸው የባሕሪዎች ዝርዝር ውስጥ ምስል‘ን (:msl
) ለማከል የ‘አጪርጽሑፎች_ነጋሪአሴቶች (achrtshuf_negariaseitoch
) ዘዴን ማዘመን አለብን፡፡ ውጤቱም በዝርዝር 13.62 ላይ ይታያል፡፡
msl
) ማከል። app/controllers/achrtshufs_controller.rb
class AchrtshufsController < ApplicationController
before_action :gb_teteqami, only: [:create, :destroy]
before_action :tkklegna_teteqami, only: :destroy
def create
@achrtshuf = ahun_teteqami.achrtshufs.build(achrtshuf_negariaseitoch)
@achrtshuf.msl.attach(params[:achrtshuf][:msl])
if @achrtshuf.save
flash[:success] = "አጪርጽሑፍ ተፈጥሯል!"
redirect_to root_url
else
@werie_qelabi = ahun_teteqami.qelabi.paginate(page: params[:page])
render 'quami_getss/menesha'
end
end
def destroy
@achrtshuf.destroy
flash[:success] = "አጪርጽሑፉ ተሰርዟል"
if request.referrer.nil? || request.referrer == achrtshufs_url
redirect_to root_url
else
redirect_to request.referrer
end
end
private
def achrtshuf_negariaseitoch
params.require(:achrtshuf).permit(:yizet, :msl)
end
def tkklegna_teteqami
@achrtshuf = ahun_teteqami.achrtshufs.find_by(id: params[:id])
redirect_to root_url if @achrtshuf.nil?
end
end
በዝርዝር 13.63 ላይ እንደሚታየው አንዴ ምስሉ ከተሰቀለ በኋላ፣ በአጪርጽሑፍ ከፊል ውስጥ የ‘ምስል_መለያ (image_tag
) ረጅን በመጠቀም ተዛማጁን የአጪርጽሑፍ ምስል (achrtshuf.msl
) ማቅረብ እንችላለን፡፡ ምስል በማይኖርበት ጊዜ፣ የምስል መለያ እንዳይታይ ለመከላከል፣ አንድ ተያይዟልን? (attached?
) የተባለ የቡልየን ዘዴን እንደተጠቀምን አስተውሉ።
app/views/achrtshufs/_achrtshuf.html.erb
<li id="achrtshuf-<%= achrtshuf.id %>">
<%= link_to amsaya_le(achrtshuf.teteqami, meten: 50), achrtshuf.teteqami %>
<span class="ተጠቃሚ"><%= link_to achrtshuf.teteqami.sim,
achrtshuf.teteqami %></span>
<span class="ይዘት">
<%= achrtshuf.yizet %>
<%= image_tag achrtshuf.msl if achrtshuf.msl.attached? %>
</span>
<span class="ማህተመጊዜ">
ከ <%= time_ago_in_words(achrtshuf.created_at) %> በፊት ተለጠፈ።
<% if ahun_teteqami?(achrtshuf.teteqami) %>
<%= link_to "ሰርዝ", achrtshuf, method: :delete,
data: { confirm: "እርግጠኛ ነዎት?" } %>
<% end %>
</span>
</li>
አንድ አጪርጽሑፍን ከአንድ ምስል ጋር የመስራቱ ውጤት በምስል 13.25 ላይ ይታያል፡፡ እንደዚህ ያሉ ነገሮች በትክክል ሲሰሩ፣ ሁል ጊዜ እገረማለሁ፣ ነገር ግን በትክክል እንደሚሰሩ ማረጋገጫው ይሄው! (ለምስል መስቀያው፣ ቢያንስ አንድ ራስሰሬ የሆነ መሰረታዊ ፈተና መጻፉ ጥሩ ሃሳብ ነው፣ ይህም ልክ እንደ አንድ መልመጃ ይሆናችሁ ዘንድ፣ ለናንተ ተትቷል (ክፍል 13.4.1.1)።)
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
ይህን_ሙሉ
የሚል ጽሑፍ ያለባቸው ማረጋገጫዎች፣ በመነሻ ገጹ ላይ አንድ የፋይል መስቀያ መስክ እና በብቁ ርክብ ምክንያት አንድ የምስል ባሕሪ እንደሚኖር ያረጋግጣሉ። በፈተና ውስጥ የእቃዎች ፋይልን ለመጫን ልዩ የሆነውን የ‘እቃ_ፋይል_ሰቃይ (fixture_file_upload
) ዘዴን እንደተጠቀምን አስተውሉ፡፡21 ጠቃሚ ምክር:- የአንድ የ‘ምስል (msl
) ባሕሪ ብቃትን ለማረጋገጥ፣ ከብቁ ርክብ በኋላ፣ በፍጠር (create
) ተግባር ውስጥ አጪርጽሑፍን ለመድረስ፣ በክፍል 11.3.3 ውስጥ የተጠቀሰውን የ‘መድብ (assigns
) ዘዴን ተጠቀሙ፡፡
$ curl -o test/fixtures/kitten.jpg -OL https://cdn.learnenough.com/kitten.jpg
test/integration/achrtshufs_beynegets_test.rb
require "test_helper"
class AchrtshufsBeynegetsTest < ActionDispatch::IntegrationTest
def setup
@teteqami = teteqamis(:michael)
end
test "የአጪርጽሑፍ በይነገጽ" do
gba_ende(@teteqami)
get root_path
assert_select 'div.pagination'
assert_select 'input[type=ይህን_ሙሉ]'
# (ሀ) ብቁ ያልሆነ ርክብ
assert_no_difference 'Achrtshuf.count' do
post achrtshufs_path, params: { achrtshuf: { yizet: "" } }
end
assert_select 'div#ስህተት_ማብራሪያ'
assert_select 'a[href=?]', '/?page=2' # ትክክለኛ የገጸቁጥር አገናኝ
# (ለ) ብቁ ርክብ
yizet = "በእውነቱ ይህ አጪርጽሑፍ ሁሉን ነገር አጠቃሎ ያቀርባል"
msl = fixture_file_upload('test/fixtures/kitten.jpg', 'image/jpeg')
assert_difference 'Achrtshuf.count', 1 do
post achrtshufs_path, params: { achrtshuf:
{ yizet: yizet, msl: msl } }
end
assert ይህን_ሙሉ.msl.attached?
assert assigns(:achrtshuf).msl.attached?
assert_redirected_to root_url
follow_redirect!
assert_match yizet, response.body
# (ሐ) ቅምጥን መሰረዝ
assert_select 'a', text: 'ሰርዝ'
first_achrtshuf = @teteqami.achrtshufs.paginate(page: 1).first
assert_difference 'Achrtshuf.count', -1 do
delete achrtshuf_path(first_achrtshuf)
end
# (መ) ሌላ ተጠቃሚን መጎብኘት (የመሰረዣ አገናኞች የሉም)
get teteqami_path(teteqamis(:ermias))
assert_select 'a', text: 'ሰርዝ', count: 0
end
.
.
.
end
በክፍል 13.4.1 ውስጥ ያለው የምስል መስቀያ ኮድ አንድ ጥሩ ጅማሬ ይኑረው እንጅ፣ የተወሰኑ ገደቦች ግን የሉትም፡፡ ለምሳሌ ያየን እንደሆን፣ በሚሰቀል ፋይል ላይ ምንም ዓይነት ገደብን አያስገድድም፣ ይህም ተጠቃሚዎች መጠኑ ትልቅ ወይም አይነቱ ብቁ ያልሆነ ፋይልን ለመስቀል በሚሞክሩበት ጊዜ በአፕልኬሽኑ ላይ ችግር ሊያስከትል ይችላል፡፡ ይህን ጉድለት ለማስተካከል፣ ለምስል መጠን እና ቅርጸት ማረጋገጫዎችን እናክላለን፡፡
ይህ ጽሑፍ እስከተጻፈበት ጊዜ ድረስ እንደሚታወቀው፣ ንቅ ማከማቻ እንደ የቅርጸት እና የመጠን ማረጋገጫዎች ለመሳሰሉት ነገሮች በተፈጥሮው ድጋፍ አይሰጥም (ይህም በጣም የሚያስገርም ነው)፤ ይሁን እንጂ ብዙውን ጊዜ ምክንያቱ ይሄ በሚሆንበት ጊዜ፣ ይህንኑ ክንዋኔ ለእኛ የሚያክል አንድ እንቁ አለ (ዝርዝር 13.66)።
Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem 'rails', '6.1.4.1'
gem 'active_storage_validations', '0.8.9'
gem 'bcrypt', '3.1.13'
.
.
.
ከዚያ የጠቅል-ጫን (bundle install
) ትእዛዝን አስኪዱ:-
$ bundle _2.2.17_ install
የእንቁው ሰነድ ላይ የተመለከተውን መመሪያ በመከተል፣ የ‘ይዘት_አይነቱ‘ን (content_type
) እንደሚከተለው አድርገን በመመርመር፣ የምስሉን ቅርጸት ማረጋገጥ እንደምንችል እናያለን:-
content_type: { in: %w[image/jpeg image/gif image/png],
message: "ብቁ የምስል ቅርጸትን መያዝ አለበት።" }
ይህ ምስሉ ሚሜ (MIME) ተብሎ በሚጠራው የፋይል ዓይነት የተደገፈ ቅርጸት መያዙን ያረጋግጣል፡፡ (ይህንን:- %w[]
የድርድር-ገንቢ አገባብ፣ በክፍል 6.2.4 ውስጥ ድርድር ለመስራት እንደተጠቀምንበት አስታውሱ፡፡)
በተመሳሳይ መልኩ፣ የፋይሉን መጠን በዚህ መልኩ ማረጋገጥ እንችላለን:-
size: { less_than: 5.megabytes,
message: "ከ 5ሜባ በታች መሆን አለበት፡፡" }
ይህ ከዚህ በፊት በጊዜ (Time) ረጅ አውድ ውስጥ ያየነው አንድ አገባብን በመጠቀም፣ አንድ የ 5 ሜጋባይት ክልልን ያስቀምጣል (ሳጥን 9.1)፡፡
እነዚህን ማረጋገጫወች በአጪርጽሑፍ ቅርጸት ውስጥ ማከሉ፣ ዝርዝር 13.67 ውስጥ ያለውን ኮድ ይሰጣል፡፡
app/models/achrtshuf.rb
class Achrtshuf < ApplicationRecord
belongs_to :teteqami
has_one_attached :msl
default_scope -> { order(created_at: :desc) }
validates :teteqami_id, presence: true
validates :yizet, presence: true, length: { maximum: 140 }
validates :msl, content_type: { in: %w[image/jpeg image/gif image/png],
message: "ብቁ የምስል ቅርጸትን መያዝ አለበት።" },
size: { less_than: 5.megabytes,
message: "ከ 5ሜባ በታች መሆን አለበት፡፡" }
end
አንድ መጠኑ ትልቅ እና የፋይል አይነቱ ብቁ ያልሆነ ምስልን ለመስቀል የተደረገ ሙከራ ያስከተለው ውጤት፣ በምስል 13.26 ላይ ይታያል። (ይህ የተደረገው ለውጥ በትክክል ይሰራ ዘንድ፣ የሬይልስ አገልጋያችሁን እንደገና ማስጀመር ሊኖርባችሁ ይችል ይሆናል።)
ከዝርዝር 13.67 ማረጋገጫዎች ጋር አብሮ የሚሄድ፣ ማለት በተገልጋይ በኩል (በአሳሽ በኩል) ለሚሰቀል ምስል፣ የመጠን እና የቅርጸት ማረጋገጫን እናክላለን። አንድ ተጠቃሚ አንድ በጣም ትልቅ የሆነ ምስልን ለመስቀል ከሞከረ አንድ ማስጠንቀቂያን ለመስጠት (ማለት ያልታሰበ የሰቀላ ጊዜን የሚከላከል እና በአገልጋዩ ላይ የሚያጋጥመውን ጪነት ቀለል የሚያደርግ) አንድ ትንሽ ጃቫስክሪፕትን (ማለት በግልጹ ጀኴይሪን) በማከል እንጀምራለን። ውጤቱ በዝርዝር 13.68 ውስጥ ይታያል።22
app/views/gru/_achrtshuf_qts.html.erb
<%= form_with(model: @achrtshuf, local: true) do |ቅ| %>
<%= render 'gru/shtet_melektoch', object: ቅ.object %>
<div class="መስክ">
<%= ቅ.text_area :yizet, placeholder: "አዲስ አጪርጽሑፍ አዘጋጅ..." %>
</div>
<%= ቅ.submit "አስቀምጥ", class: "btn btn-primary" %>
<span class="ምስል">
<%= ቅ.file_field :msl %>
</span>
<% end %>
<script type="text/javascript">
$("#achrtshuf_msl").bind("change", function() {
const size_in_megabytes = this.files[0].size/1024/1024;
if (size_in_megabytes > 5) {
alert("ከፍተኛው የፋይል መጠን 5ሜባ ነው። እባክዎ አንድ አናሳ ፋይል ይምረጡ።");
$("#achrtshuf_msl").val("");
}
});
</script>
ምንም እንኳን የዚህ መጽሐፍ ትኩረት ጃቫስክሪፕትን ማስተማር ባይሆንም፣ ዝርዝር 13.68 ጃቫስክሪፕት ይሄንን ስራ በዚህ ገጽ ለመስራት በዝርዝር 13.61 ቅጽ ላይ ያለውን የ‘አጪርጽሑፍ_ምስል (achrtshuf_msl
) የቅ.ቋ መታወቂያን እንደሚጠቀም ልትገምቱ ትችሉ ይሆናል (በርግጥ እዚህ ላይ ጃቫስክሪፕት የቅ.ቋ መታወቂያን እንደሚጠቀም በዚህ ምልክት:- #
መገመት ይቻላል)፣ (ይህንን ለማወቅ ከፈለጋችሁ፡ ተቆር-ጠቅን (Ctrl-click) ካደረጋችሁ በኋላ፣ “አባል መርምር (inspect element)” ላይ ጠቅ በማድረግ፣ ድራችሁን መመርመር ይኖርባችኋል።) በቅ.ቋ መታወቂያ ውስጥ ያለው አባል በሚቀየርበት ጊዜ፣ በምስል 13.27 ላይ እንደሚታየው፣ የጀኴይሪው ሥልት ይተኮስ እና ፋይሉ በጣም ትልቅ ከሆነ የ‘አስጠንቅቅ (alert
) ዘዴውን ይሰጣል።23
በመጨረሻም፣ በ‘ፋይል_መስክ (file_field
) ግብዓት መለያው ውስጥ ያለውን የ‘ተቀበል (accept
) ሰሚአሴትን በመጠቀም፣ ብቁ ቅርጸቶችን ብቻ ሊፈቅድ እንዲገባው በዝርዝር ለይተን መስጠት እንችላለን (ዝርዝር 13.69)፡፡
app/views/gru/_achrtshuf_qts.html.erb
<%= form_with(model: @achrtshuf, local: true) do |ቅ| %>
<%= render 'gru/shtet_melektoch', object: ቅ.object %>
<div class="መስክ">
<%= ቅ.text_area :yizet, placeholder: "አዲስ አጪርጽሑፍ አዘጋጅ..." %>
</div>
<%= ቅ.submit "አስቀምጥ", class: "btn btn-primary" %>
<span class="ምስል">
<%= ቅ.file_field :msl, accept: "image/jpeg, image/gif, image/png" %>
</span>
<% end %>
<script type="text/javascript">
$("#achrtshuf_msl").bind("change", function() {
const size_in_megabytes = this.files[0].size/1024/1024;
if (size_in_megabytes > 5) {
alert("ከፍተኛው የፋይል መጠን 5ሜባ ነው። እባክዎ አንድ አናሳ ፋይል ይምረጡ።");
$("#achrtshuf_msl").val("");
}
});
</script>
ዝርዝር 13.69 በመጀመሪያ ብቁ የሆኑ የምስል ዓይነቶች ተመርጠው እንዲፈቀዱ ሲያዘጋጅ፣ ማንኛውንም ሌላ አይነት ፋይል ላይ ደግሞ ሽበት ያደርጋል24 (ብቁ ያልሆኑትን የፋይል ዓይነቶች ደግሞ፣ ቀለማቸውን ግራጫማ በማድረግ ተቀባይነት እንዳይኖራቸው ያደርጋቸዋል) (ምስል 13.28)።
ጃቫስክሪፕትን በመጠቀም፣ ብቁ ያልሆኑ ምስሎችን፣ በአንድ አሳሽ በኩል እንዳይሰቀሉ መከላከሉ አንድ ጥሩ ገጸባህሪ ነው፣ ነገር ግን ይህ ዓይነቱ ኮድ፣ አንድ ልክ ያልሆነ የፋይል ዓይነትን ወይም አንድ ትልቅ ፋይልን ለመስቀል አስቸጋሪ እንዲሆን የሚያደርገው፣ አንድ አሳሽን ተጠቅመው ይህንኑ ነገር ለማድረግ ለሚሞክሩ ተጠቃሚዎች ብቻ መሆኑን ልትገነዘቡ ይገባል፤ ብቃት የለለለው የፋይል ዓይነትን ለመስቀል የወሰነ አንድ ተጠቃሚ፣ ሁልጊዜ ለምሳሌ:- ከርል (curl
) የተባለውን አፕልኬሽን በመጠቀም በቀጥታ አንድ የ‘ዓስቀምጥ (POST)
መጠይቅን በመስጠት አላማውን ሊያሳካ ይችላል። ስለሆነም በዝርዝር 13.67 ላይ የተመለከተው ዓይነት ማለት በአገልጋዩ-በኩል የሚያገለግሉ ማረጋገጫዎችን ማካተቱ በጣም አስፈላጊ ይሆናል።
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
በክፍል 13.4.2 ውስጥ ያሉት የምስል መጠን ማረጋገጫዎች ጥሩ ጅማሬዎች ይሁን እንጅ፣ በአሁኑ ወቅት የጣቢያችንን ገጽታ ለመስበር ብቃት ያላቸው ምስሎች እንዲሰቀሉ ይፈቅዳሉ (ምስል 13.29)። ተጠቃሚዎች በሰፈራቸው ዲስክ ውስጥ ያሉ በጣም ትልቅ የሆኑ ምስሎችን እንዲመርጡ መፍቀዱ አመች ቢሆንም፣ ምስሉን በአሳሹ ላይ ከማሳየት በፊት መጠኑን ዳግም መመጠኑ ግን አንድ ጥሩ ሃሳብ ነው።25
ኢሜጅማጂክ (ImageMagick) የተባለውን የምስል ማንቀሳቀሻያ ፕሮግራም በመጠቀም፣ ምስሎችን ዳግም እንመጥናለን፣ ይህንንም በማበልጸጊያ አካባቢያችን ላይ መጫን ይኖርብናል፡፡ (በክፍል 13.4.4 ላይ እንደምናየው፣ ሃረኩን ለስምሪት በምንጠቀምበት ጊዜ፣ የኢሜጅማጂክ ፕሮግራም በምርት ውስጥ ቀድሞውኑ-ተጪኖ እንደመጣ እንመላከታለን፡፡) በደመና ቅ.ማ.አ ላይ እሱን ለመጫን እንደሚከተለው ማድረግ እንችላለን:-
$ sudo apt-get -y install imagemagick
(የደመና ቅ.ማ.አን የማትጠቀሙ ከሆነ ወይም ሌላ ዓይነት የሊኒክስ ስርዓት እየተጠቀማችሁ ከሆነ፣ እንደዚህ ብላችሁ:- “Imagemagick <የናንተን ስርዓተ ክወና>” በማስገባት መጎልጎል ትችላላችሁ፡፡ በማክ ኦኤክስ (macOS) ላይ ሆምብሬው (Homebrew) የተባለው ፕሮግራም ተጪኖ ከሆነ፣ የ‘ብሬው ጫን ኢሜጅማጅክ (brew install
imagemagick
) ትእዛዝን በአንድ ማዘዥያ መስመር ላይ በማስኬድ ፕሮግራሙን መጫን ይቻላል። መላው ከጠፋችሁ፣ ቴክኒካዊ ብልሀታችሁን ተጠቀሙ (ሳጥን 1.2)።)
በመቀጠል፣ የገዛ ስሙ ስራውን በትክክል የሚገልጸውን የ‘ምስል_ማቀናበርያ (image_processing)
እንቁን እና በሩቢ ኢሜጅማጂክን ለማስኬድ የሚያገለግለውን የሚኒ_ማጅክ (mini_magick)
እንቁን ማለት ለምስል ሂደት የሚያገለግሉንን ሁለት እንቁዎች በእንቁ ፋይላችን ውስጥ ማከል ይኖርብናል (ዝርዝር 13.70)፡፡
Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem 'rails', '6.1.4.1'
gem 'image_processing', '1.9.3'
gem 'mini_magick', '4.9.5'
gem 'active_storage_validations', '0.8.9'
.
.
.
ከዚያ እንደተለመደው አድርጎ መጫን ነው:-
$ bundle _2.2.17_ install
እዚህ ላይ ምናልባት የሬይልስ አገልጋያችሁን ዳግም ማስጀመር ያስፈልጋችሁ ይሆናል።
አስፈላጊው ሶፍትዌር ስለተጫነ፣ አሁን የተለወጡ ምስሎችን ለመፍጠር በንቅ ማከማቻ የቀረበውን የተለያየ-መልክ (variant
) ዘዴን ለመጠቀም ዝግጁ ነን፡፡ በተለይም የምስሉ ስፋትም ሆነ ቁመት ከ 500 ፒክስል የማይበልጥ መሆኑን ለማረጋገጥ፣ ዳግም_ምጠናን_ገድብ (resize_to_limit
) የተባለውን አማራጪ ለመጠቀም እንደሚከተለው እናደርጋለን:-
msl.variant(resize_to_limit: [500, 500])
ለአሰራር አመች ይሆን ዘንድ፣ በዝርዝር 13.71 ውስጥ እንደሚታየው፣ ይህንን ኮድ በአንድ የተለየ ማለት ምስል_ማሳያ (msl_masaya
) በተባለ ዘዴ ውስጥ እናስቀምጠዋለን፡፡
app/models/achrtshuf.rb
class Achrtshuf < ApplicationRecord
belongs_to :teteqami
has_one_attached :msl
default_scope -> { order(created_at: :desc) }
validates :teteqami_id, presence: true
validates :yizet, presence: true, length: { maximum: 140 }
validates :msl, content_type: { in: %w[image/jpeg image/gif image/png],
message: "ብቁ የምስል ቅርጸትን መያዝ አለበት።" },
size: { less_than: 5.megabytes,
message: "ከ 5ሜባ በታች መሆን አለበት፡፡" }
# አንድ የተመጠነ የምስል ማሳያን ይመልሳል።
def msl_masaya
msl.variant(resize_to_limit: [500, 500])
end
end
በመጨረሻ፣ በዝርዝር 13.72 ላይ እንደሚታየው፣ የምስል-ማሳያ (msl_masaya
) ዘዴውን በአጪርጽሑፍ ከፊል ውስጥ መጠቀም እንችላለን፡፡
msl_masaya
) መጠቀም። app/views/achrtshufs/_achrtshuf.html.erb
<li id="achrtshuf-<%= achrtshuf.id %>">
<%= link_to amsaya_le(achrtshuf.teteqami, meten: 50), achrtshuf.teteqami %>
<span class="ተጠቃሚ"><%= link_to achrtshuf.teteqami.sim,
achrtshuf.teteqami %></span>
<span class="ይዘት">
<%= achrtshuf.yizet %>
<%= image_tag achrtshuf.msl_masaya if achrtshuf.msl.attached? %>
</span>
<span class="ማህተመጊዜ">
ከ <%= time_ago_in_words(achrtshuf.created_at) %> በፊት ተለጠፈ።
<% if ahun_teteqami?(achrtshuf.teteqami) %>
<%= link_to "ሰርዝ", achrtshuf, method: :delete,
data: { confirm: "እርግጠኛ ነዎት?" } %>
<% end %>
</span>
</li>
ዘዴው በዝርዝር 13.72 ውስጥ ለመጀመሪያ ጊዜ ሲጠራ፣ በዝርዝር 13.71 ውስጥ ያለው የተለያየ-መልክ (variant
) ዳግም ምጠና እንደ አስፈላጊነቱ ተፈጻሚ ይሆን እና የሚቀጥሉ አጠቃቀሞችን ውጤታማ ለማድረግ ይሸጎጣል (Cache)፤ (ማለት በተጠቃሚው አሳሽ ውስጥ ምስሎቹን ያስቀምጣል ማለት ነው)፡፡26 ውጤቱም በምስል 13.30 ላይ እንደሚታየው፣ አንድ በትክክል ዳግም የተመጠነ የምስል ማሳያ ነው፡፡
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
በክፍል 13.4.3 ላይ የበለጸገው የምስል መስቀያ ለማበልጸጊያ በቂ ነው፣ ይሁን እንጅ (ከዚህ በታች በዝርዝር 13.74 ላይ እንደሚታየው) ምስሎችን ለማከማቸት፣ በምርት ላይ ተቀባይነት የለለውን የሰፈር ዲስክን ይጠቀማል። (ከዚያ ባሻገር፣ የሃረኩ የፋይል ማከማቻ ቋሚ ሳይሆን ጊዜያዊ ነው፣ ስለሆነም በሃረኩ ላይ ባሰማራችሁ ቁጥር፣ ከዚያ በፊት የተጫኑ ምስሎች በሙሉ ይሰረዛሉ ማለት ነው።) ስለዚህ ምስሎችን በሃረኩ ላይ ከማስቀመጥ ይልቅ፣ ከአፕልኬሽናችን መቀመጫ ቦታ በተለየ መልኩ፣ ምስሎችን ለማከማቸት አንድ የደመና ማከማቻ አገልግሎትን እንጠቀማለን።
ብዙ የደመና ማከማቻ አገልግሎትን የሚሰጡ የደመና አገልግሎት ድርጅቶች አሉ፣ ይሁን እንጂ እኛ በጣም ታዋቂ የሆነውን የአማዞን የድር አገልግሎቶች (AWS) አካል የሆነውን እና ቀላል የማከማቻ አገልግሎት (S3) በመባል የሚታወቀውን፣ የደመና አገልግሎትን እንጠቀማለን፡፡27
አፕልኬሽናችን በምርት ወቅት የደመና ማከማቻውን እንዲጠቀም ለማዘጋጀት፣ በዝርዝር 13.73 ላይ እንደሚታየው፣ የ‘አድአ-ሶማስ-3ኤሶች (aws-sdk-s3)
28 እንቁን፣ በ‘ምርት (:production
) አካባቢ ውስጥ እናክላለን፡፡
Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem 'rails', '6.1.3.2'
gem 'image_processing', '1.9.3'
gem 'mini_magick', '4.9.5'
gem 'active_storage_validations', '0.8.9'
.
.
.
group :production do
gem 'pg', '1.2.3'
gem 'aws-sdk-s3', '1.87.0', require: false
end
.
.
.
ከዛ አሁንም ጠቅልን (bundle
) አንድ ጊዜ ማስኬድ ነው:-
$ bundle _2.2.17_ install
በዚህ ጊዜ የ S3 አገልግሎትን ለመጠቀም፣ የአ.ድ.አ ስርዓታችሁን ማዋቀር ያስፈልጋችኋል። ይህንን ለማድረግ የሚያስፈልጋችሁ መሰረታዊ ሂደት እንደሚከተለው ይሆናል:-29
የ S3 አገልግሎትን ማዘጋጀቱ ትንሽ ፈታኝ ሊሆን ይችላል (ሳጥን 1.2)፣ ከዚህ በላይ ለተጠቀሱት ቅደም ተከተሎች፣ ተጨማሪ መረጃ ለማግኘት የ S3 ሰነድ ላይ፣ “ሬይልስ 5‘ን [ወይም ከዚያ በላይን] ከአማዞን S3 እና ከንቅ ማከማቻ ጋር ማዘጋጀት” የሚለውን አንብቡ፣ እንዲሁም አስፈላጊ ከሆነ ጎግልን ወይም ስታክኦቨርፍሎውን በመጠቀም ስለዚሁ ጉዳይ የበለጠ መረጃ ልታገኙ ትችላላችሁ፡፡
በምርት ኤመልእክት መዋቅር ላይ እንዳደረግነው ሁሉ፣ (ዝርዝር 11.44)፣ የአ.ድ.አ ቁልፎችን በመሰሉ ተነቃፊ መረጃወች ላይ ሊደርስ የሚችለውን ጥቃት ለማስወገድ፣ የሃረኩ የ‘አካባቢ (ENV
) ተለዋዋጪን እንጠቀማለን፡፡ በክፍል 11.4 እና በክፍል 12.4 ላይ እነዚህ ተለዋዋጮች በሴንድግሪድ ተጨማሪ-አገልግሎት በኩል በራስሰር ተበይነው ነበር፣ በዚህ ሁኔታ ላይ ግን እነዚህን ተለዋዋጮች እኛው እራሳችን በግልጽ መበየን ይኖርብናል፡፡ በእንቁው ማዋቀርያ ሰነድ መሰረት፣ እነዚህ ተለዋዋጮች AWS
የሚል ቅድመ ቅጥያ ያለው ስም መያዝ እንዳለባቸው እንገነዘባለን፣ ስለሆነም የ‘ሃረኩ መዋቅር:አዘጋጅ (heroku config:set
) ዘዴን በመጠቀም ከዚህ በታች እንደሚታየው አድርገን ይህንን ማከናወን እንችላለን:-31
$ heroku config:set AWS_ACCESS_KEY_ID=<የመዳረሻ ቁልፍ> \
AWS_SECRET_ACCESS_KEY=<የምስጢር ቁልፍ> \
AWS_REGION=<ክልል> \
AWS_BUCKET=<የሸንኬሎ ስም>
ከላይ ለቦታ መያዣ ተብለው የገቡ ዋጋወችን፣ በትክክለኛ ዋጋወች መተካት ይኖርባችኋል፡፡ ክልሉን (region) ለማግኘት በ S3 ሰሌዳ ገጽ ላይ ዓ.አ.ሃ.አውን መመርመር ትችላላችሁ (ምስል 13.39)። ምስል 13.39 ላይ መመልከቱ የበለጠ ግልጽ ሊያደርገው ይችላል።
አንዴ የሃረኩ ተለዋዋጮች ከተዘጋጁ በኋላ፣ ቀጣዩ ሂደት ማከማቻ.ያምል (storage.yml
) የተባለውን የማከማቻ አማራጪን ለማዋቀር እነሱን አንድ ልዩ የያምል (YAML) ፋይል ውስጥ መጠቀም ነው፡፡ በዝርዝር 13.74 ውስጥ ያለውን ኮድ በመጠቀም፣ አንድ የአማዞን ማከማቻ አማራጪን መፍጠር እንችላለን፡፡
config/storage.yml
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>
local:
service: Disk
root: <%= Rails.root.join("storage") %>
amazon:
service: S3
access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
region: <%= ENV['AWS_REGION'] %>
bucket: <%= ENV['AWS_BUCKET'] %>
በመጨረሻም፣ በዝርዝር 13.74 ላይ የተበየነው ምርጫ በአንድ ምርት አካባቢ ውስጥ ይሰራ ዘንድ፣ በ‘ምርት.አርቢ (production.rb
) ፋይል ውስጥ በ‘አዋቅር.ንቅ_ማከማቻ.አገልግሎት (config.active_storage.service
) ሰሚአሴት ላይ እናክለዋለን። ውጤቱ በዝርዝር 13.75 ውስጥ ይታያል፡፡
config/environments/production.rb
Rails.application.configure do
.
.
.
# የተሰቀሉ ፋይሎችን በአማዞን አ.ድ.አ ላይ ማከማቸት።
config.active_storage.service = :amazon
.
.
.
end
ከላይ ካለው መዋቅር ጋር፣ ለውጦቻችንን ለማቀላቀል እና ለማሰማራት ዝግጁ ነን:-
$ rails test
$ git add -A
$ git commit -m "የተጠቃሚ አጪርጽሑፎችን ማከል"
የሆነ አፕልኬሽን በሚዋቀርበት ጊዜ፣ በውቅረቱ ላይ ብዙ ስህተቶች ሊያጋጥሙ ስለሚችሉ፣ አፕልኬሽናችን በትክክል መስራቱን ለማረጋገጥ፣ አሁን ያለበትን ቅርንጫፍ ወደ ዋና‘ው (main
) ቅርንጫፍ ከማዋሃዳችን በፊት አሁን ባለበት የርእስ ቅርንጫፍ ላይ እንዳለ በቀጥታ እናሰማራዋለን። ወደ ሃረኩ የሚደረገው ግፊት ላይ ይህን የቅርንጫፍ ስምም እንደሚከተለው አድርገን ማካተት እንችላለን:-
$ git push heroku የተጠቃሚ-አጪርጽሑፎች:main
እንደተለመደው፣ ከዚያ በኋላ ውሂበጎታውን በድጋሜ እናስጀምር እና የናሙና መረጃውን በድጋሜ እንዘራለን:-
$ heroku pg:reset DATABASE
$ heroku run rails db:migrate
$ heroku run rails db:seed
ሃረኩ ከአንድ የተጫነ የኢሜጅማጂክ ፕሮግራም ጋር ስለሚመጣ፣ በምስል 13.40 ላይ እንደሚታየው፣ የተገኘው ውጤትም የተሳከ የምስል ዳግም ምጠና እና በምርት ላይ ምስል ሰቀላ ነው።
የሬይልስ ስልጠናን ለገዙ ሰወች በሙሉ የሁሉም የመልመጃ መልሶች እዚህ ላይ ይገኛሉ።
የሌሎች ሰዎች መልሶችን ለማየት እና የራሳችሁን ደግሞ ለመመዝገብ፣ በሬይልስ ስልጠና ወይም ሁሉንም በበቂ ተማር መድረሻ ጥቅል ላይ ተመዝገቡ፡፡
የአጪርጽሑፎች ሃብትን ስለጨመርን፣ የማሳያ አፕልኬሽናችንን ለማጠናቀቅ ተቃርበናል። ከዚህ በኋላ የሚቀረው ነገር፣ ተጠቃሚዎች እርስ በርሳቸው እንዲከታተሉ የሚያደርግ አንድ ማህበራዊ ንጣፍን ማከል ብቻ ይሆናል። እንደዚህ ያሉ የተጠቃሚ ትስስሮችን እንዴት አድርገን መቀረጽ እንደምንችል እንማራለን፣ እናም የአጪርጽሑፎች ቀላቢ ያለውን ተሳትፎ በምዕራፍ 14 ላይ እንመለከታለን፡፡
ክፍል 13.4.4 ‘ን ዘላችሁ አልፋችሁ ከሆነ፣ ለውጦቻችሁን ማቀላቀላችሁን አረጋግጡ:-
$ rails test
$ git add -A
$ git commit -m "የተጠቃሚ አጪርጽሑፎችን ማከል"
ከዚያ ከ‘ዋና‘ው (main
) ቅርንጫፍ ጋር አዋህዱ:-
$ git checkout main
$ git merge የተጠቃሚ-አጪርጽሑፎች
$ git push
እና በመጨረሻም ወደ ምርት አሰማሩት:-
$ git push heroku
$ heroku pg:reset DATABASE
$ heroku run rails db:migrate
$ heroku run rails db:seed
ይህ ምዕራፍ የመጨረሻውን እና በጣም አስፈላጊ የሆኑትን የእንቁ ጪነቶች፣ ለማየት እንደበቃ ልብ ልትሉት ይገባል፡፡ ለማጣቀሻ ይሆን ዘንድ፣ የመጨረሻው የእንቁ ፋይል (Gemfile
) በዝርዝር 13.76 ውስጥ ይታያል።32
Gemfile
)።
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem 'rails', '6.1.4.1'
gem 'image_processing', '1.9.3'
gem 'mini_magick', '4.9.5'
gem 'active_storage_validations', '0.8.9'
gem 'bcrypt', '3.1.13'
gem 'faker', '2.11.0'
gem 'will_paginate', '3.3.0'
gem 'bootstrap-will_paginate', '1.0.0'
gem 'bootstrap-sass', '3.4.1'
gem 'puma', '5.3.1'
gem 'sass-rails', '6.0.0'
gem 'webpacker', '5.4.0'
gem 'turbolinks', '5.2.1'
gem 'jbuilder', '2.10.0'
gem 'bootsnap', '1.7.2', require: false
group :development, :test do
gem 'sqlite3', '1.4.2'
gem 'byebug', '11.1.3', platforms: [:mri, :mingw, :x64_mingw]
end
group :development do
gem 'web-console', '4.1.0'
gem 'rack-mini-profiler', '2.3.1'
gem 'listen', '3.4.1'
gem 'spring', '2.1.1'
end
group :test do
gem 'capybara', '3.35.3'
gem 'selenium-webdriver', '3.142.7'
gem 'webdrivers', '4.6.0'
gem 'rails-controller-testing', '1.0.5'
gem 'minitest', '5.11.3'
gem 'minitest-reporters', '1.3.8'
gem 'guard', '2.16.2'
gem 'guard-minitest', '2.4.6'
end
group :production do
gem 'pg', '1.2.3'
gem 'aws-sdk-s3', '1.87.0', require: false
end
# ዊንዶውስ የዞን መረጃ ፋይሎችን አያካትትም፤ ስለሆነም፣ በአንድ የቤተኛ የዊንዶውስ ስርዓት
# ላይ፣ ሬይንስን የምታካሂዱ ከሆነ፣ የሚከተለው እንቁ ላይ ያለውን የአስተያየት ምልክት ማስወገድ
# ይኖርባችኋል:-
# gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
has_many
) እና በአጪርጽሑፎች ቅርጸት ውስጥ ባለቤት_ነው (belongs_to
) የተባሉት ዘዴወችን በመጠቀም፣ አንድ ተጠቃሚን ብዙ አጪርጽሑፎች እንዳሉት አድርገን መቅረጽ እንደምንችል፣
has_many
) እና የ‘ባለቤት_ነው (belongs_to
) ዘዴወች ጥምረት በማሕበሩ በኩል የሚሰሩ ዘዴወችን እንደሚሰጡን፣
teteqami.achrtshufs.build(...)
) የተባለው ኮድ፣ ከአንድ ከተሰጠ ተጠቃሚ ጋር የሚዛመድ አንድ አዲስ የአጪርጽሑፍ ቁስን በራስሰር እንደሚመልስ፣
default_scope
) በኩል ነባሪ ቅደም ተከተል ማድረግን እንደሚደግፍ፣
dependent: :destroy
) አማራጪ አንድ ቁስ በሚጠፋበት ጊዜ፣ የሱ ተዛማጆች በሙሉ በአንድ ጊዜ አብረው እንዲጠፉ እንደሚያደርግ፣
where
) ዘዴ የንቅ መዝገብ ምርጫዎችን ለማከናወን ሊያገለግል እንደሚችል፣
build
) ዘዴ ለአዲስ (new
) ዘዴ የቅጽል ስሙ እንደሆነ ትገነዘባላችሁ። ይህንን ለጠቆሙት ክቡር አንባቢ አብደላ ቡድሪን ከልብ አመሰግናለሁ፡፡DESC
)።Faker::Lorem.sentence
የተባለው ዘዴ፣ ከሎረም ኢፕሰም ጽሑፍ የተዘጋጁ አረፍተ ነገሮችን ያቀርባል/ይመልሳል፣ በምዕራፍ 7 ውስጥ እንደተገለጸው፣ ሎረም ኢፕሰም ስለ አመጣጡ ብዙ የሚያስገርም ታሪክ አለው፡፡mulu_arest
) ረጅን ሌሎች ፈተናዎች ላይ ለመጠቀም ከፈለጋችሁ፣ የአፕልኬሽን ረጅውን በ‘ፈተና_ረጅ.አርቢ (test_helper.rb
) ፋይል ውስጥ ማካተት ትችላላችሁ(ለምሳሌ:- እንደ ዝርዝር 3.32 የመሳሰሉትን ለመፈተን ከፈለጋችሁ እንደዛ ማድረግ ይጠበቅባችኋል)፡፡GET
) መጠየቅ ምላሽ የሚሰጥ የለም፡፡ የአድራሻ አሞሌውን የኋሊት መምታት (ወይም ዓ.አ.ሃ.አውን ከአድራሻ አሞሌው ላይ ቀድቶ መገልበጥ) አንድ የማዟዟር ስህተትን ያስከትላል። ምንም እንኳን በአፕልኬሽኑ መደበኛ ሂደት ውስጥ ይህ ችግር በጪራሽ የማያጋጥም ቢሆንም፣ get '/microposts', to: 'staticpageshome'
ማዘዋዋሪያን በ‘አዋቅር/ማዘዋወርያወች/አርቢ (config/routes.rb
) ፋይል ውስጥ በመጨመር ግን ይህ ችግር በጪራሽ እንዳይከሰት መከላከል ትችላላችሁ፡፡where
) እና ከሱ ጋር ተዛማጅ ስለሆኑት ዘዴወች የበለጠ ለመረዳት በሬይልስ መመሪያ ውስጥ የሚገኘውን የ የንቅ ሬከርድ የመጠይቅ በይነገጽን ተመልከቱ።ከሃ.ጽ.ማ.ስ_አቅራቢ (HTTP_REFERER)
ጋር ይዛመዳል። “REFERER” የሚለው ቃል አሁን በዚህ ስልጠና ውስጥ የፊደል ስህተት የተደረገበት እንዳልሆነ ልብ ልትሉ ይገባል፣ በእውነቱ ቃሉ በዝርዝር መግለጫው ላይም በትክክል አልሰፈረም፡፡ ሬይልስ በትክክል በተጻፈው በ‘አቅራቢ (referrer
) ዘዴ አማካይነት፣ አቅራቢውን ዓ.አ.ሃ.አ በመድረስ ይህንን ስህተት ያስተካክላል፡፡\
‘ን በመጠቀም፣ ሁሉንም የውቅረት ቅንጅቶች በአንድ መስመር ላይ በማስቀመጥ፣ ሃረኩ ብዙ ጊዜ፣ እንደገና እንዳይጀምር ለመከላከል ተገቢውን ቅንጅት እናደርጋለን፡፡ ይህንን ለጠቆሙት ክቡር አንባቢ ኒኮ ግሪናሪን ከልብ አመሰግናለሁ፡፡