Upgrade to Pro — share decks privately, control downloads, hide ads and more …

About Lotus Framework

y-yagi
November 18, 2015

About Lotus Framework

My talk at Ginzarb 29.

y-yagi

November 18, 2015
Tweet

More Decks by y-yagi

Other Decks in Programming

Transcript

  1. そこでLOTUS "Lotus brings back Object Oriented Programming to web development,

    leveraging a stable API, minimal DSL and plain objects." オブジェクト指向を取り戻せ 一つの大きなライブラリではなく、小さなコンポーネントの組み 合わせでWebサービスを作れるようになっている
  2. CONTAINER . ├ ─ ─ G e m f i

    l e ├ ─ ─ R a k e f i l e ├ ─ ─ a p p s │ └ ─ ─ w e b │ ├ ─ ─ a p p l i c a t i o n . r b │ ├ ─ ─ c o n f i g │ │ └ ─ ─ r o u t e s . r b │ ├ ─ ─ c o n t r o l l e r s │ ├ ─ ─ p u b l i c │ │ ├ ─ ─ j a v a s c r i p t s │ │ └ ─ ─ s t y l e s h e e t s │ ├ ─ ─ t e m p l a t e s │ │ └ ─ ─ a p p l i c a t i o n . h t m l . e r b │ └ ─ ─ v i e w s │ └ ─ ─ a p p l i c a t i o n _ l a y o u t . r b ├ ─ ─ c o n f i g │ └ ─ ─ e n v i r o n m e n t . r b
  3. CONTAINER(ADMINを追加) ├ ─ ─ G e m f i l

    e ├ ─ ─ G e m f i l e . l o c k ├ ─ ─ R a k e f i l e ├ ─ ─ a p p s │ ├ ─ ─ a d m i n │ │ ├ ─ ─ a p p l i c a t i o n . r b │ │ ├ ─ ─ c o n f i g │ │ │ └ ─ ─ r o u t e s . r b │ │ ├ ─ ─ c o n t r o l l e r s │ │ ├ ─ ─ p u b l i c │ │ │ ├ ─ ─ j a v a s c r i p t s │ │ │ └ ─ ─ s t y l e s h e e t s │ │ ├ ─ ─ t e m p l a t e s │ │ │ └ ─ ─ a p p l i c a t i o n . h t m l . e r b │ │ └ ─ ─ v i e w s │ │ └ ─ ─ a p p l i c a t i o n _ l a y o u t . r b │ └ ─ ─ w e b │ ├ ─ ─ a p p l i c a t i o n . r b
  4. APPLICATION ├ ─ ─ G e m f i l

    e ├ ─ ─ R a k e f i l e ├ ─ ─ a p p │ ├ ─ ─ c o n t r o l l e r s │ ├ ─ ─ t e m p l a t e s │ │ └ ─ ─ a p p l i c a t i o n . h t m l . e r b │ └ ─ ─ v i e w s │ └ ─ ─ a p p l i c a t i o n _ l a y o u t . r b ├ ─ ─ c o n f i g │ ├ ─ ─ a p p l i c a t i o n . r b │ ├ ─ ─ e n v i r o n m e n t . r b │ └ ─ ─ r o u t e s . r b ├ ─ ─ c o n f i g . r u ├ ─ ─ d b ├ ─ ─ l i b │ ├ ─ ─ c o n f i g │ │ └ ─ ─ m a p p i n g . r b │ ├ ─ ─ s a m p l e
  5. ROUTING resourcesやnamespaceも使え る g e t ' / h e

    l l o ' , t o : e n d p o i n t g e t ' / ' , t o : ' h o m e # i n d e x ' , a s : : h o m e g e t ' / b o o k s / : i d ' , t o : ' b o o k s # s h o w ' r e s o u r c e s : b o o k s r e s o u r c e s : b o o k s , o n l y : [ : n e w , : c r e a t e , : s h o w ] r e s o u r c e s : b o o k s , e x c e p t : [ : i n d e x , : e d i t , : u p d a t e , : d e s t r o y ] n a m e s p a c e ' d o c s ' d o g e t ' / i n s t a l l a t i o n ' , t o : ' d o c s # i n s t a l l a t i o n ' g e t ' / u s a g e ' , t o : ' d o c s # u s a g e ' e n d Railsのルーティングの書き方に大分近 い
  6. ROUTING Routingを取得する為のヘルパーメソッドもあ る < % = r o u t

    e s . p a t h ( : g r e e t i n g ) % > < % = r o u t e s . u r l ( : g r e e t i n g ) % > < % = r o u t e s . g r e e t i n g _ p a t h % > < % = r o u t e s . g r e e t i n g _ u r l % >
  7. ACTIONS Railsと異なり、1つのクラスに1つのアクションを定義す る indexアクションを定義する場合 # a p p s /

    w e b / c o n t r o l l e r s / d a s h b o a r d / i n d e x . r b m o d u l e W e b : : C o n t r o l l e r s : : D a s h b o a r d c l a s s I n d e x i n c l u d e W e b : : A c t i o n d e f c a l l ( p a r a m s ) e n d e n d e n d 必要なのは、Action moduleのincludeと、callメソッドを定義 する事だけ viewの定義はViewクラスで行う(後述)
  8. ACTIONS 普通にRubyのクラスとして扱われる為、コンストラクタを定義 する事も出来る # a p p s / w

    e b / c o n t r o l l e r s / d a s h b o a r d / i n d e x . r b m o d u l e W e b : : C o n t r o l l e r s : : D a s h b o a r d c l a s s I n d e x i n c l u d e W e b : : A c t i o n d e f i n i t i a l i z e ( g r e e t i n g : G r e e t i n g . n e w ) @ g r e e t i n g = g r e e t i n g e n d d e f c a l l ( p a r a m s ) s e l f . b o d y = @ g r e e t i n g . m e s s a g e e n d e n d e n d
  9. PARAMS Rails同様、params変数を操作すれば OK p a r a m s [

    : q ] p a r a m s [ : b o o k ] [ : t i t l e ]
  10. PARAMS ホワイトリスト処理は paramsメソッドで行 う # a p p s /

    w e b / c o n t r o l l e r s / s i g n u p / c r e a t e . r b m o d u l e W e b : : C o n t r o l l e r s : : S i g n u p c l a s s C r e a t e i n c l u d e W e b : : A c t i o n p a r a m s d o p a r a m : e m a i l p a r a m : p a s s w o r d p a r a m : a d d r e s s d o p a r a m : c o u n t r y e n d e n d d e f c a l l ( p a r a m s ) p u t s p a r a m s [ : e m a i l ] # = > " a l i c e @ e x a m p l e . o r g " p u t s p a r a m s [ : p a s s w o r d ] # = > " s e c r e t " p u t s p a r a m s [ : a d d r e s s ] [ : c o u n t r y ] # = > " I t a l y "
  11. PARAMS paramに直接validationも書けたりもす る # a p p s / w

    e b / c o n t r o l l e r s / s i g n u p / c r e a t e . r b m o d u l e W e b : : C o n t r o l l e r s : : S i g n u p c l a s s C r e a t e i n c l u d e W e b : : A c t i o n M E G A B Y T E = 1 0 2 4 * * 2 p a r a m s d o p a r a m : n a m e , p r e s e n c e : t r u e p a r a m : e m a i l , p r e s e n c e : t r u e , f o r m a t : / @ / , c o n f i r m a t i o n : p a r a m : p a s s w o r d , p r e s e n c e : t r u e , c o n f i r m a t i o n : p a r a m : t e r m s _ o f _ s e r v i c e , a c c e p t a n c e : t r u e p a r a m : a v a t a r , s i z e : 0 . . ( M E G A B Y T E * 3 ) p a r a m : a g e , t y p e : I n t e g e r , s i z e : 1 8 . . 9 9 e n d d e f c a l l ( p a r a m s ) i f p a r a m s . v a l i d ? # . . .
  12. EXPOSURES Railsと違い、インスタンス変数を宣言しただけではviewでその 変数を使用する事が出来ない viewで使いたい変数は、明示的にexposeメソッドを使って宣 言する必要がある # a p p s

    / w e b / c o n t r o l l e r s / d a s h b o a r d / i n d e x . r b m o d u l e W e b : : C o n t r o l l e r s : : D a s h b o a r d c l a s s I n d e x i n c l u d e W e b : : A c t i o n e x p o s e : g r e e t i n g d e f c a l l ( p a r a m s ) @ g r e e t i n g = " H e l l o " @ f o o = 2 3 e n d e n d e n d 上記例だと、greetingはviewから使えるが、fooはviewからは 使えない
  13. VIEWS Viewの定義はView Classで行 う # a p p s /

    w e b / v i e w s / d a s h b o a r d / i n d e x . r b m o d u l e W e b : : V i e w s : : D a s h b o a r d c l a s s I n d e x i n c l u d e W e b : : V i e w e n d e n d クラス名にそのviewを使用するアクション名を指定す る その為、アクション毎にClassが必要になる
  14. VIEWS View Classとtemplateはコンテキストが一緒なので、View Classで定義したメソッドは、templateが呼び出す事が可能 # a p p s /

    w e b / t e m p l a t e s / d a s h b o a r d / i n d e x . h t m l . e r b < h 1 > < % = t i t l e % > < / h 1 > # a p p s / w e b / v i e w s / d a s h b o a r d / i n d e x . r b m o d u l e W e b : : V i e w s : : D a s h b o a r d c l a s s I n d e x i n c l u d e W e b : : V i e w d e f t i t l e ' D a s h b o a r d ' e n d e n d e n d 当然controllerで定義する事も可能だが、exposeが必要 + 変数しか使えない
  15. LAYOUT Layoutもクラスで管理されているので、Layoutを追加したい場 合、Layout用のクラスを追加する必要がある # a p p s / w

    e b / v i e w s / b o o k _ l a y o u t . r b m o d u l e W e b : : V i e w s c l a s s B o o k L a y o u t i n c l u d e W e b : : L a y o u t e n d e n d
  16. MODELS bookというエンティティがあった場 合 # l i b / b o

    o k s h e l f / e n t i t i e s / b o o k . r b c l a s s B o o k i n c l u d e L o t u s : : E n t i t y a t t r i b u t e s : n a m e , : p r i c e , : c o d e , : a u t h o r _ i d e n d # l i b / b o o k s h e l f / r e p o s i t o r i e s / b o o k _ r e p o s i t o r y . r b c l a s s B o o k R e p o s i t o r y i n c l u d e L o t u s : : R e p o s i t o r y e n d
  17. MODELS B o o k R e p o s

    i t o r y . a l l # = > [ # < B o o k : 0 x 0 0 7 f 4 d d 7 d 3 c 4 b 8 @ i d = 1 , @ n a m e = " a a " , @ p r i c e = " 1 0 0 " , @ c o d e = " 1 2 3 " B o o k R e p o s i t o r y . a l l . f i r s t # = > # < B o o k : 0 x 0 0 7 f 4 d d 7 d 0 a b 4 8 @ i d = 1 , @ n a m e = " a a " , @ p r i c e = " 1 0 0 " , @ c o d e = " 1 2 3 " n e w _ b o o k = B o o k . n e w ( n a m e : " n e w b o o k " , p r i c e : 1 0 0 0 , a u t h o r _ i d : 1 , c o d e : ' 0 0 0 7 7 ' # = > # < B o o k : 0 x 0 0 7 f 4 d d 7 b b d a b 0 @ n a m e = " n e w b o o k " , @ p r i c e = 1 0 0 0 , @ c o d e = " 0 0 0 7 7 " , B o o k R e p o s i t o r y . c r e a t e ( n e w _ b o o k ) # = > # < B o o k : 0 x 0 0 7 f 4 d d 7 b b 8 f 6 0 @ i d = 5 , @ n a m e = " n e w b o o k " , @ p r i c e = " 1 0 0 0 " , @ c o d e
  18. ADAPTERS adapterの指定はこんな感 じ # l i b / b o

    o k s h e l f . r b # * F i l e S y s t e m a d a p t e r a d a p t e r t y p e : : f i l e _ s y s t e m , u r i : ' f i l e : / / / d b / b o o k s h e l f _ d e v e l o p m e n t ' # * M e m o r y a d a p t e r a d a p t e r t y p e : : m e m o r y , u r i : ' m e m o r y : / / l o c a l h o s t / b o o k s h e l f _ d e v e l o p m e n t ' # * S Q L a d a p t e r a d a p t e r t y p e : : s q l , u r i : ' s q l i t e : / / d b / b o o k s h e l f _ d e v e l o p m e n t . s q l i t e 3 ' a d a p t e r t y p e : : s q l , u r i : ' p o s t g r e s : / / l o c a l h o s t / b o o k s h e l f _ d e v e l o p m e n t ' a d a p t e r t y p e : : s q l , u r i : ' m y s q l : / / l o c a l h o s t / b o o k s h e l f _ d e v e l o p m e n t '
  19. MAPPING エンティティのアトリビュートとDBのテーブルのカラムのマッピ ングは、自分で行う必要がある Railsのようによしなにはしてくれない # エンティティ c l a s

    s B o o k i n c l u d e L o t u s : : E n t i t y a t t r i b u t e s : n a m e , : p r i c e , : c o d e , : a u t h o r _ i d e n d # テーブル c r e a t e _ t a b l e : b o o k s d o p r i m a r y _ k e y : i d f o r e i g n _ k e y : a u t h o r _ i d , : a u t h o r s , o n _ d e l e t e : : c a s c a d e , n u l l : f a l s e c o l u m n : n a m e , S t r i n g , n u l l : f a l s e c o l u m n : p r i c e , I n t e g e r , n u l l : f a l s e c o l u m n : c o d e , S t r i n g , n u l l : f a l s e , u n i q u e : t r u e , s i z e : 1 2 8 c h e c k { p r i c e > 0 } e n d
  20. MAPPING # マッピング c o l l e c t

    i o n : b o o k s d o e n t i t y B o o k r e p o s i t o r y B o o k R e p o s i t o r y a t t r i b u t e : i d , I n t e g e r a t t r i b u t e : n a m e , S t r i n g a t t r i b u t e : p r i c e , S t r i n g a t t r i b u t e : c o d e , S t r i n g a t t r i b u t e : a u t h o r _ i d , I n t e g e r e n d
  21. REPOSITORIES Lotus::Repositoryでは、下記メソッドが定義されている どのadapterを使用しても上記メソッドは使用可能 SQL adapterではもうちょっとSQLラッパー用のメソッドが定義 されている . p e r

    s i s t ( e n t i t y ) – C r e a t e o r u p d a t e a n e n t i t y . c r e a t e ( e n t i t y ) – C r e a t e a r e c o r d f o r t h e g i v e n e n t i t y . u p d a t e ( e n t i t y ) – U p d a t e t h e r e c o r d c o r r e s p o n d i n g t o t h e g i v e n e n t i t y . d e l e t e ( e n t i t y ) – D e l e t e t h e r e c o r d c o r r e s p o n d i n g t o t h e g i v e n e n t i t y . f e t c h ( r a w ) – F e t c h r a w d a t a s e t s f o r t h e g i v e n r a w q u e r y s t r i n g ( e g . S Q L . e x e c u t e ( r a w ) – E x e c u t e r a w c o m m a n d ( e g . S Q L ) . a l l ­ F e t c h a l l t h e e n t i t i e s f r o m t h e c o l l e c t i o n . f i n d ­ F e t c h a n e n t i t y f r o m t h e c o l l e c t i o n b y i t s I D . f i r s t ­ F e t c h t h e f i r s t e n t i t y f r o m t h e c o l l e c t i o n . l a s t ­ F e t c h t h e l a s t e n t i t y f r o m t h e c o l l e c t i o n . c l e a r ­ D e l e t e a l l t h e r e c o r d s f r o m t h e c o l l e c t i o n . q u e r y ­ F a b r i c a t e s a q u e r y o b j e c t
  22. REPOSITORIES RDBMSのORMには を使 用 クエリーを書く用の、queryメソッドがある jeremyevans/sequel c l a s

    s B o o k R e p o s i t o r y i n c l u d e L o t u s : : R e p o s i t o r y d e f s e l f . m o s t _ r e c e n t _ b y _ a u t h o r ( a u t h o r , l i m i t : 8 ) q u e r y d o w h e r e ( a u t h o r _ i d : a u t h o r . i d ) . l i m i t ( l i m i t ) e n d e n d d e f s e l f . o r d e r _ b y _ p r i c e q u e r y { o r d e r ( : p r i c e ) } e n d e n d
  23. MAILERS 一つのメール毎に一つのメールクラスを定義する Railsのように、一つのMailerクラス複数メソッドを定義は出 来ない c l a s s M

    a i l e r s : : W e l c o m e i n c l u d e L o t u s : : M a i l e r f r o m ' n o r e p l y @ b o o k s h e l f . o r g ' t o ' u s e r @ e x a m p l e . c o m ' s u b j e c t ' W e l c o m e t o B o o k s h e l f ' e n d M a i l e r s : : W e l c o m e . d e l i v e r M a i l e r s : : W e l c o m e . d e l i v e r ( f o r m a t : : h t m l ) M a i l e r s : : W e l c o m e . d e l i v e r ( f o r m a t : : t x t )
  24. MIGRATIONS L o t u s : : M o

    d e l . m i g r a t i o n d o c h a n g e d o c r e a t e _ t a b l e : b o o k s d o p r i m a r y _ k e y : i d f o r e i g n _ k e y : a u t h o r _ i d , : a u t h o r s , o n _ d e l e t e : : c a s c a d e , n u l l : f a l s e c o l u m n : c o d e , S t r i n g , n u l l : f a l s e , u n i q u e : t r u e , s i z e : 1 2 8 c o l u m n : t i t l e , S t r i n g , n u l l : f a l s e c o l u m n : p r i c e , I n t e g e r , n u l l : f a l s e , d e f a u l t : 1 0 0 # c e n t s c h e c k { p r i c e > 0 } e n d e n d e n d changeはRails同様、リバーシブルでよしなにやってくれる up/downも使える migrationはSequel のメソッドを使用しているだけなので、詳 細はSequelのdoc( )参照 schema_modification.rdoc
  25. FORMの例 < h 2 > A d d b o

    o k < / h 2 > < d i v c l a s s = " e r r o r s " > < h 3 > T h e r e w a s a p r o b l e m w i t h y o u r s u b m i s s i o n < / h 3 > < u l > < l i > i s r e q u i r e d < / l i > < / u l > < / d i v > < % u n l e s s p a r a m s . v a l i d ? % > < % p a r a m s . e r r o r s . e a c h d o | e r r o r | % > < % = e r r o r . a t t r i b u t e _ n a m e % > < % e n d % > < % e n d % > < % = f o r m _ f o r : b o o k , r o u t e s . b o o k s _ p a t h d o d i v c l a s s : ' i n p u t ' d o l a b e l : n a m e t e x t _ f i e l d : n a m e e n d
  26. FORMの例 生成されるHTMLは下記の通り < ! d o c t y p

    e H T M L > < h t m l > < h e a d > < t i t l e > B o o k L a y o u t < / t i t l e > < / h e a d > < b o d y > < h 1 > B o o k s h e l f < / h 1 > < h 2 > A d d b o o k < / h 2 > < f o r m a c t i o n = " / b o o k s " m e t h o d = " P O S T " a c c e p t ­ c h a r s e t = " u t f ­ 8 " i d = " b o o k ­ f o r m " < i n p u t t y p e = " h i d d e n " n a m e = " _ c s r f _ t o k e n " v a l u e = " 9 2 6 b 7 0 d 7 7 7 a e e e 0 c 4 7 e 9 8 7 6 9 b e 0 1 < d i v c l a s s = " i n p u t " > < l a b e l f o r = " b o o k ­ n a m e " > N a m e < / l a b e l > < i n p u t t y p e = " t e x t " n a m e = " b o o k [ n a m e ] " i d = " b o o k ­ n a m e " v a l u e = " " > < / d i v > < d i v c l a s s = " c o n t r o l s " > < b u t t o n t y p e = " s u b m i t " > C r e a t e B o o k < / b u t t o n > < / d i v > < / f o r m > CSRFトークンも生成される
  27. COMMANDS b u n d l e e x e

    c l o t u s ­ ­ h e l p C o m m a n d s : l o t u s c o n s o l e # s t a r t s a l o t u s c o n s o l e l o t u s d b [ S U B C O M M A N D ] # m a n a g e s e t o f D B o p e r a t i o n s l o t u s g e n e r a t e # g e n e r a t e s a p p , a c t i o n , m o d e l , m a i l e r o r m i g r a t i o n l o t u s h e l p [ C O M M A N D ] # D e s c r i b e a v a i l a b l e c o m m a n d s o r o n e s p e c i f i c c o m m a n d l o t u s n e w # g e n e r a t e s a n e w a p p l i c a t i o n l o t u s r o u t e s # p r i n t s r o u t e s l o t u s s e r v e r # s t a r t s a l o t u s s e r v e r l o t u s v e r s i o n # p r i n t s L o t u s v e r s i o n
  28. COMMANDS # アプリ生成 l o t u s n e

    w b o o k s h e l f # m o d e l 生成 b u n d l e e x e c l o t u s g e n e r a t e m i g r a t i o n c r e a t e _ b o o k s # r o u t e s 表示 b u n d l e e x e c l o t u s r o u t e s # s e r v e r 起動 b u n d l e e x e c l o t u s s e r v e r # c o n s o l e 起動 b u n d l e e x e c l o t u s c o n s o l e # e t c . . .
  29. TEST minitest / rspecをどちらを使うを選択出来るようになってい る lotus newする際に、­­testオプションで指定可能 lotus new spec

    ­­test rspec デフォルトはminitest minitestはminitest/specを使用 テストの格納先は、どちらを指定してもspec配下
  30. TEST Railsのようにテスト用のクラスを提供している訳では無く、普 通のRubyファイルに対するテストを行う アクションのテストの例 # s p e c /

    w e b / c o n t r o l l e r s / d a s h b o a r d / i n d e x _ s p e c . r b r e q u i r e ' s p e c _ h e l p e r ' r e q u i r e _ r e l a t i v e ' . . / . . / . . / . . / a p p s / w e b / c o n t r o l l e r s / d a s h b o a r d / i n d e x ' d e s c r i b e W e b : : C o n t r o l l e r s : : D a s h b o a r d : : I n d e x d o l e t ( : a c t i o n ) { W e b : : C o n t r o l l e r s : : D a s h b o a r d : : I n d e x . n e w } l e t ( : p a r a m s ) { H a s h [ ] } i t " i s s u c c e s s f u l " d o r e s p o n s e = a c t i o n . c a l l ( p a r a m s ) r e s p o n s e [ 0 ] . m u s t _ e q u a l 2 0 0 e n d e n d
  31. TEST requestのテストの例 # s p e c / a p

    i _ v 1 / r e q u e s t s / u s e r s _ s p e c . r b r e q u i r e ' s p e c _ h e l p e r ' d e s c r i b e " A P I V 1 u s e r s " d o i n c l u d e R a c k : : T e s t : : M e t h o d s b e f o r e d o @ u s e r = U s e r R e p o s i t o r y . c r e a t e ( U s e r . n e w ( n a m e : ' L u c a ' ) ) e n d # a p p i s r e q u i r e d b y R a c k : : T e s t d e f a p p L o t u s : : C o n t a i n e r . n e w e n d i t " i s s u c c e s s f u l " d o g e t " / a p i / v 1 / u s e r s / # { @ u s e r . i d } " featureテストはcapybaraで(デフォルトでcapybaraを使う前提の helperが生成される)
  32. その他 i18nはまだ無い 対応自体は進められている 日本語… 環境固有の値はdotenvを使って設定するようになっている 上記ファイルがデフォルトで生成される Error messages by jodosha

    · Pull Request #74 · lotus/validations # . e n v . d e v e l o p m e n t # D e f i n e E N V v a r i a b l e s f o r d e v e l o p m e n t e n v i r o n m e n t B O O K S H E L F _ D A T A B A S E _ U R L = " p o s t g r e s : / / l o c a l h o s t / b o o k s h e l f _ d e v e l o p m e n t " W E B _ S E S S I O N S _ S E C R E T = " 5 c 4 b 5 6 4 5 b 0 c c a b 4 2 a d 2 4 7 b b 9 b 9 a 9 8 e a 6 0 1 3 5 a 0 0 0 d d 4 3 f 0 d 3 7 e a a 3 9 1 3 8 A D M I N _ S E S S I O N S _ S E C R E T = " d b a d a b 6 c 5 8 4 4 d 6 7 9 7 9 b 0 4 a 0 4 5 a 3 c a c a 7 6 6 1 b 7 3 f a 5 3 5 4 e a 7 c 3 6 c c 0 2 4
  33. END