iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0
Software Development

SQL rookie 之天天魯一下系列 第 13

Day 13 - 魯魯亂入SQL 領域(1) - 誤闖ActiveRecord::Base 篇

  • 分享至 

  • xImage
  •  

Hello, everyone!

終於可以進入下個階段囉!被翻爛的書今天想用新的專案練習Active Record 基本的query methods,並嘗試用SQL methods 來呈現及比較用法。由於自己是SQL 魯蛇,因此要特別留心method 的形態、單複數、大小寫等,那就讓我們開始吧!

首先我們來試試看取出User.first.email

irb(main):021:0> User.first.email
  User Load (0.6ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
"Sincere@april.biz"

這是Active Record 的data access method;可如果是利用SQL 可以怎麼寫呢?

我們先來組裝基本的語法:

SELECT * FROM users
#  ↓
SELECT * FROM users WHERE id = 1 
#  ↓ 
SELECT email FROM users WHERE id = 1 

我們試試看將SQL 丟到console 執行:

sql = "SELECT email FROM users WHERE id = 1"

# 目前查到了兩個比較適合的語法:

# 方法1
irb(main):031:0> ActiveRecord::Base.connection.exec_query(sql).rows
  SQL (0.7ms)  SELECT email FROM users WHERE id = 1
[
    [0] [
        [0] "Sincere@april.biz"
    ]
]

# 方法2
irb(main):032:0> User.find_by_sql(sql)
  User Load (0.7ms)  SELECT email FROM users WHERE id = 1
[
    [0] #<User:0x00007f94196c2fa0> {
           "id" => nil,
        "email" => "Sincere@april.biz"
    }
]

先稍微觀察、研究這兩個方法回傳的形態是什麼:

irb(main):042:0> ActiveRecord::Base.connection.exec_query(sql).class
  SQL (0.8ms)  SELECT email FROM users WHERE id = 1
ActiveRecord::Result < Object 

irb(main):044:0> User.find_by_sql(sql).class
  User Load (0.9ms)  SELECT email FROM users WHERE id = 1
Array < Object

有點混亂,但我們先查查第一個方法是來自哪(ActiveRecord::Base.connection.exec_query);

接著會看到一個很熟悉的字眼ActiveRecord::Base,這不是在app/models/application_record.rb出現過嗎:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

進去看了一下才發現有這東西:
lib/active_record/base.rb

下方的文字說明也在Rails Guide 看到,雖然水好像很深;之後再沿線搜尋,會找到這是個Active Record 的module ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements
Public Instance Methods

exec_query

Reference link

看起來是用丟SQL 語法進去,回傳一個處理後的ActiveRecord::Result XD

ActiveRecord::Result又是什麼呢:This class encapsulates a result returned from calling #exec_query on any database connection adapter.

是個會處理及回傳封裝後結果的類別

再去看看他的initialize方法:

def initialize(columns, rows, column_types = {})
  @columns      = columns
  @rows         = rows
  @hash_rows    = nil
  @column_types = column_types
end

大概是將SQL 處理的結果根據資料表的欄、列回傳個hash 吧 XD

整理一下,ActiveRecord::Base.connection.exec_query(sql) 應該是:

  1. 利用ActiveRecord::Base 建立與資料庫的連線(connection)
  2. 接著用exec_query query SQL
  3. 回傳一個hash result

嗯... 好像有看沒有懂,且回傳的結果有點雜,自己沒有很喜歡...
但,明天再繼續研究第二個方法User.find_by_sql(sql) 的由來好了 XD

今天的研究就到這結束吧,謝謝大家~


上一篇
Day 12 - 利用SampleDB seeding 資料(4)
下一篇
Day 14 - 魯魯亂入SQL 領域(2) - 續闖ActiveRecord::Base 篇
系列文
SQL rookie 之天天魯一下30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言