-2

我的应用程序正在使用 sidekiq 作业在数据库中保存一条推文。我在我的 rails 模型中解析 JSON 并创建依赖项。

这段代码没问题。

class PersistToDbWorker
  include Sidekiq::Worker

  def perform(tweet_id, user_id)
    tweet = TempTweet.get(tweet_id)

    if tweet
      db_tweet = Tweet.where(:id => tweet_id)
      if db_tweet.empty?
        tweet_user = TweetUser.create_or_update_tweet_user(tweet['user'])

        t = Tweet.create_from_json(tweet)
        t.tweet_user tweet_user
        t.users << User.find(user_id)
        t.save!
      else
        db_tweet.first.tweet_users << User.find(user_id)
      end
    end
  end
end

下一个最终变得丑陋。我需要帮助重构这段代码。如果您能帮助我弄清楚如何减少此代码或使其更清洁,我将非常高兴。我可以毫无问题地添加新的 gem,比如将 json 的字段映射到模型等。

class Tweet < ActiveRecord::Base
  belongs_to :tweet_user
  has_and_belongs_to_many :tweet_users
  has_and_belongs_to_many :tweet_hashtags
  has_and_belongs_to_many :tweet_urls
  has_and_belongs_to_many :users

  def self.create_from_json json
    new_tweet = Tweet.new
    new_tweet.id = json['id']
    new_tweet.text = json['text']

    if json['place']
      place = json['place']

      new_tweet.country = place['country']
      new_tweet.country_code = place['country_code']

      new_tweet.place_name = place['name']
      new_tweet.place_type = place['type']
      new_tweet.place_full_name = place['full_name']
    end

    new_tweet.tweet_user_id = json['user']['id']

    new_tweet.source = json['source']
    new_tweet.retweet_count = json['retweet_count']
    new_tweet.in_reply_to_user_id = json['in_reply_to_user_id']
    new_tweet.in_reply_to_status_id = json['in_reply_to_status_id']
    new_tweet.in_reply_to_screen_name = json['in_reply_to_screen_name']

    json['entities']['hashtags'].each do |hashtag|
      new_tweet.tweet_hashtags << from_tweet_hashtag(hashtag)
    end

    json['entities']['urls'].each do |url|
      new_tweet.tweet_urls << from_tweet_url(url)
    end

    json['entities']['user_mentions'].each do |user|
      new_tweet.tweet_users << from_tweet_user_mention(user)
    end

    new_tweet.created_at = Time.parse(json['created_at'])
    new_tweet
  end

  private

  def self.from_tweet_hashtag hashtag
    hashtags = TweetHashtag.where(:text => hashtag['text'])
    if hashtags.present?
      return hashtags.first
    else
      return TweetHashtag.new(:text => hashtag['text'])
    end
  end

  def self.from_tweet_url url
    urls = TweetUrl.where(:url => url['url'])
    if urls.present?
      return urls.first
    else
      return TweetUrl.new(:id => url['id'], 
        :expanded_url => url['expanded_url'], 
        :url => url['url'], 
        :display_url => url['display_url'])
    end
  end

  def self.from_tweet_user_mention tweet_user
    tweet_users = TweetUser.where(:id => tweet_user['id'])

    if tweet_users.present?
      return tweet_users.first
    else
      return TweetUser.new(:id => tweet_user['id'], 
        :screen_name => tweet_user['screen_name'], 
        :name => tweet_user['name'])
    end
  end
end
4

1 回答 1

1
class Tweet < ActiveRecord::Base
  belongs_to :tweet_user
  has_and_belongs_to_many :tweet_users
  has_and_belongs_to_many :tweet_hashtags
  has_and_belongs_to_many :tweet_urls
  has_and_belongs_to_many :users
  def self.create_from_json json; new.instance_eval do
    %w[
      id text source retweet_count in_reply_to_user_id in_reply_to_status_id
      in_reply_to_screen_name
    ].each{|k| instance_variable_set("@#{k}", json[k])}
    @tweet_user_id = json["user"]["id"]
    @created_at = Time.parse(json["created_at"])
    from_tweet(@tweet_hashtags, "hashtags",
      TweetHashtag, e, :text)
    from_tweet(@tweet_urls, "urls",
      TweetUrl, e, :url, :id, :expanded_url, :display_url)
    from_tweet(@tweet_users, "user_mentions",
      TweetUser, e, :id, :screen_name, :name)

    if place = json["place"]
      @country = place["country"]
      @country_code = place["country_code"]
      @place_name = place["name"]
      @place_type = place["type"]
      @place_full_name = place["full_name"]
    end
  end end
  private
  def from_tweet property, s, klass, h, k, *ks
    property.concat(json["entities"][s].map{|e|
      a = klass.where(k => h[k.to_s])
      a.present? ? a.first : klass.new(Hash[[k, *ks].map{|k| [k, h[k.to_s]]}])
    }
  end
end
于 2013-09-03T03:14:38.470 回答