Class: Rack::Scaffold::Adapters::CoreData

Inherits:
Sequel
  • Object
show all
Defined in:
lib/rack/scaffold/adapters/core_data.rb

Instance Attribute Summary

Attributes inherited from Base

#klass

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Sequel

#one_to_many_associations, #paginate, #plural, #singular, #timestamps?

Methods inherited from Base

#[], #all, #count, #create!, #destroy!, #find, inherited, #method_missing, #one_to_many_associations, #paginate, #plural, #singular, #timestamps?, #update!, #update_timestamp_field

Constructor Details

#initialize(entity, options = {}) ⇒ CoreData

Returns a new instance of CoreData.



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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/rack/scaffold/adapters/core_data.rb', line 30

def initialize(entity, options = {})
  adapter = self.class
  klass = adapter.const_get(entity.name.capitalize)
  klass.dataset = entity.name.downcase.pluralize.to_sym

  klass.class_eval do
    alias_method :update!, :update
    alias_method :destroy!, :destroy

    self.strict_param_setting = false
    self.raise_on_save_failure = false

    plugin :json_serializer, naked: true, include: [:url]
    plugin :schema
    plugin :validation_helpers

    if options[:timestamps]
      if options[:timestamps].instance_of? Hash
        plugin :timestamps, options[:timestamps]
      else
        plugin :timestamps, update_on_create: true
      end
    end

    plugin :nested_attributes if options[:nested_attributes]

    def url
      "/#{self.class.table_name}/#{self[primary_key]}"
    end

    entity.relationships.each do |relationship|
      entity_options = { class: adapter.const_get(relationship.destination.capitalize) }

      if relationship.to_many?
        one_to_many relationship.name.to_sym, entity_options
        if options[:nested_attributes]
          nested_attributes relationship.name.to_sym
        end
      else
        many_to_one relationship.name.to_sym, options
      end
    end

    set_schema do
      primary_key :id

      entity.attributes.each do |attribute|
        next if attribute.transient?

        options = {
          null: attribute.optional?,
          index: attribute.indexed?,
          default: attribute.default_value
        }

        type = case attribute.type
               when 'Integer 16' then :int2
               when 'Integer 32' then :int4
               when 'Integer 64' then :int8
               when 'Float' then :float4
               when 'Double' then :float8
               when 'Decimal' then :float8
               when 'Date' then :timestamp
               when 'Boolean' then :boolean
               when 'Binary' then :bytea
               else :varchar
               end

        column attribute.name.to_sym, type, options
      end

      entity.relationships.each do |relationship|
        options = {
          index: true,
          null: relationship.optional?
        }

        unless relationship.to_many?
          column "#{relationship.name}_id".to_sym, :integer, options
        end
      end
    end

    if table_exists?
      missing_columns = schema.columns.reject { |c| columns.include?(c[:name]) }
      db.alter_table table_name do
        missing_columns.each do |options|
          add_column options.delete(:name), options.delete(:type), options
        end
      end
    else
      create_table
    end
  end

  klass.send :define_method, :validate do
    entity.attributes.each do |attribute|
      case attribute.type
      when 'Integer 16', 'Integer 32', 'Integer 64'
        validates_integer attribute.name
      when 'Float', 'Double', 'Decimal'
        validates_numeric attribute.name
      when 'String'
        validates_min_length attribute.minimum_value, attribute.name if attribute.minimum_value
        validates_max_length attribute.maximum_value, attribute.name if attribute.maximum_value
      end
    end
  end

  super(klass)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Rack::Scaffold::Adapters::Base

Class Method Details

.===(model) ⇒ Object



10
11
12
13
14
15
16
17
18
# File 'lib/rack/scaffold/adapters/core_data.rb', line 10

def ===(model)
  return true if ::CoreData::DataModel === model

  begin
    !!::CoreData::DataModel.new(model)
  rescue StandardError
    false
  end
end

.resources(xcdatamodel, options = {}) ⇒ Object



20
21
22
23
24
25
26
27
# File 'lib/rack/scaffold/adapters/core_data.rb', line 20

def resources(xcdatamodel, options = {})
  model = ::CoreData::DataModel.new(xcdatamodel)
  model.entities.each do |entity|
    const_set(entity.name.capitalize, Class.new(::Sequel::Model)) unless const_defined?(entity.name.capitalize)
  end

  model.entities.collect { |entity| new(entity, options) }
end