social-snippet/social-snippet-registry-core

View on GitHub
lib/social_snippet/registry/webapi/models/repository.rb

Summary

Maintainability
A
25 mins
Test Coverage
class SocialSnippet::Registry::WebAPI::Repository

  include Mongoid::Document
  include Mongoid::Timestamps # adds created_at and updated_at fields


  #
  # constants
  #

  ORIGIN_TYPE_GITHUB = 1

  FIELD_KEYS = [
    :name,
    :url,
    :desc,
    :dependencies,
    :license,
    :languages,
  ]


  #
  # field <name>, :type => <type>, :default => <value>
  #

  # Repository's Name (e.g. "my-repo")
  field :name, :type => String

  # Repository's URL (e.g. "git://github.com/user/repo.git")
  field :url, :type => String

  # Repository's description (e.g. "This is my repository.")
  field :desc, :type => String

  # Repository's dependencies (e.g. ["dep-to-1", "dep-to-2", ...])
  field :dependencies, :type => Array, :default => []

  # Repository's license (e.g. MIT)
  field :license, :type => String

  # Target programming languages (e.g. C++, Ruby)
  field :languages, :type => Array, :default => []

  field :origin_type, :type => Integer, :default => -> { detect_origin_type }

  # You can define indexes on documents using the index macro:
  # index :field <, :unique => true>
  index({name: 1}, {unique: true})

  # You can create a composite key in mongoid to replace the default id using the key macro:
  # key :field <, :another_field, :one_more ....>
 
  #
  # validations
  #
  validates_presence_of :name
  validates_presence_of :url
  validates_length_of :name, :minimum => 1, :maximum => 64
  validates_length_of :desc, :maximum => 200
  validates_length_of :url, :maximum => 256
  validates_length_of :license, :maximum => 64

  validate do
    errors[:name] << "Invalid name" unless self.class.is_valid_repo_name?(name)
    errors[:url] << "Invalid URL" unless self.class.is_valid_url?(url)
    if dependencies.is_a?(Array)
      errors[:dependencies] << "invalid dependencies" if has_invalid_dependencies?
      errors[:dependencies] << "The size of dependencies must be less than 64" if dependencies.length > 64
    end
    if languages.is_a?(Array)
      errors[:languages] << "The size of languages must be less than 64" if languages.length > 64
    end
  end

  def detect_origin_type
    if url.nil?
      nil
    elsif self.class.is_github_url?(url)
      ORIGIN_TYPE_GITHUB
    end
  end

  def has_invalid_dependencies?
    dependencies.any? {|dep_name| not self.class.is_valid_repo_name?(dep_name) }
  end

  def has_invalid_language?
    languages.any? {|language| not self.class.is_valid_language?(lang) }
  end

  #
  # methods
  #
  
  def to_object
    FIELD_KEYS.reduce({}) do |obj, key|
      obj[key.to_sym] = self[key]
      obj
    end
  end

  def update_by_snippet_json(json_obj)
    filter = %w(
      desc
    )
    repo_info = json_obj.select {|k, v| filter.include? k }
    write_attributes repo_info
    # deps: hash to array
    self.dependencies = json_obj["dependencies"] && json_obj["dependencies"].keys
  end

  class << self

    def is_github_url?(url)
      return false unless is_valid_url?(url)
      uri = ::URI.parse(url)
      "github.com" === uri.host && /^\/[^\/]+\/[^\/]+$/ === uri.path
    end

    def is_valid_url?(url)
      return false unless /^(http|https|git)\:\/\// === url
      uri = ::URI.parse(url)
      if "github.com" === uri.host
        return false unless /^\/[^\/]+\/[^\/]+$/ === uri.path
        return true
      end

      false
    end

    def is_valid_language?(language)
      /^[a-zA-Z0-9\.\-\_\+\#]+$/ === language
    end

    def is_valid_repo_name?(repo_name)
      /^[a-z][a-z0-9\.\-\_]*$/ === repo_name
    end

    def all_repos
      all.map {|repo| repo.to_object }
    end

    def query(s)
      where(:name => /#{s}/).map {|repo| repo.to_object } # TODO
    end

    def create_by_snippet_json(json_obj)
      model = find_or_create_by(:name => json_obj["name"])
      model.update_by_snippet_json json_obj
      return model
    end

  end # class << self

end # Repository