Какво научих покрай проекта.
Понеже вече няколко съботи и недели си пиша проекта, а и понеже ми хареса идеята на 5тото домашно, реших да споделя какво съм научил покрай проекта. И по-скоро искам да споделя не колко съм бил тъп преди и колко умен сега, ами да разкажа за някои неща в които си счупих главата и (евентуално) опитът ми да бъде полезен на някоя заблудена душа от курса.
Първо, data_mapper. Реших да ползвам датамапер вместо активрекорд, защото някъде (вече напомня къде) прочетох че е по-лесно за noob-ове като мен. Правилен или не, изборът ми е вече факт и всичко работи идеално. Какво обаче ми създаде ядове докато го подкарам?
- Зависимостите. В никой пример който гледах не успях да намеря списък с всички джемове дето ми трябват. В крайна сметка така и не разбрах кои са необходими и кои не. Мога да постна списък с джемовете, които съм инсталирал, но сред тях ще има и някои излишни. Оправих се чрез Google-ване на конкретните съобщения за грешки.
-
Set-ърите на обектите. Оказа се че когато напишете
property :foo, String
се създава сетър и гетър за обекта. Освен поведението, което се очаква да имат, те правят и нещо скрито, което има отношение към заявките в базата. Какъв беше проблемът при мен? Имам клас Период с 2 property-та - от и до. За да поддържам консистентността на обектите, правя валидации в сетърите. И съответно в тях не извиквах супера. Защо - ами защото класът го бях написал преди 2-3 седмици, когато проектът ми не ползваше бази данни (бях още на начално ниво) и съответно супер нямаше. Доста време ми отне да съобразя защо всяка заявка save до базата беше "INSERT INTO "periods" DEFAULT VALUES"
- Някои методи. Датамапера дефинира някои класови методи, сред които методът load, който ми трябваше в един друг клас. Това поне се съобразява лесно.
Тестове.
Не знам защо го подкарах мързеливата, но реших да не чета за някакъв framework за тестване, а да ползвам примера от лекциите, като го доразвия малко. Ето какво ползвам в момента:
require 'data_mapper'
#require all models
Dir["./src/model/*.rb"].each { |file| require file}
DataMapper::Logger.new $stdout, :debug
DataMapper.setup :default, "sqlite:db/test.db"
DataMapper.finalize
DataMapper.auto_migrate!
#DataMapper.auto_upgrade!
class Test
def Test.ok(expected, actual, string = nil)
success = (expected == actual)
if success then
puts "\033[42mok\033[0m"#Green -> ok -> White again
return
else
puts "\033[41mfailed"#Red
puts string if string
puts "Expected #{expected.inspect}, Actual #{actual.inspect}"
puts caller.join "\n"
puts "\033[0m"#Back to white
end
end
end
Настройвам тестова база, защото планирам да тествам и четене/писане в базата.
Тестовете ги пускам с watchr. Хубаво, ама трябва като напиша нов тест (в нов файл), трябва да променям файла watchr.rb. Пък мен не ме кефи. Затова съм си написал следният скрипт
run_all_tests.sh:
ls ./tests/*_test.rb |cat| while read file
do
echo "$file"
ruby $file
done
Конвенцията ми е че всички тестове са в папка test и завършват на _test.rb. Това май не е добра конвенция и скоро ще рефактурирам, но това няма съществено да промени скрипта.
Това добре, но когато създам нов файл трябва да го добавям в watchr.rb. Това в един момент също става досадно. Затова пък си написах следния скрипт
create_watchr.sh:
watchr="watchr.rb"
echo "">$watchr
find|cat|grep .rb| while read file
do
#Remove leading "./"
file=`echo "$file"|sed -r 's/^.{2}//'`
echo "watch(\"$file\") do">>$watchr
echo " system \"clear\"">>$watchr
echo " system \"./tests/run_all_tests.sh\"">>$watchr
echo "end">>$watchr
echo "">>$watchr
done
Този скрипт генерира следният файл
watchr.rb:
watch("watchr.rb.bak") do
system "clear"
system "./tests/run_all_tests.sh"
end
watch("tests/period_test.rb") do
system "clear"
system "./tests/run_all_tests.sh"
end
watch("tests/test.rb") do
system "clear"
system "./tests/run_all_tests.sh"
end
watch("tests/statistic_test.rb") do
system "clear"
system "./tests/run_all_tests.sh"
end
watch("watchr.rb") do
system "clear"
system "./tests/run_all_tests.sh"
end
watch("src/model/period.rb") do
system "clear"
system "./tests/run_all_tests.sh"
end
watch("src/model/statistic.rb") do
system "clear"
system "./tests/run_all_tests.sh"
end
watch("src/model/.statistic.rb.swp") do
system "clear"
system "./tests/run_all_tests.sh"
end
watch("src/util/device_manager.rb") do
system "clear"
system "./tests/run_all_tests.sh"
end
watch("src/util/ticker.rb") do
system "clear"
system "./tests/run_all_tests.sh"
end
watch("main.rb") do
system "clear"
system "./tests/run_all_tests.sh"
end
Тук е моментът да кажа "Да, Кънев, има 2 излишни празни реда в началото и в края" и "Да, Кънев, грозно е". Тъй като мързелът не е добродетел, обещавам да намеря време и да оправя скрипта да не генерира грозен код.
Това е от мен за сега, надявам се да не съм подвел аудиторията на курса с грешни практики.