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

Content integration @ Bookmate

exAspArk
October 07, 2015

Content integration @ Bookmate

#MaybeMonad #XML #ONIX #Ruby

https://github.com/exAspArk/better_struct

exAspArk

October 07, 2015
Tweet

More Decks by exAspArk

Other Decks in Programming

Transcript

  1. Metadata http://www.editeur.org/83/Overview ONIX (ONline Information eXchange) is an XML-based international

    standard for representing and communicating book industry product information in electronic form.
  2. ONIX sample <?xml  version="1.0"  encoding="utf-­‐8"?>   <ONIXMessage  xmlns:xsd="http://www.w3.org/2001/XMLSchema"  xmlns:xsi="http://www.w3.org/ 2001/XMLSchema-­‐instance"

     release="3.0"  xmlns="http://www.editeur.org/onix/3.0/reference">      <Header>          <SentDateTime>20131202T192459</SentDateTime>          <DefaultPriceType>42</DefaultPriceType>          <DefaultCurrencyCode>EUR</DefaultCurrencyCode>          ...      </Header>      <Product>          <NotificationType>03</NotificationType>          <RecordSourceType>01</RecordSourceType>          <ProductIdentifier>              <ProductIDType>15</ProductIDType>              <IDValue>9781824302123</IDValue>          </ProductIdentifier>          <DescriptiveDetail>            <Contributor>                  <SequenceNumber>1</SequenceNumber>                  <ContributorRole>A01</ContributorRole>                  <PersonName>David  Herbert  Lawrence</PersonName>              </Contributor>              <Subject>                  <SubjectSchemeIdentifier>10</SubjectSchemeIdentifier>                  <SubjectCode>FIC000000</SubjectCode>              </Subject>              ...          </DescriptiveDetail>          <PublishingDetail>              <PublishingDate>                  <PublishingDateRole>11</PublishingDateRole>                  <DateFormat>00</DateFormat>                  <Date>20101028</Date>              </PublishingDate>              <SalesRights>                  <SalesRightsType>06</SalesRightsType>                  <Territory>                      <CountriesIncluded>AS  CA  GU  MP  PH  PR  US  VI</CountriesIncluded>                  </Territory>              </SalesRights>              ...          </PublishingDetail>          ...
  3. • ONIX 2.1 – https://github.com/yob/onix (not maintained) • ONIX 3.0

    – https://github.com/immateriel/im_onix RubyGems
  4. • Easy to start • Open source • No ubiquitous

    language • Extra data abstractions https://en.wikipedia.org/wiki/Domain-driven_design
  5. ONIX 2.1 Book metadata ONIX 3.0 onix2 im_onix onix2 adapter

    onix3 adapter Gems Application XML Why to use this extra layer?
  6. BetterStruct example BetterStruct.new(nil)  ==  BetterStruct.new(nil).no_undefined_method_error   #  =>  true  

    BetterStruct.new(nil)  ==  BetterStruct.new(nil).maybe.monad   #  =>  true  
  7. BetterStruct example BetterStruct.new(nil)  ==  BetterStruct.new(nil).no_undefined_method_error   #  =>  true  

    BetterStruct.new(nil)  ==  BetterStruct.new(nil).maybe.monad   #  =>  true   like_open_struct  =  BetterStruct.new({  title:  "Fifty  Shades  of  Grey"  })   like_open_struct.title.value   #  =>  "Fifty  Shades  of  Grey"  
  8. BetterStruct example BetterStruct.new(nil)  ==  BetterStruct.new(nil).no_undefined_method_error   #  =>  true  

    BetterStruct.new(nil)  ==  BetterStruct.new(nil).maybe.monad   #  =>  true   like_open_struct  =  BetterStruct.new({  title:  "Fifty  Shades  of  Grey"  })   like_open_struct.title.value   #  =>  "Fifty  Shades  of  Grey"   like_open_struct.title.sub("Fifty",  "No").first.value   #  =>  "N"
  9. ONIX example <?xml  version="1.0"  encoding="utf-­‐8"?>   <ONIXMessage  xmlns:xsd="http://www.w3.org/2001/XMLSchema"  xmlns:xsi="http://www.w3.org/2001/ XMLSchema-­‐instance"

     release="3.0"  xmlns="http://www.editeur.org/onix/3.0/reference">      <Product>          <DescriptiveDetail>              <TitleDetail>                  <TitleElement>                      <TitleText>Atlas  Shrugged</TitleText>                  </TitleElement>              </TitleDetail>          </DescriptiveDetail>      </Product>   </ONIXMessage>
  10. class  ONIX::V3::ProductAdapter      def  initialize(product)        

     @product  =  BetterStruct.new(product)      end      def  title          @product.descriptive_detail.title_detail.title_element.title_text.value      end   end <?xml  version="1.0"  encoding="utf-­‐8"?>   <ONIXMessage  xmlns:xsd="http://www.w3.org/2001/XMLSchema"  xmlns:xsi="http://www.w3.org/2001/ XMLSchema-­‐instance"  release="3.0"  xmlns="http://www.editeur.org/onix/3.0/reference">      <Product>          <DescriptiveDetail>              <TitleDetail>                  <TitleElement>                      <TitleText>Atlas  Shrugged</TitleText>                  </TitleElement>              </TitleDetail>          </DescriptiveDetail>      </Product>   </ONIXMessage> ONIX example
  11. class  ONIX::V3::ProductAdapter      def  initialize(product)        

     @product  =  BetterStruct.new(product)      end      def  title          @product.descriptive_detail.title_detail.title_element.title_text.value      end   end   ONIX example xml  =  "<DescriptiveDetail><TitleDetail><TitleElement><TitleText>Atlas  Shrugged</ TitleText></TitleElement></TitleDetail></DescriptiveDetail>"  
  12. class  ONIX::V3::ProductAdapter      def  initialize(product)        

     @product  =  BetterStruct.new(product)      end      def  title          @product.descriptive_detail.title_detail.title_element.title_text.value      end   end   ONIX example https://github.com/savonrb/nori xml  =  "<DescriptiveDetail><TitleDetail><TitleElement><TitleText>Atlas  Shrugged</ TitleText></TitleElement></TitleDetail></DescriptiveDetail>"   product  =  Nori.new.parse(xml)   #  =>  {  "DescriptiveDetail"  =>  {  "TitleDetail"  =>  {  "TitleElement"  =>  {  "TitleText"  =>   "Atlas  Shrugged"  }}}}  
  13. class  ONIX::V3::ProductAdapter      def  initialize(product)        

     @product  =  BetterStruct.new(product)      end      def  title          @product.descriptive_detail.title_detail.title_element.title_text.value      end   end   ONIX example xml  =  "<DescriptiveDetail><TitleDetail><TitleElement><TitleText>Atlas  Shrugged</ TitleText></TitleElement></TitleDetail></DescriptiveDetail>"   product  =  Nori.new.parse(xml)   #  =>  {  "DescriptiveDetail"  =>  {  "TitleDetail"  =>  {  "TitleElement"  =>  {  "TitleText"  =>   "Atlas  Shrugged"  }}}}   product_adapter  =  ONIX::V3::ProductAdapter.new(product)   product_adapter.title   #  =>  "Atlas  Shrugged" https://github.com/savonrb/nori
  14. product   #  =>  {  "DescriptiveDetail"  =>  {  "TitleDetail"  =>

     {  "TitleElement"  =>  {  "TitleText"  =>   "Atlas  Shrugged"  }}}}   BetterStruct.new(product).descriptive_detail.title_detail.title_element.title_text.value   ONIX example
  15. product   #  =>  {  "DescriptiveDetail"  =>  {  "TitleDetail"  =>

     {  "TitleElement"  =>  {  "TitleText"  =>   "Atlas  Shrugged"  }}}}   BetterStruct.new(product).descriptive_detail.title_detail.title_element.title_text.value   product["DescriptiveDetail"]["TitleDetail"]["TitleElement"]["TitleText"]   ONIX example
  16. product   #  =>  {  "DescriptiveDetail"  =>  {  "TitleDetail"  =>

     {  "TitleElement"  =>  {  "TitleText"  =>   "Atlas  Shrugged"  }}}}   BetterStruct.new(product).descriptive_detail.title_detail.title_element.title_text.value   product["DescriptiveDetail"]  &&        product["DescriptiveDetail"]["TitleDetail"]  &&        product["DescriptiveDetail"]["TitleDetail"]["TitleElement"]  &&      product["DescriptiveDetail"]["TitleDetail"]["TitleElement"]["TitleText"]   ONIX example
  17. product   #  =>  {  "DescriptiveDetail"  =>  {  "TitleDetail"  =>

     {  "TitleElement"  =>  {  "TitleText"  =>   "Atlas  Shrugged"  }}}}   BetterStruct.new(product).descriptive_detail.title_detail.title_element.title_text.value   product["DescriptiveDetail"]  &&        product["DescriptiveDetail"]["TitleDetail"]  &&        product["DescriptiveDetail"]["TitleDetail"]["TitleElement"]  &&      product["DescriptiveDetail"]["TitleDetail"]["TitleElement"]["TitleText"]   product[“DescriptiveDetail”].      try(:[],  “TitleDetail").      try(:[],  “TitleElement").      try(:[],  "TitleText")   ONIX example
  18. product   #  =>  {  "DescriptiveDetail"  =>  {  "TitleDetail"  =>

     {  "TitleElement"  =>  {  "TitleText"  =>   "Atlas  Shrugged"  }}}}   BetterStruct.new(product).descriptive_detail.title_detail.title_element.title_text.value   product["DescriptiveDetail"]  &&        product["DescriptiveDetail"]["TitleDetail"]  &&        product["DescriptiveDetail"]["TitleDetail"]["TitleElement"]  &&      product["DescriptiveDetail"]["TitleDetail"]["TitleElement"]["TitleText"]   product[“DescriptiveDetail”].      try(:[],  “TitleDetail").      try(:[],  “TitleElement").      try(:[],  "TitleText")   product["DescriptiveDetail"]["TitleDetail"]["TitleElement"]["TitleText"]  rescue  nil ONIX example
  19. CSV example Título completo Año publicación Nombre 1 eISBN epub

    Programa de transición 2008 Trotsky, León 9781449262123 filepath  =  "spanish_publisher.csv"   books  =  CSV.parse(File.read(filepath),  headers:  true)   book_data  =  BetterStruct.new(books.first.to_h)  
  20. CSV example Título completo Año publicación Nombre 1 eISBN epub

    Programa de transición 2008 Trotsky, León 9781449262123 filepath  =  "spanish_publisher.csv"   books  =  CSV.parse(File.read(filepath),  headers:  true)   book_data  =  BetterStruct.new(books.first.to_h)   book_data.titulo_completo.value   #  =>  "Programa  de  transición"  
  21. CSV example Título completo Año publicación Nombre 1 eISBN epub

    Programa de transición 2008 Trotsky, León 9781449262123 filepath  =  "spanish_publisher.csv"   books  =  CSV.parse(File.read(filepath),  headers:  true)   book_data  =  BetterStruct.new(books.first.to_h)   book_data.titulo_completo.value   #  =>  "Programa  de  transición"   book_data.ano_publicacion.value   #  =>  "2008"  
  22. CSV example Título completo Año publicación Nombre 1 eISBN epub

    Programa de transición 2008 Trotsky, León 9781449262123 filepath  =  "spanish_publisher.csv"   books  =  CSV.parse(File.read(filepath),  headers:  true)   book_data  =  BetterStruct.new(books.first.to_h)   book_data.titulo_completo.value   #  =>  "Programa  de  transición"   book_data.ano_publicacion.value   #  =>  "2008"   book_data.nombre_1.split(",  ").reverse.join("  ").value   #  =>  "León  Trotsky"  
  23. CSV example Título completo Año publicación Nombre 1 eISBN epub

    Programa de transición 2008 Trotsky, León 9781449262123 filepath  =  "spanish_publisher.csv"   books  =  CSV.parse(File.read(filepath),  headers:  true)   book_data  =  BetterStruct.new(books.first.to_h)   book_data.titulo_completo.value   #  =>  "Programa  de  transición"   book_data.ano_publicacion.value   #  =>  "2008"   book_data.nombre_1.split(",  ").reverse.join("  ").value   #  =>  "León  Trotsky"   book_data.e_isbn_epub.value   #  =>  "9781449262123"