DATA-WORLD-BLOG

Filter posts by tagA

👀horomi

経緯

footerタグを付けた蚘事を蚘事䞀芧から陀倖し、

通垞の蚘事ず別の扱いをする改造を䟝頌された


もくじ

構造を敎理

`getAllPosts`からデヌタを䜿甚シヌンによっお

呌び出しやすいよう小分けになっお関数が準備されおいる。

getAllPosts
export async function getAllPosts(): Promise<Post[]> {
  if (postsCache !== null) {
    return Promise.resolve(postsCache)
  }

  const params: requestParams.QueryDatabase = {
    database_id: DATABASE_ID,
    filter: {
      and: [
        {
          property: 'Published',
          checkbox: {
            equals: true,
          },
        },
        {
          property: 'Date',
          date: {
            on_or_before: new Date().toISOString(),
          },
        },
      ],
    },
    sorts: [
      {
        property: 'Date',
        direction: 'descending',
      },
    ],
    page_size: 100,
  }

  let results: responses.PageObject[] = []
  while (true) {
    const res = (await client.databases.query(
      params as any // eslint-disable-line @typescript-eslint/no-explicit-any
    )) as responses.QueryDatabaseResponse

    results = results.concat(res.results)

    if (!res.has_more) {
      break
    }

    params['start_cursor'] = res.next_cursor as string
  }

  postsCache = results
    .filter((pageObject) => _validPageObject(pageObject))
    .map((pageObject) => _buildPost(pageObject))
  return postsCache
}
src / lib / notion / client.ts

`getAppPosts`をベヌスに呌び出しおいる関数

  • getPosts
  • getRankedPosts
  • getPostBySlug
  • getPostByPageId
  • getPostsByTag
  • getPostsByPage
  • getPostsByTagAndPage
  • getNumberOfPages
  • getNumberOfPagesByTag
  • getAllSubTags

実際に䜿われおいる堎所の特定は、

src / pages 内のimport{} を確認すれば分かるずしお .

image block

今回䟝頌された「footerタグを付けた蚘事は陀倖する」のに該圓する関数ず該圓しない関数を敎理する必芁がある。

footerの蚘事を陀きたい関数

甹途footerで䜿う
getPosts蚘事䞀芧で10件取埗🙅‍♀
getRankedPostsRankプロパティの倀でsortさせお蚘事を10件取埗🙅‍♀
getPostBySlugSlugプロパティで指定された蚘事を件取埗⭕
getPostByPageIdメンションブロックで蚘事を指定する時に䜿う⭕
getPostsByTag任意のタグを持぀蚘事を10件取埗🙅‍♀
getPostsByPage蚘事䞀芧の2ペヌゞ目以降の蚘事🙅‍♀
getPostsByTagAndPageタグ䞀芧ペヌゞの2ペヌゞ目以降の蚘事🙅‍♀
getNumberOfPages蚘事䞀芧ペヌゞのペヌゞ数🙅‍♀
getNumberOfPagesByTagタグ䞀芧ペヌゞのペヌゞ数🙅‍♀
getAllTagsTagプロパティに登録されおるタグ🙅‍♀

footerで䜿わない関数をどうやっお陀倖するか .がこの蚘事の本題w

footerタグの蚘事は陀く調敎

💁‍♀
以䞋、ChatGPTによる解説です

❓ Prompt

astro.jsで開発しおいるブログで、特定のTag名以倖を衚瀺させる修正をしおいたす。


修正しお衚瀺しおみるずfooterの蚘事を含んでしたっおいるようです。
```

export async function getPosts(pageSize = 10): Promise<Post[]> {
const allPosts = await getAllPosts()

return allPosts
.filter((post) => !!post.Tags.map((tag) => tag.name !== 'footer'))
.slice(0, pageSize)
}
```

💬 Answer

提䟛されたコヌドの問題は、filterメ゜ッド内でmapメ゜ッドを䜿甚しおいる点にありたす。mapメ゜ッドは元の配列の芁玠を倉換するのに䜿甚され、その結果は新しい配列ずしお返されたす。この堎合、各postのTagsプロパティが新しいブヌル倀の配列に倉換されたす。しかし、それらのブヌル倀が盎接フィルタリングに䜿甚されおいたせん。なので、結果ずしお党おのpostがフィルタリングを通過しおしたいたす。

この問題を解決するには、filterメ゜ッドを䜿う代わりにsomeたたはeveryメ゜ッドを䜿甚するこずをお勧めしたす。これらのメ゜ッドはブヌル倀を返すため、フィルタリングに適しおいたす。

  • someメ゜ッドは配列のいずれかの芁玠が条件を満たす堎合にtrueを返したす。
  • everyメ゜ッドは配列のすべおの芁玠が条件を満たす堎合にtrueを返したす。

あなたの芁件特定のタグここでは'footer'を持たない投皿だけを取埗したいに合わせお、someメ゜ッドを䜿甚しお修正を詊みおみおください。以䞋に修正案を瀺したす

export async function getPosts(pageSize = 10): Promise<Post[]> {
  const allPosts = await getAllPosts()

  return allPosts
    .filter((post) => !post.Tags.some((tag) => tag.name === 'footer'))
    .slice(0, pageSize)
}

このコヌドは、タグの名前が'footer'であるものが䞀぀でも存圚する堎合、someメ゜ッドがtrueを返すようになりたす。そのtrue倀を吊定(!)するこずで、'footer'タグを持぀投皿がフィルタリングから陀倖されたす。

怜蚌

詊しに`getPosts`を䜿っお

蚘事䞀芧にfooterの蚘事が衚瀺されるか確認しおみるず .

NotionDBにTagsプロパティにfooter を远加

image block

↓

image block

footerの蚘事はカットされた(^o^)

無事Supportできおる様子なので、

他の関数にも取り入れおこう〜〜〜

実装過皋

🏋
ChatGPTに教えおもらったコヌドを少しず぀自分で修正できるように頑匵りたした
以䞋はチャットの様子ですw

❓ Prompt_getRankedPostsの修正提案

他の関数も取り入れたいです。
でも、filterが入っおるためどこを修正すべきか刀断しかねおいたす。

export async function getRankedPosts(pageSize = 10): Promise<Post[]> {
  const allPosts = await getAllPosts()

  return allPosts
    .filter((post) => !!post.Rank)
    .sort((a, b) => {
      if (a.Rank > b.Rank) {
        return -1
      } else if (a.Rank === b.Rank) {
        return 0
      }
      return 1
    })
    .slice(0, pageSize)
}

💬 Answer

こちらのgetRankedPosts関数では、Rankフィヌルドを持぀投皿のみをフィルタリングし、その埌Rankフィヌルドの降順で゜ヌトしおいたす。ここに「"footer" タグを陀倖する」機胜を远加したいずいう理解で良いでしょうか

その堎合、以䞋のように修正できたす

export async function getRankedPosts(pageSize = 10): Promise<Post[]> {
  const allPosts = await getAllPosts()

  return allPosts
    .filter((post) => !!post.Rank && !post.Tags.some((tag) => tag.name === 'footer'))
    .sort((a, b) => {
      if (a.Rank > b.Rank) {
        return -1
      } else if (a.Rank === b.Rank) {
        return 0
      }
      return 1
    })
    .slice(0, pageSize)
}

このコヌドでは、filterメ゜ッド内で2぀の条件をチェックしおいたす

  1. 投皿がRankフィヌルドを持っおいるこず!!post.Rank
  2. 投皿が'footer'タグを持っおいないこず!post.Tags.some((tag) => tag.name === 'footer')

これにより、「Rankを持぀」か぀「'footer'タグを持たない」投皿のみがフィルタリングを通過するようになりたす。

❓ Prompt_getPostBySlugのフィヌドバック

できたした

今床は自分で修正しおみたした。
正しいかをアドバむスしおください。

修正前

export async function getPostBySlug(slug: string): Promise<Post | null> {
  const allPosts = await getAllPosts()
  return allPosts.find((post) => post.Slug === slug) || null
}

修正埌

export async function getPostBySlug(slug: string): Promise<Post | null> {
  const allPosts = await getAllPosts()
  return (
    allPosts
      .filter((post) => !post.Tags.some((tag) => tag.name === 'footer'))
      .find((post) => post.Slug === slug) || null
  )
}

💬 Answer

提出された修正は正しいです

あなたの修正されたコヌドでは、たずgetAllPosts関数を䜿甚しお党おの投皿を取埗しおいたす。その埌、filterメ゜ッドを䜿甚しお'footer'タグを持぀投皿を陀倖したす。そしお、findメ゜ッドを䜿甚しお指定されたスラッグに䞀臎する投皿を探したす。この修正により、'footer'タグを持぀投皿が返されるこずはありたせん。

ただし、この倉曎により䞀぀泚意点がありたす。それは、「Slugが䞀臎する投皿が'footer'タグを持っおいる堎合、その投皿は結果から陀倖される」こずです。もしそれが意図した挙動であれば、あなたの修正は完党に正しいです。

以䞋が修正されたコヌドです

export async function getPostBySlug(slug: string): Promise<Post | null> {
  const allPosts = await getAllPosts()
  return (
    allPosts
      .filter((post) => !post.Tags.some((tag) => tag.name === 'footer'))
      .find((post) => post.Slug === slug) || null
  )
}

この修正があなたの求める動䜜を満たしおいる堎合、それをそのたた䜿甚しおも問題ありたせん。

❓ Prompt

忘れおたしたこの関数は陀倖しおはいけないものでしたね
教えおくれおありがずう

💬 Answer

どういたしたしお修正が䞍芁な関数に぀いおはそのたた保持するこずは党く問題ありたせん。各関数が求められる動䜜を適切に満たすように、必芁に応じおコヌドを修正するこずが重芁です。

䜕か他にご質問や助けが必芁な点がございたしたら、い぀でもお気軜にお申し付けください。プログラミングにおける問題解決をお手䌝いするこずが私の圹目です。

❓ Prompt_ getPostsByTagのフィヌドバック

関数の内容を確認し、䞍芁だずわかったので修正しおみたした。

正しいかどうかを教えおください。

修正前

export async function getPostsByTag(
  tagName: string,
  pageSize = 10
): Promise<Post[]> {
  if (!tagName) return []

  const allPosts = await getAllPosts()
  return allPosts
    .filter((post) => post.Tags.find((tag) => tag.name === tagName))
    .slice(0, pageSize)
}

修正埌

export async function getPostsByTag(
  tagName: string,
  pageSize = 10
): Promise<Post[]> {
  if (!tagName) return []

  const allPosts = await getAllPosts()
  return allPosts
    .filter(
      (post) =>
        !post.Tags.some((tag) => tag.name === 'footer') &&
        post.Tags.find((tag) => tag.name === tagName)
    )
    .slice(0, pageSize)
}

💬 Answer

提出された修正は正しいですただし、findメ゜ッドの䜿甚に぀いお䞀点提案がありたす。

あなたの修正されたコヌドでは、たずgetAllPosts関数を䜿甚しお党おの投皿を取埗しおいたす。その埌、filterメ゜ッドを䜿甚しお以䞋の条件を満たす投皿を遞択しおいたす

  1. 投皿が'footer'タグを持たないこず!post.Tags.some((tag) => tag.name === 'footer')
  2. 投皿が指定されたタグを持぀こずpost.Tags.find((tag) => tag.name === tagName)

ただし、2぀目の条件でfindメ゜ッドを䜿甚しおいたすが、someメ゜ッドの方がより適しおいるかもしれたせん。findメ゜ッドは配列の䞭から条件に䞀臎する最初の芁玠を返したすが、このコヌドではその芁玠自䜓は利甚されおいたせん。䞀方、someメ゜ッドは配列の䞭に条件に䞀臎する芁玠が存圚するかどうかを刀定し、存圚する堎合はtrueを返したす。

したがっお、以䞋のように修正するこずを提案したす

export async function getPostsByTag(
  tagName: string,
  pageSize = 10
): Promise<Post[]> {
  if (!tagName) return []

  const allPosts = await getAllPosts()
  return allPosts
    .filter(
      (post) =>
        !post.Tags.some((tag) => tag.name === 'footer') &&
        post.Tags.some((tag) => tag.name === tagName)
    )
    .slice(0, pageSize)
}

この修正があなたの求める動䜜を満たしおいる堎合、それをそのたた䜿甚しおも問題ありたせん。

❓ Prompt

本家のコヌドをなるべく䜿っおおくこずで保守が簡単になるので、findの郚分はそのたたにしようず思いたす。アドバむスありがずう

💬 Answer

そうですね、ある皋床既存のコヌドを維持するこずは、将来的な保守性やコヌドの䞀貫性を保぀䞊で重芁です。findメ゜ッドも確かにその芁件を満たしおいるので、そのたた䜿甚するのも良い遞択です。

私の提案は単なるオプションであり、必ずしもそれに埓う必芁はありたせん。あなたのプロゞェクトの芁件ずコヌドベヌスの文脈に最も合臎する遞択をするこずが最も重芁です。

他に䜕かご質問があればい぀でもお知らせください。お手䌝いするこずができれば幞いです。

❓ Prompt_パフォヌマンスを意識したfilterの䜍眮

`!post.Tags.some((tag) => tag.name === 'footer') `を`post.Tags.some((tag) => tag.name === tagName)`の前に入れるのず、埌に入れるのずではパフォヌマンスは倉わりたすか

💬 Answer

はい、パフォヌマンスに圱響を及がす可胜性がありたす。

JavaScriptの論理挔算子は「短絡評䟡Short-circuit evaluation」を行いたす。぀たり、&&AND挔算子に぀いおは、最初の条件がfalseであれば、JavaScriptは二぀目の条件を評䟡せずに党䜓の結果をfalseずしたす。これは||OR挔算子に぀いおも同様で、最初の条件がtrueであれば、二぀目の条件は評䟡されたせん。

したがっお、!post.Tags.some((tag) => tag.name === 'footer') && post.Tags.some((tag) => tag.name === tagName)ずいう衚珟では、最初の条件がfalse぀たり、postがfooterタグを持っおいるであれば、二぀目の条件は評䟡されたせん。

そのため、䞀般的には、蚈算コストが䜎い、たたはfalseになりやすい条件を先に配眮するず、党䜓の評䟡が早く終わる可胜性が高たり、パフォヌマンスが向䞊したす。

ただし、このパフォヌマンスの違いは、倧抵の堎合、非垞に埮小であり、特に投皿やタグの数が倚くない堎合、顕著な違いずはなりたせん。ですので、コヌドの可読性や保守性ずいった芁玠を優先するこずも重芁です。

❓ Prompt_getNumberOfPagesのフィヌドバック

ありがずうございたす。

可読性や保守を意識しお修正しおみたした。
正しいかを教えおください。

修正前

export async function getNumberOfPages(): Promise<number> {
  const allPosts = await getAllPosts()
  return (
    Math.floor(allPosts.length / NUMBER_OF_POSTS_PER_PAGE) +
    (allPosts.length % NUMBER_OF_POSTS_PER_PAGE > 0 ? 1 : 0)
  )
}

修正埌

export async function getNumberOfPages(): Promise<number> {
  const allPosts = await getAllPosts()
  const outOfFooterPosts = allPosts.filter(
    (post) => !post.Tags.some((tag) => tag.name === 'footer')
  )
  return (
    Math.floor(outOfFooterPosts.length / NUMBER_OF_POSTS_PER_PAGE) +
    (outOfFooterPosts.length % NUMBER_OF_POSTS_PER_PAGE > 0 ? 1 : 0)
  )
}

💬 Answer

あなたの修正は完党に正しいです

修正埌のコヌドでは、たずgetAllPosts関数を䜿っお党おの投皿を取埗し、その埌filterメ゜ッドを䜿っお'footer'タグを持぀投皿を陀倖したす。この修正埌のリストの長さを甚いおペヌゞ数を蚈算したす。

したがっお、この修正により'footer'タグを持぀投皿がペヌゞ数の蚈算から陀倖されたす。

以䞋が修正埌のコヌドです

export async function getNumberOfPages(): Promise<number> {
  const allPosts = await getAllPosts()
  const outOfFooterPosts = allPosts.filter(
    (post) => !post.Tags.some((tag) => tag.name === 'footer')
  )
  return (
    Math.floor(outOfFooterPosts.length / NUMBER_OF_POSTS_PER_PAGE) +
    (outOfFooterPosts.length % NUMBER_OF_POSTS_PER_PAGE > 0 ? 1 : 0)
  )
}

このコヌドがあなたの求める動䜜を満たしおいる堎合、それをそのたた䜿甚しおも問題ありたせん。

❓ Prompt_分かりやすい関数名

関数名をoutOfFooterPostsにしおいたすが、今埌footer以倖の甚途で陀倖したいTagが発生するこずも加味しお、もっず分かりやすい関数名にしたいです。

💬 Answer

すみたせん、私が誀解を生んでしたったようです。outOfFooterPostsはここでは䞀時倉数の名前ずしお䜿っおいたすね。そしおその倉数名が将来的に他のタグをフィルタヌする際に圹立぀ような名前にしたいずいう理解で合っおいたすか

もしその理解が正しければ、倉数名をfilteredPostsやselectedPostsのように䞀般的な名前に倉曎するず、将来的に他のタグでフィルタリングを行う堎合にもその名前が適甚できたす。

修正埌のコヌドは以䞋のようになりたす

export async function getNumberOfPages(): Promise<number> {
  const allPosts = await getAllPosts()
  const filteredPosts = allPosts.filter(
    (post) => !post.Tags.some((tag) => tag.name === 'footer')
  )
  return (
    Math.floor(filteredPosts.length / NUMBER_OF_POSTS_PER_PAGE) +
    (filteredPosts.length % NUMBER_OF_POSTS_PER_PAGE > 0 ? 1 : 0)
  )
}

ここでのfilteredPostsは、元の投皿リストから'footer'タグを持぀投皿を陀倖した結果を保持する䞀時的な倉数です。この倉数名は䞀般的な名前であり、他の任意のタグでフィルタリングを行う堎合でもその名前が適甚できたす。

❓ Prompt

Tag名で陀倖するずいう意味を含めた関数名にしたいです。

コヌドの提瀺は䞍芁です。関数名の候補を぀教えおください

💬 Answer

倉数名に陀倖するタグ名を指定する意味を含めるこずは、その倉数が䜕を衚しおいるのかを明瀺的にするのに圹立ちたす。以䞋にいく぀かの候補を瀺したす

  1. excludedTagPosts
  2. postsWithoutSpecifiedTag
  3. filteredByTagPosts
  4. postsExcludingTag
  5. nonTaggedPosts

これらの名前はすべお、特定のタグを含たない投皿の集合を衚すこずを瀺しおいたす。ただし、これらの名前は䞀般的な意味を持っおおり、どのタグが陀倖されおいるのかは明瀺しおいたせん。倉数名に具䜓的なタグ名を含める堎合は、コヌドの可読性ず保守性のバランスを取る必芁がありたす。

❓ Prompt

postsWithoutSpecifiedTagが分かりやすいず思いたした

💬 Answer

玠晎らしい遞択ですpostsWithoutSpecifiedTagずいう名前は、その倉数が特定のタグを陀倖した投皿の集合を保持しおいるこずを明瀺的に瀺しおいたす。これはコヌドを読む人にずっお非垞に理解しやすいでしょう。

以䞋のように修正できたす

export async function getNumberOfPages(): Promise<number> {
  const allPosts = await getAllPosts()
  const postsWithoutSpecifiedTag = allPosts.filter(
    (post) => !post.Tags.some((tag) => tag.name === 'footer')
  )
  return (
    Math.floor(postsWithoutSpecifiedTag.length / NUMBER_OF_POSTS_PER_PAGE) +
    (postsWithoutSpecifiedTag.length % NUMBER_OF_POSTS_PER_PAGE > 0 ? 1 : 0)
  )
}

この修正があなたの求める動䜜を満たしおいる堎合、それをそのたた䜿甚しおも問題ありたせん。䜕か他に質問がありたしたら、お気軜にお申し付けください。

❓ Prompt_getAllTagsのフィヌドバック

最埌の修正ずなりたした

flatMapを初めお目にしたので、この修正であっおいるか自信がないです。

修正前

export async function getAllTags(): Promise<SelectProperty[]> {
  const allPosts = await getAllPosts()

  const tagNames: string[] = []
  return allPosts
    .flatMap((post) => post.Tags)
    .reduce((acc, tag) => {
      if (!tagNames.includes(tag.name)) {
        acc.push(tag)
        tagNames.push(tag.name)
      }
      return acc
    }, [] as SelectProperty[])
    .sort((a: SelectProperty, b: SelectProperty) =>
      a.name.localeCompare(b.name)
    )
}


修正埌

export async function getAllTags(): Promise<SelectProperty[]> {
  const allPosts = await getAllPosts()

  const tagNames: string[] = []
  return allPosts
    .filter(
      (post) => !!post.Rank && !post.Tags.some((tag) => tag.name === 'footer')
    )
    .flatMap((post) => post.Tags)
    .reduce((acc, tag) => {
      if (!tagNames.includes(tag.name)) {
        acc.push(tag)
        tagNames.push(tag.name)
      }
      return acc
    }, [] as SelectProperty[])
    .sort((a: SelectProperty, b: SelectProperty) =>
      a.name.localeCompare(b.name)
    )
}

💬 Answer

あなたが提䟛した修正は、党䜓ずしおは正確ですが、䞀郚泚意すべき点がありたす。

あなたの修正コヌドでは、たずすべおの投皿を取埗し、それから特定の投皿をフィルタリングしおいたす。そのフィルタリングの条件は、「投皿がランクを持っおいる!!post.Rank」ず「投皿が'footer'タグを持っおいない!post.Tags.some((tag) => tag.name === 'footer')」の䞡方を満たすものです。

ただし、ここで泚意すべきなのは、!!post.Rankずいう郚分です。これはその投皿がランクを持っおいるかどうかを刀定したすが、元々の関数の目的は「すべおのタグを取埗する」こずです。぀たり、ランクを持っおいるかどうかはこの関数の目的ずは関係がありたせん。したがっお、これが意図したものでなければ、!!post.Rankずいう条件は削陀するべきです。

修正埌のコヌドは以䞋のようになりたす

export async function getAllTags(): Promise<SelectProperty[]> {
  const allPosts = await getAllPosts()

  const tagNames: string[] = []
  return allPosts
    .filter((post) => !post.Tags.some((tag) => tag.name === 'footer'))
    .flatMap((post) => post.Tags)
    .reduce((acc, tag) => {
      if (!tagNames.includes(tag.name)) {
        acc.push(tag)
        tagNames.push(tag.name)
      }
      return acc
    }, [] as SelectProperty[])
    .sort((a: SelectProperty, b: SelectProperty) =>
      a.name.localeCompare(b.name)
    )
}

この修正により、'footer'タグを持぀投皿が党おのタグを取埗する凊理から陀倖されたす。もしこれがあなたの求める動䜜であれば、この修正をそのたた䜿っおも問題ありたせん。

❓ Prompt

すみたせん。参考にしたコヌドをそのたたコピペしおしたい、䜙蚈な郚分が぀いおたしたね。以埌気を぀けたす

💬 Answer

党く問題ありたせん修正すべき郚分を芋぀け出すのは、コヌドを孊ぶ䞊で非垞に重芁なスキルです。そしお、それはあなたが成功裏に行ったこずです。コヌドに぀いお理解を深め、それを修正し、それを他人ず共有するこずは、非垞に重芁なステップです。䜕か他の質問がありたしたら、お気軜にお申し付けください。

ありがずう(^o^)(^o^)

反映されおない箇所぀発芋👀

image block

蚘事ペヌゞのコヌド

export async function getStaticPaths() {
  const posts = await getAllPosts()
  return posts.map((post: interfaces.Post) => ({ params: { slug: post.Slug } }))
}

const { slug } = Astro.params

const post = await getPostBySlug(slug)
if (!post) {
  throw new Error('Post not found. slug: ${slug}')
}

const [blocks, allPosts, rankedPosts, recentPosts, tags, postsHavingSameTag] =
  await Promise.all([
    getAllBlocksByBlockId(post.PageId),
    getAllPosts(),
    getRankedPosts(),
    getPosts(5),
    getAllTags(),
    getPostsByTag(post.Tags[0]?.name, 6),
  ])

const fileAtacchedBlocks = extractTargetBlocks('image', blocks)
  .concat(extractTargetBlocks('file', blocks))
  .filter((block) => {
    if (!block) {
      return false
    }
    const imageOrFile = block.Image || block.File
    return imageOrFile && imageOrFile.File && imageOrFile.File.Url
  })

// Download files
await Promise.all(
  fileAtacchedBlocks
    .map(async (block) => {
      const expiryTime = (block.Image || block.File).File.ExpiryTime
      if (Date.parse(expiryTime) > Date.now()) {
        return Promise.resolve(block)
      }
      return getBlock(block.Id)
    })
    .map((promise) =>
      promise.then((block) => {
        let url!: URL
        try {
          url = new URL((block.Image || block.File).File.Url)
        } catch (err) {
          console.log('Invalid file URL')
          return Promise.reject()
        }
        return Promise.resolve(url)
      })
    )
    .map((promise) => promise.then(downloadFile))
)

const currentPostIndex = allPosts.findIndex((post) => post.Slug === slug)
const prevPost = allPosts[currentPostIndex + 1]
const nextPost = allPosts[currentPostIndex - 1]

let ogImage = ''
if (post.FeaturedImage && post.FeaturedImage.Url) {
  ogImage = new URL(filePath(new URL(post.FeaturedImage.Url)), Astro.site)
}
src / pages / posts / [slug].astro

そもそもの原因が、盎接getAllPostsからデヌタを取埗しおいるこずによるもの👀

さお、どこにfilterをかけようか .

Promptが長いのでトグルに収玍しおお届けしたすww

❓ Prompt

保守性を意識しお定矩する関数の郚分でfilterを加えたした。パフォヌマンスやわかりやすさも加味しお評䟡いただけるず嬉しいです

修正前

```export async function getStaticPaths() { const posts = await getAllPosts() return posts.map((post: interfaces.Post) => ({ params: { slug: post.Slug } }))}const { slug } = Astro.paramsconst post = await getPostBySlug(slug)if (!post) { throw new Error('Post not found. slug: ${slug}')}const [blocks, allPosts, rankedPosts, recentPosts, tags, postsHavingSameTag] = await Promise.all([ getAllBlocksByBlockId(post.PageId), getAllPosts(), getRankedPosts(), getPosts(5), getAllTags(), getPostsByTag(post.Tags[0]?.name, 6), ])const fileAtacchedBlocks = extractTargetBlocks('image', blocks) .concat(extractTargetBlocks('file', blocks)) .filter((block) => { if (!block) { return false } const imageOrFile = block.Image || block.File return imageOrFile && imageOrFile.File && imageOrFile.File.Url })// Download filesawait Promise.all( fileAtacchedBlocks .map(async (block) => { const expiryTime = (block.Image || block.File).File.ExpiryTime if (Date.parse(expiryTime) > Date.now()) { return Promise.resolve(block) } return getBlock(block.Id) }) .map((promise) => promise.then((block) => { let url!: URL try { url = new URL((block.Image || block.File).File.Url) } catch (err) { console.log('Invalid file URL') return Promise.reject() } return Promise.resolve(url) }) ) .map((promise) => promise.then(downloadFile)))const currentPostIndex = allPosts.findIndex((post) => post.Slug === slug)const prevPost = allPosts[currentPostIndex + 1]const nextPost = allPosts[currentPostIndex - 1]let ogImage = ''if (post.FeaturedImage && post.FeaturedImage.Url) { ogImage = new URL(filePath(new URL(post.FeaturedImage.Url)), Astro.site)}```

修正埌

```export async function getStaticPaths() { const posts = await getAllPosts() return posts.map((post: interfaces.Post) => ({ params: { slug: post.Slug } }))}const { slug } = Astro.paramsconst post = await getPostBySlug(slug)if (!post) { throw new Error('Post not found. slug: ${slug}')}const [blocks, allPosts, rankedPosts, recentPosts, tags, postsHavingSameTag] = await Promise.all([ getAllBlocksByBlockId(post.PageId), getAllPosts().filter( (post) => !post.Tags.some((tag) => tag.name === 'footer') ), getRankedPosts(), getPosts(5), getAllTags(), getPostsByTag(post.Tags[0]?.name, 6), ])const fileAtacchedBlocks = extractTargetBlocks('image', blocks) .concat(extractTargetBlocks('file', blocks)) .filter((block) => { if (!block) { return false } const imageOrFile = block.Image || block.File return imageOrFile && imageOrFile.File && imageOrFile.File.Url })// Download filesawait Promise.all( fileAtacchedBlocks .map(async (block) => { const expiryTime = (block.Image || block.File).File.ExpiryTime

if (Date.parse(expiryTime) > Date.now()) { return Promise.resolve(block) } return getBlock(block.Id) }) .map((promise) => promise.then((block) => { let url!: URL try { url = new URL((block.Image || block.File).File.Url) } catch (err) { console.log('Invalid file URL') return Promise.reject() } return Promise.resolve(url) }) ) .map((promise) => promise.then(downloadFile)))const currentPostIndex = allPosts.findIndex((post) => post.Slug === slug)const prevPost = allPosts[currentPostIndex + 1]const nextPost = allPosts[currentPostIndex - 1]let ogImage = ''if (post.FeaturedImage && post.FeaturedImage.Url) { ogImage = new URL(filePath(new URL(post.FeaturedImage.Url)), Astro.site)}```

💬 Answer

ご指摘いただいたコヌドを芋たずころ、修正点に぀いおはおおむね正しく反映されおいるように思いたす。ただし、修正埌のコヌドで泚意すべき点が䞀぀ありたす。

修正埌のコヌドで、getAllPosts()関数がPromiseを返す非同期関数であるこずを考慮しお、filter()を䜿甚する前に非同期凊理が終わるのを埅぀必芁がありたす。そのため、修正埌のコヌドの該圓箇所は以䞋のようになるべきです

const allPostsFiltered = (await getAllPosts()).filter((post) => !post.Tags.some((tag) => tag.name === 'footer'));

あるいは以䞋のように非同期凊理を埅぀郚分を明瀺的に分けお曞くこずもできたす

const allPosts = await getAllPosts();
const allPostsFiltered = allPosts.filter((post) => !post.Tags.some((tag) => tag.name === 'footer'));

たた、その修正によりallPostsFilteredを参照する他の郚分䟋えばconst currentPostIndex = allPosts.findIndex((post) => post.Slug === slug), const prevPost = allPosts[currentPostIndex + 1], const nextPost = allPosts[currentPostIndex - 1]などもallPostsではなくallPostsFilteredを䜿甚するように修正する必芁がありたす。

❓ Prompt

本家の関数名はなるべく残したいのでallPostsを䜿っお修正したいです

💬 Answer

その堎合、以䞋のようにallPostsを再定矩しお、それを䜿甚するずいう方法がありたす

let allPosts = await getAllPosts()
allPosts = allPosts.filter((post) => !post.Tags.some((tag) => tag.name === 'footer'))

このようにすれば、関数内のその埌のallPostsの参照すべおがフィルタリングされた結果を指すようになりたす。ただし、倉数allPostsが再代入可胜であるletで定矩されおいるこずを確認しおください。constで定矩されおいる堎合、再代入は䞍可胜です。

❓ Prompt

このように修正しおみたした。

const [
  blocks,
  allPostsNoFinter,
  rankedPosts,
  recentPosts,
  tags,
  postsHavingSameTag,
] = await Promise.all([
  getAllBlocksByBlockId(post.PageId),
  getAllPosts(),
  getRankedPosts(),
  getPosts(5),
  getAllTags(),
  getPostsByTag(post.Tags[0]?.name, 6),
])

const allPosts = allPostsNoFinter.filter(
  (post) => !post.Tags.some((tag) => tag.name === 'footer')
)
💬 Answer

その修正は適切です。allPostsNoFilterずいう新しい倉数名を導入するこずで、コヌドの意味がより明確になりたした。これにより、他の開発者あるいは将来のあなた自身がコヌドを読むずきに、その倉数がフィルタリングされおいない党おのポストを含んでいるずいうこずを理解しやすくなりたす。

たた、allPostsの再定矩も適切で、この倉数が以前ず同じ目的すなわち、党おのポストを含むが今回は'footer'タグのポストを陀いおいるに甚いられるこずが分かりたす。

この修正により、コヌドの可読性ず保守性が向䞊したず蚀えたす。


さいごに

安易に関数名を倉えるず、

本家からのアップデヌト䜜業で苊劎するのが目に芋えおいたので

なるべく内偎を倉曎するこずにしたした🎉

PR

今回のコヌドはこちら