# [rails][model][note]rails4 model & 資料庫語法筆記
###### tags: `rails`,`Rails4`,`model`,`note`
## CRUD語法相關筆記
### regex相關
ex1
```ruby
regex = "\\d{4}-\\d{2}-\\d{2}"
customers = Customer.where("birthday ~* '#{regex}'")
```
### group+count簡例
https://stackoverflow.com/questions/27815296/group-count-having-and-order-by-in-rails
```ruby
# 取出每個顧客的訂單數
Order.group(:customer_id).count
# 取出每個顧客的訂單大於2的訂單數量
Order.group(:customer_id).having("count(customer_id) > 2").count
# 取出顧客的訂單數量大於2的總顧客數
Order.group(:customer_id).having("count(customer_id) > 2").count.keys.count
```
### 將query轉為raw sql語法
https://stackoverflow.com/questions/5483407/subqueries-in-activerecord
```ruby
User.where(:id => [5, 1, 2, 3]).to_sql
```
### raw query
https://stackoverflow.com/questions/15855606/rails-4-raw-query-using-activerecord
https://stackoverflow.com/questions/14824453/rails-raw-sql-example
### 找出非null跟empty的record
https://blog.arkency.com/rails-how-to-find-records-where-column-is-not-null-or-empty/
### 寫入時間日期
https://stackoverflow.com/questions/41224597/ruby-on-rails-how-to-save-current-datetime-to-database
```ruby
Customer.update(first.created_at: Datetime.Now)
```
### where相關
#### 用where+update_all更新資料
https://stackoverflow.com/questions/9186822/how-do-i-do-an-update-statement-where-a-condition
```ruby
UrModel.where(state: 'decline').update_all(state: 'deny')
```
>在where情況下若使用update會出現argument error
>
#### 關於where.not跟nil
https://thoughtbot.com/blog/activerecord-s-where-not-and-nil
>where.not無法取得欄位為null的值!
#### where with raw query
https://stackoverflow.com/questions/17192829/does-rails-4-have-support-for-or-queries
```ruby
Article.where("articles.title = 'Rails 3' OR articles.title = 'Rails 4'")
```
#### where not in with raw query
```ruby
text_array = ["status1","status2"]
output = Order.where("orders.column1 IS NULL OR (orders.column1 NOT IN ('#{text_array.join("','")}'))")
```
#### 用陣列查詢
@users = User.where(id:[1,2,3])
## Scope
https://railsbook.tw/chapters/16-model-basic.html#scope-and-class-method
### 設定資料預設排序
```ruby
class Product < ActiveRecord::Base
default_scope {order('id ASC')}
end
```
## Model
### 檢查某筆資料是否存在於資料表中
https://stackoverflow.com/questions/18082778/rails-checking-if-a-record-exists-in-database
```ruby
if Truck.where(:id => current_truck.id).blank?
# no truck record for this id
else
# at least 1 record for this truck
end
```
### 取得關連式資料表的資料
https://progressbar.tw/courses/3/watching
ex1
cat為主分類,subcat為次分類,
cat與subcat為1 to N relationship
subcat belongs_to cat
cat has_many subcats
/app/models/subcat.rb
```ruby=
class Subcat < ActiveRecord::Base
belongs_to :cat
has_many :products
def get_subcat_name
"#{cat.name}/#{name}"
end
end
```
>重點1:直接用小寫cat可取得subcat上層cat的資料
>重點2:直接在model裡面打model的屬性即可取得該屬性
### 取出資料中所有id:使用ids
rails console
```c!
2.2.6 :039 > Cat.all.ids
(0.4ms) SELECT "cats"."id" FROM "cats"
=> [1, 2, 3]
```
## join相關
### join三個資料表
三個資料表:cats(主分類),subcats(次分類),products(產品)
cats has many subcats
subcats belongs to cats
subcats has many products
products belongs to subcats
#### 較差的寫法: 直接join
https://stackoverflow.com/questions/10322164/rails-3-joins-select-only-certain-columns
models/cat.rb
```ruby=
class Cat < ActiveRecord::Base
has_many :subcats
end
```
models/subcat.rb
```ruby=
class Subcat < ActiveRecord::Base
belongs_to :cat
has_many :products
end
```
models/product.rb
```ruby=
class Product < ActiveRecord::Base
belongs_to :subcat
end
```
application_controller.rb
```ruby
class ApplicationController < ActionController::Base
#...
def get_products(id,subcat_id= nil)
begin
cat_id = id
@cat=Cat.find_by(id: cat_id)
if subcat_id
@subcat=@cat.subcats.find_by(id: subcat_id)
raise if !@subcat
return @subcat.products
else
return Product.joins(subcat: :cat)
.select(%Q(
products.id as id,
subcats.id as subcat_id,
cats.id as cat_id,
cats.name as cat_name,
subcats.name as subcat_name,
products.name,
products.description,
products.img_url,
products.price
))
.where(subcat_id: @cat.subcats.ids)
end
rescue
redirect_to products_cat_path(Cat.first)
end
end
end
```
>寫在appplication_controller的function可以被所有controller呼叫
#### 較好的寫法: 使用has_many: though
models/cat.rb
```ruby=
class Cat < ActiveRecord::Base
has_many :subcats
has_many :products, through: :subcats #<--加上這行
end
```
models/subcat.rb
```ruby=
class Subcat < ActiveRecord::Base
belongs_to :cat
has_many :products
end
```
models/product.rb
```ruby=
class Product < ActiveRecord::Base
belongs_to :subcat
end
```
application_controller.rb
```ruby
class ApplicationController < ActionController::Base
#...
def get_products(id,subcat_id= nil)
begin
cat_id = id
@cat=Cat.find_by(id: cat_id)
if subcat_id
@subcat=@cat.subcats.find_by(id: subcat_id)
raise if !@subcat
return @subcat.products
else
return @cat.products #<--改成這樣
end
rescue
redirect_to products_cat_path(Cat.first)
end
end
end
```
### 計算join後結果的總筆數
假設用上述method去結合table,如何計算資料的總筆數?
ans: 用size
controller
```ruby=
#...
@products = get_products(params[:id])
@total = @products.size
#...
```
>不能用count,會出問題
## 設定連動刪除
https://stackoverflow.com/questions/2203835/how-can-i-delete-child-objects-when-the-parent-is-deleted-in-rails
```ruby
class Table1 < ActiveRecord::Base
has_many :table1_table2_relationships,:dependent => :destroy
has_many :table2s,through: :table1_table2_relationships
end
```