Class: MysqlSimpleOrm::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/mysql_simple_orm.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = {}) ⇒ Base

Returns a new instance of Base.



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/mysql_simple_orm.rb', line 6

def initialize(attrs={})
  self.class.build_entity_methods
  
  cols = self.class.fetch_columns.select{|c| c.to_s != 'id'}.map(&:to_sym)
  attrs.keys.each { |key| attrs[key.to_sym] = attrs.delete(key)}
  cols.each do |c|
    if !attrs.has_key?(c)
      attrs[c] = nil 
    end
  end

  attrs.each do |key, val| 
    if !self.class.method_defined?(key)
      raise "No method `#{key}` for #{self.class.name.capitalize} instance." 
    end
    send("#{key}=", val) if key.to_s != 'id'
    @id = val if key.to_s == 'id'
  end
 
end

Class Method Details

.allObject



195
196
197
198
# File 'lib/mysql_simple_orm.rb', line 195

def all
  sql = "SELECT * FROM #{table_name}"
  exec(sql).map{|row| new(row)}
end

.at(position) ⇒ Object



178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/mysql_simple_orm.rb', line 178

def at(position)
  if position == :first
    order = 'ASC'
  elsif position == :last
    order = 'DESC'
  end

  return nil unless order
  
  sql = "SELECT * FROM #{table_name} ORDER BY id #{order} LIMIT 1"
  new exec(sql).first
end

.belongs_to(model) ⇒ Object



120
121
122
123
124
125
126
127
# File 'lib/mysql_simple_orm.rb', line 120

def belongs_to(model)
  define_method(model) do
    # binding.pry
    foreign_key = "#{model}_id"
    Object.const_get(model.to_s.capitalize)
      .where("id = #{send(foreign_key)}").first
  end
end

.build_entity_methodsObject



157
158
159
# File 'lib/mysql_simple_orm.rb', line 157

def build_entity_methods
  columns(*fetch_columns)
end

.check_errors(obj, fields) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/mysql_simple_orm.rb', line 99

def check_errors(obj, fields)
  (@validations || []).map do |validation| 
    field = validation[0].to_s
    msg = validation[1]
    block = validation[2]
    if fields.include? field
      if block
        evaluation = block.call(obj)
        {field: field, msg: msg[:msg]} if !evaluation
      end
    end
  end.compact
end

.columns(*args) ⇒ Object



235
236
237
238
239
240
# File 'lib/mysql_simple_orm.rb', line 235

def columns(*args)
  args.each do |f| 
    attr_accessor(f) if f != 'id'  
    attr_reader(f) if f == 'id'
  end
end

.condition_builder(cond) ⇒ Object



209
210
211
212
213
214
215
216
217
# File 'lib/mysql_simple_orm.rb', line 209

def condition_builder(cond)
  res = cond.reduce('') do |res, each_cond|
    attr = each_cond.first
    value = each_cond.last
    operator = value.is_a?(Array) ? "IN (#{value.map{|x|"'#{x}'"}.join(', ')})": "= '#{value}'"
    res += "#{attr.to_s} #{operator} AND "
  end
  res[0...-5]
end

.create(attrs) ⇒ Object



230
231
232
233
# File 'lib/mysql_simple_orm.rb', line 230

def create(attrs)
  obj = new(attrs)
  obj.save ? obj : nil
end

.exec(sql) ⇒ Object



226
227
228
# File 'lib/mysql_simple_orm.rb', line 226

def exec(sql)
  @@db_client.query(sql)
end

.fetch_columnsObject



165
166
167
168
# File 'lib/mysql_simple_orm.rb', line 165

def fetch_columns
  cols = exec("EXPLAIN #{table_name}")
  cols.map{|row| row['Field'] }
end

.filtered_attrsObject



161
162
163
# File 'lib/mysql_simple_orm.rb', line 161

def filtered_attrs
  fetch_columns.select{|f| f != 'id'}
end

.find(id) ⇒ Object



191
192
193
# File 'lib/mysql_simple_orm.rb', line 191

def find(id)
  where(id: id).first
end

.firstObject



170
171
172
# File 'lib/mysql_simple_orm.rb', line 170

def first
  at(:first)
end

.has_many(model, **fk) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/mysql_simple_orm.rb', line 141

def has_many(model, **fk)
  self.define_singleton_method(:via) do
    fk[:via] 
  end
  method_name = model
  method_name = fk[:as] if fk[:as]
  singular = model.to_s.chop
  # p method_name
  define_method(method_name) do
    foreign_key = "#{self.class.name.downcase}_id"
    foreign_key = fk[:via] if !fk[:via].nil?
    Object.const_get(singular.capitalize)
      .where("#{foreign_key} = #{send(:id)}")
  end
end

.has_one(model, **fk) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
# File 'lib/mysql_simple_orm.rb', line 129

def has_one(model, **fk) 
  method_name = model
  method_name = fk[:as] if fk[:as]
  define_method(method_name) do
    # binding.pry
    foreign_key = "#{model}_id"
    foreign_key = fk[:via] if fk[:via]
    Object.const_get("#{model.to_s.capitalize}")
      .where("id = #{send(foreign_key)}").first
  end
end

.joins(model, cond = nil) ⇒ Object



200
201
202
203
204
205
206
207
# File 'lib/mysql_simple_orm.rb', line 200

def joins(model, cond=nil)
  fk = "#{table_name.to_s.chop}_id"
  fk = self.via.to_s if self.via
  sql = "SELECT * FROM #{table_name} INNER JOIN #{model.to_s} ON #{model.to_s}.#{fk} = #{table_name}.id"
  sql += " WHERE #{cond}" if cond
  p sql
  exec(sql).map{|row| binding.pry; new(row)}
end

.lastObject



174
175
176
# File 'lib/mysql_simple_orm.rb', line 174

def last
  at(:last)
end

.method_missing(method, *args) ⇒ Object



94
95
96
97
# File 'lib/mysql_simple_orm.rb', line 94

def method_missing(method, *args)
  return where($1 => args.first).first if method.to_s =~ /^get_by_(.+)/
  super
end

.setupObject



83
84
85
86
87
88
89
90
91
# File 'lib/mysql_simple_orm.rb', line 83

def setup
  options = yield
  @@db_client = Mysql2::Client.new(
    host: options[:host], 
    username: options[:username], 
    password: options[:password], 
    database: options[:database]
  )
end

.table_nameObject



242
243
244
245
# File 'lib/mysql_simple_orm.rb', line 242

def table_name
  return "#{self.to_s.downcase}s" if superclass.to_s == 'MysqlSimpleOrm::Base'
  "#{superclass.to_s.downcase}s"
end

.validate(field, message, &block) ⇒ Object



113
114
115
116
117
118
# File 'lib/mysql_simple_orm.rb', line 113

def validate(field, message, &block)
  validation = [field, message]
  validation << block if block_given?
  @validations ||= []
  @validations << validation
end

.where(cond) ⇒ Object



219
220
221
222
223
224
# File 'lib/mysql_simple_orm.rb', line 219

def where(cond)
  cond = condition_builder(cond) if cond.is_a?(Hash)
  sql = "SELECT * FROM #{table_name} WHERE #{cond}"
  puts sql
  exec(sql).map{|row| new(row)}
end

Instance Method Details

#errorsObject



76
77
78
# File 'lib/mysql_simple_orm.rb', line 76

def errors
  (@errors ||= []).compact.uniq
end

#saveObject



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
# File 'lib/mysql_simple_orm.rb', line 49

def save
  filtered_attrs = self.class.filtered_attrs
  @errors = self.class.check_errors(self, filtered_attrs)
  return false if errors.to_a.any?
  if id.nil?
    items = filtered_attrs.reduce({k: [], v: []}) do |res, k|
      res[:k] << "`#{k}`"
      res[:v] << "'#{send(k)}'"
      res
    end 
    values = "(#{items[:k].join(', ')}) VALUES (#{items[:v].join(',')})"
    sql = "INSERT INTO #{self.class.table_name} #{values}"
    self.class.exec(sql)
    @id = @@db_client.last_id
    return true
  else
    attrs = filtered_attrs.reduce({}) do |res, c|
      res[c] = send(c)
      res
    end
    update_with(attrs)
  end
rescue => e
  puts e
  false  
end

#update_with(attrs = {}) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/mysql_simple_orm.rb', line 27

def update_with(attrs={})
  return false if id.nil?
  
  allowed_attrs = attrs.select do |k, v| 
    self.class.fetch_columns.include?(k.to_s) && k.to_s != 'id'
  end

  allowed_attrs.each{|k, v| send("#{k}=", v)}

  filtered_attrs = self.class.filtered_attrs
  @errors = self.class.check_errors(self, filtered_attrs)
  
  return false if errors.to_a.any?

  values = allowed_attrs.map{|k,v| "`#{k}` = '#{v}'"}.join(', ')
  sql = "UPDATE #{self.class.table_name} SET #{values} WHERE id=#{id}"
  self.class.exec(sql)
  return true
rescue
  false 
end