File: model_extend.rb

package info (click to toggle)
ruby-diva 2.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 264 kB
  • sloc: ruby: 1,967; sh: 8; makefile: 3
file content (105 lines) | stat: -rw-r--r-- 3,099 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# -*- coding: utf-8 -*-

require 'diva/field'
require 'diva/type'

=begin rdoc
Diva::Model のクラスメソッド
=end
module Diva::ModelExtend
  extend Gem::Deprecate

  attr_reader :slug, :spec

  # Modelのインスタンスのuriスキーム。オーバライドして適切な値にする
  # ==== Return
  # [String] URIスキーム
  def scheme
    @_scheme ||= to_s.split('::', 2).first.gsub(/\W/, '').downcase.freeze
  end

  # Modelのインスタンスのホスト名。オーバライドして適切な値にする
  # ==== Return
  # [String] ホスト名
  def host
    @_host ||= to_s.split('::', 2).last.split('::').reverse.join('.').gsub(/[^\w.]/, '').downcase.freeze
  end

  # Modelにフィールドを追加する。
  # ==== Args
  # [field_name] Symbol フィールドの名前
  # [type] Symbol フィールドのタイプ。:int, :string, :bool, :time のほか、Diva::Modelのサブクラスを指定する
  # [required] boolean _true_ なら、この項目を必須とする
  def add_field(field, type: nil, required: false)
    if field.is_a?(Symbol)
      field = Diva::Field.new(field, type, required: required)
    end
    (@fields ||= []) << field
    define_method(field.name) do
      @value[field.name]
    end

    define_method("#{field.name}?") do
      !!@value[field.name]
    end

    define_method("#{field.name}=") do |value|
      @value[field.name] = field.type.cast(value)
      self.class.store_datum(self)
      value
    end
    self
  end

  def fields
    @fields ||= []
  end
  alias :keys :fields
  deprecate :keys, 'fields', 2018, 2

  def schema
    {
      fields: fields.map(&:schema),
      uri: uri
    }
  end

  def uri
    @uri ||= Diva::URI("diva://object.type/#{slug || SecureRandom.uuid}")
  end

  #
  # プライベートクラスメソッド
  #

  def field
    Diva::FieldGenerator.new(self)
  end

  # URIに対応するリソースの内容を持ったModelを作成する。
  # URIに対応する情報はネットワーク上などから取得される場合もある。そういった場合はこのメソッドは
  # Delayer::Deferred::Deferredable を返す可能性がある。
  # とくにオーバライドしない場合、このメソッドは常に例外 Diva::NotImplementedError を投げる。
  # ==== Args
  # [uri] _handle_ メソッドで指定したいずれかの条件に一致するURI
  # ==== Return
  # [Delayer::Deferred::Deferredable]
  #   ネットワークアクセスを行って取得するなど取得に時間がかかる場合
  # [self]
  #   すぐにModelを生成できる場合、そのModel
  # ==== Raise
  # [Diva::NotImplementedError]
  #   このModelでは、find_by_uriが実装されていない
  # [Diva::ModelNotFoundError]
  #   _uri_ に対応するリソースが見つからなかった
  def find_by_uri(uri)
    raise Diva::NotImplementedError, "#{self}.find_by_uri does not implement."
  end

  # Modelが生成・更新された時に呼ばれるコールバックメソッドです
  def store_datum(retriever); end

  def container_class
    Array
  end
end