Model中好用的小知识

Model中好用的小知识

ids

在strong params内加入post_ids:[],使用simple_form时只要写上f.association就可以了,传入controller的时候会形成post_ids这个array,rails会根据post_ids帮我们建立关联

1
2
3
4
<%= simple_form_for @drink do |f| %>
<%= f.association :materials, :as => :check_boxes %><br>
<%= f.submit "Submit" %>
<% end %>

collect(&:id)

1
2
3
users = User.all
users.collect(&:id)
users.collect(&:name)

这都可以把users中的id或者name都拿出来组成一个array

比如:

1
2
topics = [{id:1,title:"topic1"},{id:2,title:"topic2"}]
topics.collect(&:id)

执行结果 [1,2]

把id都变成浮点数

1
topics.collect{ |t| t.id.to_f }

或者

1
topics.collect(&:id).collect(&:to_f)

产生结果:[1.0,2.0]

includes

不好的写法

1
2
3
4
5
class Board < ActiveRecord
def
@bards = Board.all
end
end

然后在view中使用@board.topics,来获得每一个topic,如果有10个topics,这样系统会到数据库中查找10次。

如果用includes

1
2
3
4
5
class Board < ActiveRecord
def
@bards = Board.includes(:topics).all
end
end

在view中写@board.topics,就只会去数据库查找一次,把10个topic一次查出来,然后把抓出来的所有topic和board用board_id相关联。
这样做减少了数据库的负担。提到效能。

counter_cache

counter_cache是在做关联关系时计算数据量的一个方法。
不好的写法:

1
@board.topics.size

这代表我们都要算数量的时候都得通过sql去数据库计算topics,也会造成效能问题。
所以rails内建了counter_cache方法。

1
2
3
class Topic < ActiveRecord
belongs_to :board, counter_cache: true
end

在Board表中增加字段topics_count.这样以后Board内的topics有增减的时候,rails就会帮我们增减topics_count,这样在写@board.topics.size后,rails就会预设去找topics_count,不用重新生成sql去数据库中查找。

如果想写成自己定义的字段名称,如count_of_topics,那么可以这样做

1
2
3
class Topic < ActiveRecord
belongs_to :board, counter_cache: :count_of_topics
end

STI

单一表格继承 STI(Single-table inheritance)

Rails Guide 對此的說明:

a way to add inheritance to your models

让子类继承父类的属性和方法。
在父类中加入type,来表示类型

例:User有分 Native 跟 Foreigner;
使用场景:拥有一样的特性,但是行为不同时使用继承。

1
2
3
4
5
6
7
8
9
10
11
12
class User < ActiveRecord::Base
end
class Native < User
end
class Foreigner < User
end
native = Native.create(name:"foobar")
native.type
得出"Native"

Polymorphic Assoiciaion

Polymorphic Assoiciaion是rails内让两个不同的Model同时has_many一个model的做法。最常见的就是做留言系统的时候。

对文章可以留言,对看板留言,但是这些留言所需要的字段都是一样的,没必要建两套。
那么,这样的model只需要新增一个Comment model再用Polymorphic Assoiciaion关联就可以了。

1
2
3
4
5
6
7
8
9
10
11
class Comment < ActiveRecord
belongs_to :commentable, :polymorphic => true
end
class Board < ActiveRecord
has_many :comments, :as => :commentable
end
class Topic < ActiveRecord
has_many :comments, :as => :commentable
end

Comment里面必须包含两个字段。
commentable_id和commentable_type
commentable_type记录model名称
commentable_id记录该model下的id

Rails3之後的 migration 可以單獨寫t.references :imageable, polymorphic: true就會自動生成這兩個欄位。

1
2
3
4
5
6
7
8
9
class CreatePictures < ActiveRecord::Migration
def change
create_table :pictures do |t|
t.string :name
t.references :imageable, polymorphic: true
t.timestamps
end
end
end