
ããã«ã¡ã¯ãHabrïŒ å°ãåã«ãç§ã¯è±èŠã®ãã¬ãŒã ã¯ãŒã¯ã«èå³ãæã¡ãé ã®äžã«èœã¡çãããã«ãåå¿è
åãã®å
¬åŒã¬ã€ãã翻蚳ãå§ããŸããã ãããã³ãã¥ããã£ãšå
±æããããšæããŸãã 翻蚳ãåäœã«è¿ã¥ããããšããŸããããç§ã¯äœå®¶ãšããããã¯èªè
ã§ããã翻蚳ã«ã€ããŠã®ã³ã¡ã³ããããã°ãé æ
®ãªãè¡šçŸããŠãã ããã
ãã®ã¬ã€ãã§ã¯ãæåã®ãããžã§ã¯ããè±èŠã§äœæããç°¡åãªWebã¢ããªã±ãŒã·ã§ã³ãäœæããŸãã ãã¬ãŒã ã¯ãŒã¯ã®ãã¹ãŠã®äž»èŠã³ã³ããŒãã³ãã«è§Šãããã¹ãã§äœæããããã¹ãŠãã«ããŒããŸãã
è±èŠãšã¯ïŒ
Hanamiã¯ãå€ãã®ãã€ã¯ãã©ã€ãã©ãªã§æ§æãããRuby MVCãã¬ãŒã ã¯ãŒã¯ã§ãã
ã·ã³ãã«ã§å®å®ããAPIãæå°éã®DSLãããã³å€ãã®è²¬ä»»ãæã€éæ³ã®ãããªæŽç·Žãããã¯ã©ã¹ãããã·ã³ãã«ãªãªããžã§ã¯ãã䜿çšããèšå®ããããŸãã
çŽç²ãªè²¬ä»»ãæã€åçŽãªãªããžã§ã¯ãã䜿çšããã³ã¹ãã¯ãå®åçãªã³ãŒã以äžã®ãã®ã§ãã Hanamiã¯ãäœã¬ãã«ã®å®è£
ã³ãŒããæäŸããããšã«ããããã®äœåãªäœæ¥ãåæžããæ¹æ³ãæäŸããŸãã
ãªãè±èŠã§ããïŒ
è±èŠãéžæããçç±ã¯3ã€ãããŸãã
è±èŠè»œé
è±èŠã³ãŒãã¯æ¯èŒççãã§ãã 圌ã¯ããã¹ãŠã®Webã¢ããªã±ãŒã·ã§ã³ãå¿
èŠãšãããã®ãèªåã§æžããªãããã«ãå¿
èŠãªãã®ã ãã«è²¬ä»»ããããŸãã Hanamiã«ã¯ããã€ãã®ãªãã·ã§ã³ã¢ãžã¥ãŒã«ãä»å±ããŠãããä»ã®ã©ã€ãã©ãªãç°¡åã«æ¥ç¶ã§ããŸãã 建ç¯ã«ãããè±èŠã®æå³ã
ãã¬ãŒã«ãŠã§ã€ãã«é£œããããè±èŠã«æ³šæããŠãã ãã
Hanamiã¯ã³ã³ãããŒã©ãŒã¢ã¯ã·ã§ã³ãã¯ã©ã¹ã«åºã¥ããŠãããããåç¬ã§ç°¡åã«ãã¹ãã§ããŸãã
ãŸããè±èŠã¯ãã€ã³ã¿ã©ã¯ã¿ãŒïŒãŠãŒã¹ã±ãŒã¹ïŒã§ããžãã¹ããžãã¯ãèšè¿°ããããšããå§ãããŸãã
ãã¥ãŒã¯ãã³ãã¬ãŒããšã¯å¥ã§ããããããããã®ããžãã¯ã¯åç¬ã§ãã¹ãããããšãã§ããŸãã
è±èŠã¯ã¹ã¬ããã»ãŒãã§ã
ãã«ãã¹ã¬ããã䜿çšãããšãã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ãåäžãããããšãã§ããŸãã ã¹ã¬ããã»ãŒãã³ãŒããèšè¿°ããããšã¯é£ãããããŸãããHanamiïŒã¢ããªã±ãŒã·ã§ã³å
šäœãŸãã¯ãã®äžéšïŒã¯ã¹ã¬ããã»ãŒãã§ãã
ã¬ã€ã
ãã®ã¬ã€ãã§ã¯ãé«åºŠãªã³ã³ããŒãã³ããšãæ¬æ Œçãªã¢ããªã±ãŒã·ã§ã³ã§ããããæºåããæ¹æ³ïŒæ§æã䜿çšããã¹ãïŒã«ã€ããŠèª¬æããŸãã è°è«ãããæ¶ç©ºã®ãããžã§ã¯ãã¯ãBookshelfããšåŒã°ããŸãã人ã
ãæ¬ãå
±æããæ¬ã賌å
¥ãããªã³ã©ã€ã³ã³ãã¥ããã£ã§ãã
ã¯ããã«
äœæè
ã«ããéäŒæšæ¶
ããã«ã¡ã¯ ãã®ããŒãžãèªãã§ãããªããããããè±èŠã«ã€ããŠãã£ãšç¥ããããšæãã§ãããã ããã§ãšãããããŸãïŒ ãµããŒããããå®å
šã§ãé«éã§ããã¹ãå¯èœãªã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããæ°ããæ¹æ³ãæ¢ããŠãããªããããªãã¯è¯ãæã«ããŸãã è±èŠã¯ããªãã®ãããªäººã®ããã«äœãããŠããŸãã
ããªããå®å
šãªåå¿è
ã§ãããçµéšè±å¯ãªéçºè
ã§ãããã«é¢ä¿ãªããããªãã«èŠåããããšã¯äŸ¡å€ããããŸãã åŠç¿ããã»ã¹ã¯é£ããã§ããã ã éçºã«é¢ããç¹å®ã®èŠéããéçºãã10幎åŸãããªãã®ç¿æ
£ã®ããã€ããç Žãããšã¯é£ãããããããŸããã å€åã¯åžžã«èªåãžã®ææŠã§ãã
äžéšã®æ©èœã¯ç¹ã«å¥åº·ã«èŠããªãããã«èŠããããšããããŸãããããã¯åžžã«ããªãã®æèŠã®åé¡ã§ã¯ãããŸããã ããã¯ãç¿æ
£ãèšèšãã¹ããŸãã¯ãã°ã®åé¡ã§ããå¯èœæ§ããããŸãã åæã®ããã³ãã¥ããã£ãšç§ã¯ãæ¯æ¥è±èŠã®æ¹åã«åªããŠããŸãã
ãã®ã¬ã€ãã§ã¯ãæåã®ãããžã§ã¯ããè±èŠã§äœæããç°¡åãªWebããŒã¹ã®ã¢ããªã±ãŒã·ã§ã³ãbookshelfããäœæããŸãã ãã¬ãŒã ã¯ãŒã¯ã®ãã¹ãŠã®äž»èŠã³ã³ããŒãã³ãã«è§Šãããã¹ãã§äœæããããã¹ãŠãã«ããŒããŸãã
åé¡ãçºçããå Žåãæ··ä¹±ããå Žåã¯ã âããã«ãã£ããã«ãŒã ã«ã¢ã¯ã»ã¹ããŠè³ªåããŠãã ããã ãã€ã§ãåãã§æäŒã£ãŠããã人ãããŸãã
楜ããã§ãã ãã
ã«ã«ã»ã®ãã£
è±èŠã¯ãªãšãŒã¿ãŒ
ãŸããã
å§ããåã«ãããã€ãã®ããšãæ確ã«ããŸãã å§ããããã«ãWebã¢ããªã±ãŒã·ã§ã³éçºã®åºæ¬çãªç¥èãå¿
èŠã ãšããŸãã
Bundler ã Rakeãªã©ã®ããã€ãã®ãã®ã«ç²ŸéããŠããå¿
èŠããããŸããã¿ãŒããã«ã§äœæ¥ãã ModelãViewãControllerãã¿ãŒã³ã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸãã
ãã¥ãŒããªã¢ã«ã®åŸåã§ã¯ã SQLite PostgresqlããŒã¿ããŒã¹ã䜿çšããŸãã
å
ã«é²ãã«ã¯ãRuby 2.3以äžã®äœæ¥ããŒãžã§ã³ãšSQLite 3+ãå¿
èŠã§ãã
æ°ããè±èŠãããžã§ã¯ããäœæããŸããã
Hanamiã§ãããžã§ã¯ããäœæããã«ã¯ããŸãRubygemsãä»ããŠHanami gemãã€ã³ã¹ããŒã«ããå¿
èŠããããŸãã
次ã«ã hanami new
consoleã³ãã³ãã䜿çšããŠãæ°ãããããžã§ã¯ããçæã§ããŸãã
% gem install hanami % hanami new bookshelf
ããã©ã«ãã§ã¯ããããžã§ã¯ãã¯SQLiteã䜿çšããããã«æ§æãããŸãã å®éã®ãããžã§ã¯ãã§ã¯ãããšãã°Postgresãªã©ã®å¥ã®ããŒã¿ããŒã¹ãšã³ãžã³ãæå®ã§ããŸãã
% hanami new bookshelf --database=postgres
ããã«ãããã³ãã³ããå®è¡ããããã©ã«ãã«æ°ããbookshelf
ãã©ã«ããäœæãããŸãã ãããäœãå«ããèŠãŠãã ããïŒ
% cd bookshelf % tree -L 1 . âââ Gemfile âââ Rakefile âââ apps âââ config âââ config.ru âââ db âââ lib âââ public âââ spec 6 directories, 3 files
å°ãªããšãããã«ã€ããŠç¥ã£ãŠããã¹ãããšã¯ä»¥äžã®ãšããã§ãã
Gemfile
ã¯ãRubygemsã®äŸåé¢ä¿ãå®çŸ©ããŸãïŒãã³ãã©ãŒã䜿çšïŒãRakefile
ã¯ãRakeã¿ã¹ã¯ã«ã€ããŠèª¬æããŠããŸããapps
ã¯ã1ã€ä»¥äžã®Rackäºæã¢ããªã±ãŒã·ã§ã³ãå«ãŸããŠããŸãã
ããã§ã Web
ãšåŒã°ããæåã®Hanamiçæã¢ããªã±ãŒã·ã§ã³ãèŠã€ããããšãã§ããŸãã
ããã§ãã³ã³ãããŒã©ãŒããã¥ãŒãã«ãŒãããã¿ãŒã³ãèŠã€ããŸããconfig
ã¯ïŒçªç¶ïŒïŒæ§æãã¡ã€ã«ãå«ãŸããŠããŸãã- ã©ãã¯ãµãŒããŒçšã®
config.ru
ïŒã©ãã¯ã¢ããïŒã db
ã¯ãããŒã¿ããŒã¹ãšç§»è¡ã¹ããŒããå«ãŸããŠããŸããlib
ã¯ããšã³ãã£ãã£ããªããžããªãå«ãããžãã¹ããžãã¯ãšãã¡ã€ã³ã¢ãã«ãå«ãŸããŠããŸããpublic
ã¯ãã³ã³ãã€ã«æžã¿ã®ã¢ã»ãããšéçãã¡ã€ã«ãå«ãŸããŸããspec
ã¯ãã¹ããå«ãŸããŠããŸãã
Bundlerã䜿çšããŠGemfileã§æå®ãããäŸåé¢ä¿ã«é²ã¿ãã€ã³ã¹ããŒã«ããŸãããã 次ã«ããµãŒããŒãéçºã¢ãŒãã§èµ·åããŸãã
% bundle install % bundle exec hanami server
ãããŠ...ã§æåã®è±èŠãããžã§ã¯ãã«äŒããŸããã httpïŒ// localhostïŒ2300 ïŒ ãã©ãŠã¶ã«æ¬¡ã®ãããªãã®ã衚瀺ãããã¯ãã§ãã

è±èŠå»ºç¯
Hanamiã¢ãŒããã¯ãã£ã«ãããåäžã®Rubyããã»ã¹ã«è€æ°ã®HanamiïŒããã³RackïŒã¢ããªã±ãŒã·ã§ã³ãå«ããããšãã§ããŸãã
ãããã®ã¢ããªã±ãŒã·ã§ã³ã¯apps/
ãã£ã¬ã¯ããªã«ãããŸãã ãããã¯ããããããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãã³ã³ãããŒã«ããã«ãããã·ã¥ããŒãããŸãã¯HTTP APIãªã©ã®è£œåã®ã³ã³ããŒãã³ãã«ãªããŸãã
ãããã¯ãã¹ãŠã lib/
ãã©ã«ããŒã«ããããžãã¹ããžãã¯é
ä¿¡ã¡ã«ããºã ã®äžéšã§ãã ããã¯ããã¡ã€ã³ã¢ãã«ãèšè¿°ãããŠããå Žæãçžäºã®çžäºäœçšã§ããã補åã«ãã£ãŠæäŸãããæ©èœãæ§æããŠããŸã ã
è±èŠå»ºç¯ã¯ãããããããã®çŽç²å»ºç¯ã®ã¢ã€ãã¢ã«åŒ·ã圱é¿ãããŸããã
æåã®ãã¹ããæžã
ãã©ãŠã¶ã§èŠãã¢ããªã±ãŒã·ã§ã³ã®éå§ç»é¢ã¯ãåäžã®ã«ãŒãã決å®ãããŸã§ããã©ã«ãã§è¡šç€ºãããããŒãžã§ãã
Hanamiã¯ãWebã¢ããªã±ãŒã·ã§ã³ãéçºããæ¹æ³ãšããŠã è¡åé§ååéçº ïŒBDDïŒãæšå¥šããŠããŸãã æåã®ããŒãžãäœæããåã«ãæåã«ãã®æäœã説æããé«ã¬ãã«ã®ãã¹ããäœæããŸãã
ããã©ã«ãã®Hanamiã¯Behavior-Based DevelopmentïŒBDDïŒããµããŒãããŠãããšããäºå®ã«ããããããã ç¹å¥ãªãã¹ããã¬ãŒã ã¯ãŒã¯ã䜿çšããå¿
èŠã¯ãããŸãããç¹å¥ãªçµ±åãã©ã€ãã©ãªãå¿
èŠãããŸããã
Minitest ïŒããã©ã«ãïŒããå§ããŸããããªãã·ã§ã³--test=rspec.
ãããžã§ã¯ããäœæããå Žåã¯ã RSpecã䜿çšããããšãã§ããŸã--test=rspec.
ãã®åŸãHanamiã¯ãã«ããŒãšãã¡ã€ã«ãã³ãã¬ãŒããçæããŸãã
èŠä»¶ãæºãããŸã
ãã§ã«ãã¹ãããããã©ã®ããã«èœã¡ãããèŠãããšãã§ããŸãã
% rake test Run options: --seed 44759 # Running: F Finished in 0.018611s, 53.7305 runs/s, 53.7305 assertions/s. 1) Failure: Homepage#test_0001_is successful [/Users/hanami/bookshelf/spec/web/features/visit_home_spec.rb:6]: Expected "<!DOCTYPE html>\n<html>\n <head>\n <title>Not Found</title>\n </head>\n <body>\n <h1>Not Found</h1>\n </body>\n</html>\n" to include "Bookshelf". 1 runs, 1 assertions, 1 failures, 0 errors, 0 skips
åæ Œããæãæ¥ãŸããã ãã¹ãã«åæ Œããããã«å¿
èŠãªæ°è¡ã®ã³ãŒãã段éçã«äœæããŸãã
æåã«è¿œå ããå¿
èŠãããã®ã¯ã«ãŒãã§ãïŒ
ã¢ããªã±ãŒã·ã§ã³ã®ã«ãŒãURLãhome
ã³ã³ãããŒã©ãŒã®ã¢ã¯ã·ã§ã³index
ãªãã€ã¬ã¯ãããŸãïŒè©³çŽ°ã«ã€ããŠã¯ã ã«ãŒãã£ã³ã°ã¬ã€ããåç
§ããŠãã ããïŒã ããã§ãã¢ã¯ã·ã§ã³index
äœæã§ããŸãã
ããã¯ç©ºã®ã¢ã¯ã·ã§ã³ã²ãŒã ã§ãããããžãã¯ã¯å«ãŸããŠããŸããã åã¢ã¯ã·ã§ã³ã«ã¯å¯Ÿå¿ãããã¥ãŒããããŸãããã¥ãŒã¯ãã¢ã¯ã·ã§ã³ã«å°çãããªã¯ãšã¹ããžã®å¿çãšããŠè¿ãããå¿
èŠãããRubyãªããžã§ã¯ããè¡šããŸãã
...ããããŸã空ã§ããããã³ãã¬ãŒããã¬ã³ããªã³ã°ããã ãã§ãã ããã©ã«ãã§ã¯ãããã¯erb
ãã¡ã€ã«ã§ããã slim
ãŸãã¯haml
䜿çšãçŠæ¢ãã人ã¯ããŸããã ãã¹ãã«åæ Œããã«ã¯ãä¿®æ£ããå¿
èŠããããŸãã å¿
èŠãªã®ã¯ãæ¬æ£ã®ã¿ã€ãã«ãè¿œå ããããšã ãã§ãã
# apps/web/templates/home/index.html.erb <h1>Bookshelf</h1>
å€æŽãä¿åãããã¹ããå床å®è¡ãããšããã®æéã¯éããŸãã ãããïŒ
Run options:
æ°ããã¢ã¯ã·ã§ã³ãçæããŸã
è±èŠã®äž»èŠãªã³ã³ããŒãã³ãã«ã€ããŠåŠãã ããšã掻çšããŠãæ°ããã¢ã¯ã·ã§ã³ãè¿œå ããŸãããã Bookshelfãããžã§ã¯ãã¯ãæžç±ã®äŒèšãç®çãšããŠããŸãã
æžç±ã«é¢ããæ
å ±ãããŒã¿ããŒã¹ã«ä¿åãããŠãŒã¶ãŒã«ããã管çããæ©äŒãäžããŸãã æåã®ã¹ãããã¯ãã·ã¹ãã ã«ä¿åãããŠãããã¹ãŠã®æžç±ã®ãªã¹ãã衚瀺ããããšã§ãã
æ©èœãã¹ãã®å©ããåããŠãç§ãã¡ãç®æããŠããæ©èœã説æããŸãã
ãã¹ãã¯éåžžã«åçŽã§ãã¯ã©ãã·ã¥ããŸããããã¯ãã¢ãã¬ã¹/books
ãã¢ããªã±ãŒã·ã§ã³ã«ãã£ãŠãŸã èªèãããŠããªãããã§ãã ãããä¿®æ£ããã¢ã¯ã·ã§ã³ã³ã³ãããŒã©ãŒãäœæããŸãã
è±èŠçºé»æ©
Hanamiã«ã¯ãæ°ããæ©èœãæ§æããå®åã³ãŒããæžããããã®ãžã§ãã¬ãŒã¿ãŒãããã€ãä»å±ããŠããŸãã
ã¿ãŒããã«ã«å
¥åïŒ
% bundle exec hanami generate action web books
ãã®ã³ãã³ãã¯ã Webã¢ããªã±ãŒã·ã§ã³ã®ããã¯ã³ã³ãããŒã©ãŒã§æ°ããã¢ã¯ã·ã§ã³ã€ã³ããã¯ã¹ãçæããå¿
èŠããããŸãã
ããã«ããã空ã®ã¢ã¯ã·ã§ã³ããã¥ãŒããã³ãã¬ãŒããæäŸããã apps/web/config/routes.rb
ãžã®ã«ãŒããè¿œå ããapps/web/config/routes.rb
ã
get '/books', to: 'books#index'
ZSHã§ã¯ããšã©ãŒzsh: no matches found: books#index
ãååŸã§ãzsh: no matches found: books#index
ã ãã®å Žåãå¥ã®æ§æãè©ŠããŠãã ããã
% hanami generate action web books/index
ããã§ããã¹ãã«åæ Œããã«ã¯ããã¡ã€ã«apps/web/templates/books/index.html.erb
ã次ã®ããã«ããã ãã§ãã
<h1>Bookshelf</h1> <h2>All books</h2> <div id="books"> <div class="book"> <h3>Patterns of Enterprise Application Architecture</h3> <p>by <strong>Martin Fowler</strong></p> </div> <div class="book"> <h3>Test Driven Development</h3> <p>by <strong>Kent Beck</strong></p> </div> </div>
å€æŽãä¿åãããã¹ãã«åæ Œããããšã確èªããŠãã ããïŒ
ã³ã³ãããŒã©ãŒãšã¢ã¯ã·ã§ã³ã®çšèªã¯æ··ä¹±ãæãå¯èœæ§ããããããæ確ã«ãã䟡å€ããããŸããã¢ã¯ã·ã§ã³ã¯Hanamiã¢ããªã±ãŒã·ã§ã³ã®åºç€ãæ§æããŸãã ã³ã³ãããŒã©ã¯ãããã€ãã®ã¢ã¯ã·ã§ã³ãçµã¿åãããåãªãã¢ãžã¥ãŒã«ã§ãã
äžè¬ã«ãã¢ããªã±ãŒã·ã§ã³ã«ãã³ã³ãããŒã©ãŒããæŠå¿µçã«ååšããŠããã«ãããããããå®éã«ã¯ã¢ã¯ã·ã§ã³ã²ãŒã ã®ã¿ã䜿çšããŸãã
ãžã§ãã¬ãŒã¿ã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ãžã®æ°ãããšã³ããªãã€ã³ããäœæããŸããã ãã ããæ°ãããã³ãã¬ãŒãã«ã¯home/index.html.erb
ãšåã<h1>
ãå«ãŸããŠãããšããäºå®ã«æ³šæãã䟡å€ããããŸãã ãããä¿®æ£ããŸãããã
ã¬ã€ã¢ãŠã
ãã¿ãŒã³ããšã«åãè¡ãç¹°ãè¿ãããšãé¿ããããã«ãã¬ã€ã¢ãŠãã䜿çšã§ããŸãã ãã¡ã€ã«apps/web/templates/application.html.erb
ãéãã次ã®ããã«ããŸãã
<!DOCTYPE HTML> <html> <head> <title>Bookshelf</title> </head> <body> <h1>Bookshelf</h1> <%= yield %> </body> </html>
ããã§ãä»ã®ãã³ãã¬ãŒãããéè€ããè¡ãåé€ã§ããŸãã
ã¬ã€ã¢ãŠãã¯ä»ã®ãã³ãã¬ãŒããšäŒŒãŠããŸãããæšæºãã³ãã¬ãŒããã©ããããããã«äœ¿çšãããŸãã yield
ããŒã¯ãŒãã¯ãéåžžã®ãã³ãã¬ãŒãã®ã³ã³ãã³ãã«çœ®ãæããããŸãã ããã¯ãããããŒãããã¿ãŒãã¡ãã¥ãŒãªã©ã®ã¢ã€ãã ãç¹°ãè¿ãã®ã«æé©ãªå Žæã§ãã
ããŒã¿ããŒã¹ã¹ããŒããå€æŽãã移è¡
æ£çŽã«èšããšããã³ãã¬ãŒãå
ã®ããŒãã¯ã€ã€ãŒãããã¯ã¯äžæ£è¡çºã§ãã ã©ã€ãããŒã¿ãã¢ããªã±ãŒã·ã§ã³ã«è¿œå ããŸãã
ãŸããæ¬ã«é¢ããããŒã¿ãä¿åããããã®ããŒã¿ããŒã¹å
ã®ããŒãã«ãå¿
èŠã§ãã 移è¡ã䜿çšããŠäœæã§ããŸãã ãžã§ãã¬ãŒã¿ãŒã䜿çšããŠç©ºã®ç§»è¡ãäœæããŸãã
ããã«ããã db/migrations/20161115110038_create_books.rb
ãããªååã®ãã¡ã€ã«ãdb/migrations/20161115110038_create_books.rb
ãç·šéããŸãã
Hanami::Model.migration do change do create_table :books do primary_key :id column :title, String, null: false column :author, String, null: false column :created_at, DateTime, null: false column :updated_at, DateTime, null: false end end end
Hanamiã¯ãããŒã¿ããŒã¹ã¹ããŒãã®å€æŽãèšè¿°ããããã®ç¹å¥ãªèšèªãæäŸããŸãã 䜿çšæ¹æ³ã«ã€ããŠã¯ã移è¡ã¬ã€ããã芧ãã ãã ã
ãã®å Žåããšã³ãã£ãã£ã®åå±æ§ã®åãæã€æ°ããããŒãã«ãå®çŸ©ããŸãã
ããŒã¿ããŒã¹ãæºåããŸãããïŒ
% bundle exec hanami db prepare
ããŒã¿ããšã³ãã£ãã£ãšããŠè¡šçŸãã
ããŒã¿ããŒã¹ã«æžç±ãä¿åããããŒãžã«è¡šç€ºããŸãã ãã®ããã«ã¯ãããŒã¿ããŒã¹ãèªã¿æžãããæ¹æ³ãå¿
èŠã§ãã ãšã³ãã£ãã£ãšãªããžããªã®çŽ¹ä»ïŒ
- ãšã³ãã£ãã£ã¯ãèå¥åã«ãã£ãŠäžæã«èå¥ãããïŒ
Book
åã®ïŒãã¡ã€ã³ã®ãªããžã§ã¯ãã§ãã - ãªããžããªã¯ãšã³ãã£ãã£ãšã¬ã€ã€ãŒã®éã«ããããšã³ãã£ãã£ã®ååšã®ç¶ç¶æ§ãä¿èšŒããŸãã
ãšã³ãã£ãã£ã¯å®å
šã«ããŒã¿ããŒã¹ã«äŸåããŸããã ããã«ããããã¹ããç°¡åã«ãªããŸã ã
ãã®ããã Book
äŸåããããŒã¿ãä¿åãããªããžããªãå¿
èŠã§ãã
ãšã³ãã£ãã£ãšãªããžããªã®è©³çŽ°ã«ã€ããŠã¯ãã¢ãã«ã¬ã€ããã芧ãã ããã
Hanamiã¯ã¢ãã«ã®ãžã§ãã¬ãŒã¿ãŒãæäŸããŠããã®ã§ã Book
ãšã³ãã£ãã£ãšå¯Ÿå¿ãããªããžããªãäœæããŸãããã
% bundle exec hanami generate model book create lib/bookshelf/entities/book.rb create lib/bookshelf/repositories/book_repository.rb create spec/bookshelf/entities/book_spec.rb create spec/bookshelf/repositories/book_repository_spec.rb
ãžã§ãã¬ãŒã¿ãŒã¯ããšã³ãã£ãã£ããªããžããªãããã³ãã¹ãçšã®é¢é£ãã¡ã€ã«ãæäŸããŸãã
ãšã³ãã£ãã£ãšé£æºããŸã
ãšã³ãã£ãã£ã¯åºæ¬çã«åçŽãªRubyãªããžã§ã¯ãã«è¿ããã®ã§ãã ç§ãã¡ã¯åœŒãã«æ±ããŠããè¡åã«çŠç¹ãåãããªããã°ãªãããããããããããä¿åããæ¹æ³ã«ã®ã¿çŠç¹ãåãããŸãã
çŸåšãåçŽãªãšã³ãã£ãã£ã¯ã©ã¹ãå¿
èŠã§ãã
ãã®ã¯ã©ã¹ã¯ãåæåäžã«ãã©ã¡ãŒã¿ãŒãšããŠæž¡ãããåå±æ§ã®ã²ãã¿ãŒãšã»ãã¿ãŒãçæããŸãã ãŠããããã¹ããæžãããšã§ããã確èªã§ããŸãïŒ
ãªããžããªã®äœ¿çš
ããã§ããªããžããªãè©ŠãæºåãæŽããŸããã Hanami console
ã³ãã³ãã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ã®ã³ã³ããã¹ãã§IRbãèµ·åããæ¢åã®ãªããžã§ã¯ãã䜿çšã§ããããã«ããŸãã
% bundle exec hanami console >> repository = BookRepository.new => => #<BookRepository:0x007f9ab61fbb40 ...> >> repository.all => [] >> book = repository.create(title: 'TDD', author: 'Kent Beck') => #<Book:0x007f9ab61c23b8 @attributes={:id=>1, :title=>"TDD", :author=>"Kent Beck", :created_at=>2016-11-15 11:11:38 UTC, :updated_at=>2016-11-15 11:11:38 UTC}> >> repository.find(book.id) => #<Book:0x007f9ab6181610 @attributes={:id=>1, :title=>"TDD", :author=>"Kent Beck", :created_at=>2016-11-15 11:11:38 UTC, :updated_at=>2016-11-15 11:11:38 UTC}>
Hanamiãªããžããªã«ã¯ãããŒã¿ããŒã¹ãã1ã€ãŸãã¯è€æ°ã®ãšã³ãã£ãã£ã®äž¡æ¹ãããŒãããããã®ã¡ãœããããããŸãã æ¢åã®ãã®ãäœæããã³æŽæ°ããããšãã§ããŸãã ãªããžããªå
ã®ç¬èªã®ã¯ãšãªã«æ°ããã¡ãœãããå®çŸ©ããããšãã§ããŸãã
ãã®çµæãHanamiããšã³ãã£ãã£ãšãªããžããªã䜿çšããŠããŒã¿ãã¢ãã«åããæ¹æ³ãèŠãŸããã ãšã³ãã£ãã£ã¯åäœãåæ ãããªããžããªã¯ãšã³ãã£ãã£ãšããŒã¿ã¹ãã¢ã®éä¿¡ã«äœ¿çšãããŸãã 移è¡ã䜿çšããŠãããŒã¿ããŒã¹ã¹ããŒãã«å€æŽãé©çšã§ããŸãã
åçããŒã¿ã衚瀺
æ°ããããŒã¿ã¢ããªã³ã°ãšã¯ã¹ããªãšã³ã¹ã䜿çšããŠãããã¯ãªã¹ãããŒãžã«å€åããããŒã¿ã衚瀺ã§ããŸãã ããã«ã€ããŠã¯ã以åã«äœæãããã¹ããé©çšããŸãã
ãã¹ãã§å¿
èŠãªãšã³ããªãäœæããããŒãžäžã®æžç±ã¯ã©ã¹ã®æ°ããããã«å¯Ÿå¿ããŠãããšè¿°ã¹ãŸããã ãã¹ããå床å®è¡ãããšãããŒã¿ããŒã¹ã«é¢é£ãããšã©ãŒã衚瀺ãããå¯èœæ§ãé«ããªããŸãã éçºããŒã¿ããŒã¹ã¯æ¢ã«ç§»è¡æžã¿ã§ããããŸã ãã¹ãããŒã¿ããŒã¹ã¯ç§»è¡ããŠããªãããšã«æ³šæããŠãã ããã
% HANAMI_ENV=test bundle exec hanami db prepare
ããã§ããã³ãã¬ãŒããå€æŽããŠéçHTMLãåé€ã§ããŸãã ãã¥ãŒã¯ã䜿çšå¯èœãªãã¹ãŠã®ã¬ã³ãŒãã調ã¹ãŠè¡šç€ºããå¿
èŠããããŸãã ãã©ãŒã ã«ãã®ãããªå€æŽãå¿
èŠãšãããã¹ããäœæããŸãã
æžç±ããªãã衚瀺ãããã®ããªãå Žåãã€ã³ããã¯ã¹ããŒãžã«ã¡ãã»ãŒãžã衚瀺ãããããšã瀺ããŸããã æ¬ãããå Žåããããã®ãªã¹ãã衚瀺ãããŸãã ããŒã¿ãã¥ãŒã®ã¬ã³ããªã³ã°ã¯æ¯èŒçç°¡åã§ãã Hanamiã¯ãæå°éã®ã€ã³ã¿ãŒãã§ã€ã¹ãæã€ã·ã³ãã«ãªãªããžã§ã¯ãããèšèšãããŠãããããåã
ã«ç°¡åã«ãã¹ãã§ããé£æºããŠæ©èœããŸãã
èšç»ãå®è£
ããããã«ãã³ãã¬ãŒããæžãçŽããŸãããïŒ
# apps/web/templates/books/index.html.erb <h2>All books</h2> <% if books.any? %> <div id="books"> <% books.each do |book| %> <div class="book"> <h2><%= book.title %></h2> <p><%= book.author %></p> </div> <% end %> </div> <% else %> <p class="placeholder">There are no books yet.</p> <% end %>
æ©èœãã¹ããå床å®è¡ãããšãã³ã³ãããŒã©ãŒã®ã¢ã¯ã·ã§ã³ãšããŠå€±æããŸã
ç§ãã¡ã®èŠè§£ã®ããã«ãŸã æ¬ãå
¬éããŠããŸããã ãã®å Žåã®ãã¹ããæžãããšãã§ããŸãïŒ
éåžžãã¢ã¯ã·ã§ã³ã®ãã¹ãã®äœæã«ã¯2ã€ã®åŽé¢ããããŸããå¿çãªããžã§ã¯ãã«é¢ããã¹ããŒãã¡ã³ããäœæããŸããå¿çãªããžã§ã¯ãã¯ãã¹ããŒã¿ã¹ãããããŒãããã³ã³ã³ãã³ãã®Rackäºæé
åã§ãã ãŸãã¯ãåŒã³åºãåŸã®ã¢ã¯ã·ã§ã³ããããŒã¿ãèŠãããšããäºå®ã«ã€ããŠã ããã§ãã¢ã¯ã·ã§ã³ãå€æ°variable :books
ã衚瀺ããããšã瀺ããŸããã
expose
ã¢ã¯ã·ã§ã³ã¯ã©ã¹ã¡ãœããã䜿çšããŠã @books
ã€ã³ã¹ã¿ã³ã¹@books
å
容ãèªç€ºããŠããã¥ãŒã§äœ¿çšã§ããããã«ããŸãã ããã§ãã¹ãã«å床åæ Œã§ããŸãïŒ
% bundle exec rake Run options: --seed 59133 # Running: ......... Finished in 0.042065s, 213.9543 runs/s, 380.3633 assertions/s. 6 runs, 7 assertions, 0 failures, 0 errors, 0 skips
ã·ã¹ãã ã«æ°ããæ¬ãè¿œå ããæ©èœãäœæããã ãã§ãã èšç»ã¯ç°¡åã§ãã詳现ãå
¥åã§ãããã©ãŒã ãå«ãããŒãžãäœæããŸãã
ãŠãŒã¶ãŒããã©ãŒã ãéä¿¡ãããšãæ°ãããšã³ãã£ãã£ãäœæããŠä¿åãããŠãŒã¶ãŒãæžç±ã®ãªã¹ãã®ããããŒãžã«ãªãã€ã¬ã¯ãããŸãã ã¯ã€ãºã§ã¹ããŒãªãŒãè¡šçŸããŠãã ããïŒ
ãã®æç¹ã§ãã¢ã¯ã·ã§ã³ããã¥ãŒããã³ãã¬ãŒããã©ã®ããã«æ©èœããããèªèããå¿
èŠããããŸãã
ããã»ã¹ãå°ãã¹ããŒãã¢ããããããã«èå³æ·±ãéšåã«é²ã¿ãŸãã æåã«ãã New Book
ãããŒãžã®æ°ããã¢ã¯ã·ã§ã³ãäœæããŸãã
% bundle exec hanami generate action web books
ããã«ãããã¢ããªã±ãŒã·ã§ã³ã«æ°ããã«ãŒããè¿œå ãããŸãã
次ã®èå³æ·±ãç¹ã¯ãã³ãã¬ãŒãã«é¢é£ããŠããŸããããã¯ã Book
ãšã³ãã£ãã£ã®HTMLãã©ãŒã ãçæããããã«Hanamiãã©ãŒã ãã«ããŒã䜿çšããããã§ãã
ãã©ãŒã ã®ãã«ããŒã䜿çšããŠã1ã€ã®apps/web/templates/books/new.html.erb
ãäœæãapps/web/templates/books/new.html.erb
ã
# apps/web/templates/books/new.html.erb <h2>Add book</h2> <%= form_for :book, '/books' do div class: 'input' do label :title text_field :title end div class: 'input' do label :author text_field :author end div class: 'controls' do submit 'Create Book' end end %>
ãã©ãŒã ã®åãã£ãŒã«ãã«<label>
ã¿ã°ãè¿œå ããåãã£ãŒã«ããã©ããããŸã
Hanami HTMLãã«ããŒã䜿çšãã<div>
ã³ã³ããã
ãã©ãŒã ãéä¿¡ããã«ã¯ãå¥ã®ã¢ã¯ã·ã§ã³ãå¿
èŠã§ãã ã¢ã¯ã·ã§ã³Books::Create
ãŸãããïŒ
% bundle exec hanami generate action web books#create
ããã«ãããã¢ããªã±ãŒã·ã§ã³ã«æ°ããã«ãŒããè¿œå ãããŸãã
ã¢ã¯ã·ã§ã³ãäœæãã
ïŒcreateã¢ã¯ã·ã§ã³ã«ã¯2ã€ã®ããšãå¿
èŠã§ãã ãŠããããã¹ãã§ããããè¡šçŸããŸãããïŒ
ããããååã«ç°¡åã«ããŸãã ãšã³ãã£ãã£ãããŒã¿ããŒã¹ã«æžã蟌ãæ¹æ³ã¯ãã§ã«ç¢ºèªããŠããã redirect_to
ã䜿çšããŠredirect_to
ãå®è£
ã§ããŸãã
ãã®æå°éã®å®è£
ã¯ããã¹ããåã³æåãããã®ã«ååãªã¯ãã§ãã
% bundle exec rake Run options: --seed 63592 # Running: ............... Finished in 0.081961s, 183.0142 runs/s, 305.0236 assertions/s. 12 runs, 14 assertions, 0 failures, 0 errors, 2 skips
äœãšããã§ãšãããããŸãïŒ
銬ãä¿æããŸãïŒ æãè
ã«å¯Ÿããé²åŸ¡ãè¡ãã«ã¯å°ãå¿èãå¿
èŠã§ãã 誰ãããã£ãŒã«ãã«å
¥åããã«ãã©ãŒã ãéä¿¡ãããšã©ããªããŸããïŒ
ããŒã¿ããŒã¹ã«èª€ã£ãããŒã¿ãå
¥åããããããŒã¿æŽåæ§éåã«é¢ãããšã©ãŒã確èªã§ããŸãã ç¡å¹ãªããŒã¿ãã·ã¹ãã ããé ãããæ¹æ³ã絶察ã«å¿
èŠã§ãïŒ
ãã¹ãã§ãã§ãã¯ãè¡šçŸããã«ã¯ããã¹ãã倱æããå Žåã¯ã©ãããã°ããã®ããèããå¿
èŠããããŸãã bookshelf#new
ãã©ãŒã ã«åã¬ã³ããªã³ã°ããããšããbookshelf#new
ãŸãããã®ããããŠãŒã¶ãŒã«ããäžåºŠèšå
¥ããæ©äŒãäžããŸãã ãã®åäœãåäœãã¹ãã§èª¬æããŸãã
ããã§ããã¹ãã§ã¯2ã€ã®ä»£æ¿ã·ããªãªã説æããŸããå
ã®æåãããã¹ãšããã¹ãã倱æããæ°ããã·ããªãªã§ãã ãã¹ããä¿®æ£ããããã«ãæ€èšŒãè¡ããŸãã
ãã¡ããããã¹ãŠã®æ€èšŒã«ãŒã«ãæ¬è³ªçã«çœ®ãããšãã§ããŸããè±èŠã§ã¯ããŠãŒã¶ãŒå
¥åã®ãœãŒã¹ã«å°ãè¿ããã€ãŸãã¢ã¯ã·ã§ã³ã§çŽæ¥æ€èšŒã«ãŒã«ãå®çŸ©ããããšãã§ããŸãã Hanamiã¢ã¯ã·ã§ã³ã¯ã params
ã¯ã©ã¹ã¡ãœããã䜿çšããŠæå¹ãªãã©ã¡ãŒã¿ãŒå€ã決å®ã§ããŸãã
ãã®ã¢ãããŒãã«ãããåæã«ïŒãã©ã¡ãŒã¿ãŒã®ãã¯ã€ããªã¹ããèšå®ãïŒä¿¡é ŒãããŠããªããŠãŒã¶ãŒå
¥åã«å¯Ÿããè匱æ§ãé²ãããã«æ®ãã¯ç¡èŠãããŸãïŒ ãåãå
¥ããããå€ãæå®ã§ããŸãã
, , ,
, URL. , ?
HTTP
422 ( ) .
, , . apps/web/templates/books/new.html.erb
.
, Hanami , params
, . , , , .
.
, - , , . .
, , params
:
:
params.errors
( ) .
apps/web/templates/books/new.html.erb
:
<% unless params.valid? %> <div class="errors"> <h3>There was a problem with your submission</h3> <ul> <% params.error_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %>
, "is required", , . .
% bundle exec rake Run options: --seed 59940 # Running: .................. Finished in 0.078112s, 230.4372 runs/s, 473.6765 assertions/s. 15 runs, 27 assertions, 0 failures, 0 errors, 1 skips
, . "web":
Hanami REST- , :
resources :books, only: [:index, :new, :create] root to: 'home#index'
, , , ,
routes
:
% bundle exec hanami routes Name Method Path Action books GET, HEAD /books Web::Controllers::Books::Index new_book GET, HEAD /books/new Web::Controllers::Books::New books POST /books Web::Controllers::Books::Create root GET, HEAD / Web::Controllers::Home::Index
hanami routes
( _path
_url
routes
), HTTP , .
, resources
, . , form_for
?
<%= form_for :book, '/books' do # ... end %>
, , , . routes
, , :
<%= form_for :book, routes.books_path do # ... end %>
apps/web/controllers/books/create.rb
:
redirect_to routes.books_path
èŠçŽãã
Hanami !
, : Hanami, , ; ; , .
, . , the Hanami API , .
PS Translation Gang , , GeorgeGorbanev , .