【Rails】입력된 값을 바탕으로 GET요청을 보내 데이터를 취득하여 DB에 저장

16786 단어 JSON루비Rails

하는 것



이번에는 GET statuses/oembed — Twitter Developers을 사용하여 트위터 카드를 표시합니다.

임베디드 HTML을 검색하려면 인증이 필요하지 않으므로 간단한 요청으로 데이터를 검색할 수 있습니다.

흐름은 다음과 같습니다.
  • 입력된 URL에서 ID 얻기
  • 요청을 보내 데이터를 가져옵니다
  • URL, json을 데이터베이스에 저장
  • 저장된 데이터 표시

  • 개발 환경



    Ruby 2.6.5
    Rails 5.2.3
    MySQL 8.0.19

    컨트롤러



    별도로 드문 일은하지 않습니다.
    redirect_to, render는 적합합니다.

    tweets_controller.rb
    class TweetsController < ApplicationController
      def create
        if @tweet.create(tweet_params)
          redirect_to tweet_path(@tweet)
        else
          render :new
        end
      end
    
      def update
        @tweet = Tweet.find(params[:id])
        if @tweet.update(tweet_params)
          redirect_to tweet_path(@tweet)
        else
          render :edit
        end
      end
    
      private
    
      def tweet_params
        params.require(:tweet).permit(:url)
      end
    end
    

    모델



    사전에 json을 넣을 예정인 t_json 컬럼을 마이그레이션으로 작성해 둡니다.
    (추기) json을 1 컬럼을 넣는 것은, 변경이나 데이터의 취득이 곤란하기 때문에 안티 패턴이라고 말해지고 있습니다. 사용할 때는주의하십시오.

    tweet.rb
    # == Schema Information
    #
    # Table name: tweets
    #
    #  id         :bigint           not null, primary key
    #  url        :string(255)      not null
    #  t_json     :json             not null
    #  created_at :datetime         not null
    #  updated_at :datetime         not null
    #
    
    class Tweet < ApplicationRecord
      validates :url, presence: true, length: { maximum: 200 }
    end
    

    이 상태에서는 입력한 URL만 저장됩니다. 그래서 url에서 t_json을 얻고 저장할 때까지의 흐름을 순서대로 따라갑니다.

    1. 입력된 URL에서 ID 얻기



    URL은, 예를 들면 https://twitter.com/Interior/status/507185938620219395 의 형태가 됩니다만, 요구에 필요한 것은 ID의 507185938620219395 의 부분만입니다.
    그러면 입력된 URL에서 ID가 되는 문자열을 추출하는 tweet_id라는 인스턴스 메서드를 만듭니다.
      def tweet_id
        url.split('/').last
      end
    

    덧붙여서, tweet.tweet_id 라고 하는 쓰는 방법으로, 모델의 외부로부터도 ID를 취득할 수 있습니다.

    2. 요청을 제출하여 데이터 검색



    TwitterAPI에 GET 요청을 보냅니다.
    curl 명령은 다음과 같은 명령입니다.

    ExampleRequest
    $ curl 'https://publish.twitter.com/oembed?url=https%3A%2F%2Ftwitter.com%2FInterior%2Fstatus%2F507185938620219395'
    

    이것을 Ruby로 구현합니다. 두 가지 방법을 언급합니다.

    open_uri를 사용하는 방법


      def tweet_json
        url = "https://publish.twitter.com/oembed?url=https%3A%2F%2Ftwitter.com%2FInterior%2Fstatus%2F#{tweet_id}"
        responce = OpenURI.open_uri(url)  # リクエストを送り、返り値をresponceに代入
        ActiveSupport::JSON.decode(responce.read)
      end
    

    Net :: HTTP를 사용하는 방법


      def tweet_json
        url = "https://publish.twitter.com/oembed?url=https%3A%2F%2Ftwitter.com%2FInterior%2Fstatus%2F#{tweet_id}"
        uri = URI.parse(url)
        responce = Net::HTTP.get(uri)  # リクエストを送り、返り値をresponceに代入
        JSON.parse(responce)
      end
    

    Ruby HTTP 요청을 보내는 방법의 성능 비교 에 의하면, Net::HTTP 쪽이 빠른 것 같습니다.

    이제 다음과 같은 json 형식의 데이터를 반환하는 메서드를 만들 수있었습니다.
    {
      "url": "https://twitter.com/Interior/status/507185938620219395",
      "author_name": "US Dept of Interior",
      "author_url": "https://twitter.com/Interior",
      "html": "<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Happy 50th anniversary to the Wilderness Act! Here&#39;s a great wilderness photo from <a href="https://twitter.com/YosemiteNPS">@YosemiteNPS</a>. <a href="https://twitter.com/hashtag/Wilderness50?src=hash">#Wilderness50</a> <a href="http://t.co/HMhbyTg18X">pic.twitter.com/HMhbyTg18X</a></p>&mdash; US Dept of Interior (@Interior) <a href="https://twitter.com/Interior/status/507185938620219395">September 3, 2014</a></blockquote>n<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>",
      "width": 550,
      "height": null,
      "type": "rich",
      "cache_age": "3153600000",
      "provider_name": "Twitter",
      "provider_url": "https://twitter.com",
      "version": "1.0"
    }
    

    3. 얻은 json을 tweet.t_json에 저장하고 저장



    tweet을 저장하기 전에 before_save 를 사용하여 t_json 에 값을 넣기로 합니다.set_json 메소드의 역할은, URL이 변경되고 있었을 경우, t_json 에 값을 넣는다는 것입니다.
    외부 API를 너무 두드리는 것은 좋지 않기 때문에 URL이 바뀌지 않은 경우는 특별히 변경하지 않습니다 (이번 예에서는 그 밖에 변경할 수 있는 컬럼이 없기 때문에 별로 필요하지 않습니다만).

    tweet.rb
    class Tweet < ApplicationRecord
      before_save :set_json # 追加
    
      def set_json
        self.t_json = tweet_json if will_save_change_to_url?
      end
    
      def tweet_json
        # TwitterAPIから取得したJSONデータを返す
      end
    end
    

    최종 모델



    tweet.rb
    class Tweet < ApplicationRecord
      before_save :set_json
      validates :url, presence: true, length: { maximum: 200 }
    
      def tweet_id
        url.split('/').last
      end
    
      private  # 以下のメソッドは外部から呼び出さないのでprivateにする
    
      def set_json
        self.t_json = tweet_json if will_save_change_to_url?
      end
    
      def tweet_json
        url = "https://publish.twitter.com/oembed?url=https%3A%2F%2Ftwitter.com%2FInterior%2Fstatus%2F#{tweet_id}"
        uri = URI.parse(url)
        responce = Net::HTTP.get(uri)
        JSON.parse(responce)
      end
    

    보기



    Twitter 카드를 표시하려면 json의 "html"를 그대로 HTML로 출력하면 좋으므로 뷰 파일에서 다음과 같이 작성합니다.

    view.html.erb
    <%= @tweet.t_json['html'].html_safe %>
    

    트윗 정보를 얻는 옵션


    "https://publish.twitter.com/oembed?url=https%3A%2F%2Ftwitter.com%2FInterior%2Fstatus%2F#{tweet_id}&omit_script=true"
    

    이렇게 & 로 연결합니다. (파라미터의 종류에 대해서는 공식 페이지 참조)omit_script=true 로 하면, <script> 부분을 제외한 HTML이 돌려주어지므로, 1 페이지에 복수의 트윗을 표시하는 경우는 추천입니다.

    view.html.erb
    <% @tweets.each do |tweet| %>
      <%= tweet.t_json['html'].html_safe %>
    <% end %>
    
    <%= javascript_include_tag '//platform.twitter.com/widgets.js' %>
    

    링크


  • Ruby에서 JSON 형식의 결과가 반환되는 URL을 Parse

  • 예외 처리 등 세세하게 실시하는 경우
  • Ruby on Rails에서 API를 활용하여 간단한 애플리케이션 만들기
  • rails 푹신한 01 : rails로 WebAPI를 두드리는
  • 좋은 웹페이지 즐겨찾기