解决方案

Sequel简介

seo靠我 2023-09-23 13:50:14

Sequel: Ruby数据库工具包

简介

Sequel是Ruby中用于访问SQL数据库的一个简单、灵活、强大的工具包。

Sequel能够保证线程安全,提供了连接池功能以及简洁的SDL用于创建SQL查询及表SEO靠我定义;Sequel包括一个强大的ORM层用于映射数据库记录和Ruby对象以及相关的记录;Sequel提供一些高级的数据库特写,比如,预处理的语句,绑定变量、存储过程、事务、两阶段提交、事务隔离、主/从SEO靠我结构及数据库分片。Sequel现在可以适配ADO, Amalgalite, CUBRID, DataObjects, IBM_DB, JDBC, MySQL, Mysql2, ODBC, OracleSEO靠我, PostgreSQL, SQLAnywhere, SQLite3, Swift, and TinyTDS。

Sequel被设计用来简单的连接和操作数据库,Sequel处理所有繁杂的事情,比如,保持连SEO靠我接、使用正确的SQL格式以及获取数据,这样你就可以专注于自己的应用了。

Sequel使用数据库的概念来检索数据。一个数据集对象封装了一个SQL查询并且支持关联(原文是supports chainabilSEO靠我ity,意思应该是关联),使你能够通过简洁灵活的Ruby DSL来方便的获取数据。

例如,下面的一行代码就可以返回中东地区国家的平均GDP:DB[:countries].filter(:region =SEO靠我> Middle East).avg(:GDP)

这条语句等价于:

SELECT avg(GDP) FROM countries WHERE region = Middle East

由于数据库只有在需要的SEO靠我时候才取回数据,所以被缓存以便再使用。记录是作为Hash类型返回的,所以可以使用一个可枚举的接口访问:

middle_east = DB[:countries].filter(:region => MiSEO靠我ddle East) middle_east.order(:name).each{|r| puts r[:name]}

Sequel还提供了简便的方法用于从数据集中提取数据,比如一个扩展SEO靠我的map方法:

middle_east.map(:name) #=> [Egypt, Turkey, Israel, ...]

或者是通过.to_hash方法把结果作为一个hash,一列作为kye,另一列SEO靠我作为value:

middle_east.to_hash(:name, :area) #=> {Israel => 20000, Turkey => 120000, ...}

安装

gem install SEO靠我sequel

小例子

require sequelDB = Sequel.sqlite # memory database, requires sqlite3DB.create_table :items SEO靠我doprimary_key :idString :nameFloat :price enditems = DB[:items] # Create a dataset# PopulateSEO靠我 the table items.insert(:name => abc, :price => rand * 100) items.insert(:name => deSEO靠我f, :price => rand * 100) items.insert(:name => ghi, :price => rand * 100)# Print out the numSEO靠我ber of records puts "Item count: #{items.count}"# Print out the average price puts "SEO靠我The average price is: #{items.avg(:price)}"

Sequel控制台

Sequel包含一个IRB控制台用于快速的访问数据库,使用方式如下:

sequel sqlite:SEO靠我//test.db # test.db in current directory

这样就可以获得一个IRB会话用于访问数据库。

入门

连接数据库

你可以使用Sequel.connect(URL)方法来连接数据SEO靠我库:

require sequel DB = Sequel.connect(sqlite://blog.db) # requires sqlite3

URL可以包含用户名、密码、端口号:

DSEO靠我B = Sequel.connect(postgres://user:password@host:port/database_name) # requires pg

你也可以提供可选参数,例如,连接池大SEO靠我小,SQL查询的logger:

DB = Sequel.connect("postgres://user:password@host:port/database_name",:max_connectioSEO靠我ns => 10, :logger => Logger.new(log/db.log))

你也可以为连接提供一个block,block执行完成后会从数据库连接断开:

Sequel.connect(postSEO靠我gres://user:password@host:port/database_name){|db| db[:posts].delete}

DB约定

在Sequel文档中,我们使用DB常量来表示你创建的SSEO靠我equel::Database实例。

另外,一些使用Sequel的框架,可能已经为你创建好了Sequel::Database实例,但是你可能不知道怎么获取它,大部分情况下你可以通过Sequel::ModSEO靠我el.db来获取。

任意的SQL命令

你可以使用Database#run来执行任意的SQL命令:

DB.run("create table t (a text, b text)") DB.rSEO靠我un("insert into t values (a, b)")

你也可以通过SQL来获取数据集:

dataset = DB[select id from items] dataset.SEO靠我count # will return the number of records in the result set dataset.map(:id) # will return aSEO靠我n array containing all values of the id column in the result set

通过SQL语句获取的数据集,你可以操作每一条记录:

DB[select *SEO靠我 from items].each do |row|p row end

在SQL语句中,还可以使用占位符:

name = Jim DB[select * from itemSEO靠我s where name = ?, name].each do |row|p row end

获取数据集实例

数据集是记录被检索和操作的主要方式,他们基本是通过Database#from和SEO靠我Database#[]方法获得的:

posts = DB.from(:posts) posts = DB[:posts] # same

获取记录

你可以通过all方法获取所有记录:

postsSEO靠我.all # SELECT * FROM posts

all方法返回一个包含hash的数组,每个hash对应一条记录。

你也可以通过each迭代器来访问记录:posts.each{|rowSEO靠我| p row}

或者更拽一点:

names_and_dates = posts.map([:name, :date]) old_posts, recent_posts = posts.pSEO靠我artition{|r| r[:date] < Date.today - 7}

可以获取第一条记录:

posts.first # SELECT * FROM posts LIMIT 1

或者SEO靠我获取指定的记录:

posts[:id => 1] # SELECT * FROM posts WHERE id = 1 LIMIT 1

如果数据集是有序的,你也可以获取最后一条记录:

posSEO靠我ts.order(:stamp).last # SELECT * FROM posts ORDER BY stamp DESC LIMIT 1

过滤记录

一个过滤记录的简单方式是通过提供给SEO靠我where方法一个hash:

my_posts = posts.where(:category => ruby, :author => david) # WHERE category =SEO靠我 ruby AND author = david

也可以指定一个范围:

my_posts = posts.where(:stamp => (Date.today - 14)..(Date.today - SEO靠我7)) # WHERE stamp >= 2010-06-30 AND stamp <= 2010-07-07

或者一个数据:

my_posts = posts.where(:categoSEO靠我ry => [ruby, postgres, linux]) # WHERE category IN (ruby, postgres, linux)

Sequel也可以接受表达式:

my_SEO靠我posts = posts.where{stamp > Date.today << 1} # WHERE stamp > 2010-06-14 my_posts = pSEO靠我osts.where{stamp =~ Date.today} # WHERE stamp = 2010-07-14

一些数据库还允许指定正则表达式:

my_posts = posts.wSEO靠我here(:category => /ruby/i) # WHERE category ~* ruby

你也可以使用exclude进行反向过滤:

my_posts = posts.exclSEO靠我ude(:category => [ruby, postgres, linux]) # WHERE category NOT IN (ruby, postgres, linux)

你甚至SEO靠我可以提供一个WHERE语句:

posts.where(stamp IS NOT NULL) # WHERE stamp IS NOT NULL

字符串中也可以使用参数,比如:

author_SEO靠我name = JKR posts.where((stamp < ?) AND (author != ?), Date.today - 3, author_name) #SEO靠我 WHERE (stamp < 2010-07-11) AND (author != JKR)

数据集也可以用于子查询:

DB[:items].where(price > ?, DB[:items].seSEO靠我lect{avg(price) + 100}) # WHERE price > (SELECT avg(price) + 100 FROM items)

汇总记录

count方法可以很方便SEO靠我的统计记录数量:

posts.where(Sequel.like(:category, %ruby%)).count # SELECT COUNT(*) FROM posts WHERESEO靠我 category LIKE %ruby%

通过max/min方法可以获取最大/最小值:

max = DB[:history].max(:value) # SELECT max(valueSEO靠我) FROM historymin = DB[:history].min(:value) # SELECT min(value) FROM history

通过sum/avg方法可以计算SEO靠我和/平均值:

sum = DB[:items].sum(:price) # SELECT sum(price) FROM items avg = DB[:items].aSEO靠我vg(:price) # SELECT avg(price) FROM items

记录排序

通过order方法可以对数据集进行排序:

posts.order(:stamp) SEO靠我 # ORDER BY stamp posts.order(:stamp, :name) # ORDER BY stamp, name

链式的order和where一样,SEO靠我不起作用:

posts.order(:stamp).order(:name) # ORDER BY name

但是可以使用order_append/order_prepend方法:

postSEO靠我s.order(:stamp).order_append(:name) # ORDER BY stamp, nameposts.order(:stamp).order_prepend(SEO靠我:name) # ORDER BY name, stamp

你也可以指定降序:

posts.reverse_order(:stamp) # ORDER BY stamp DSEO靠我ESC posts.order(Sequel.desc(:stamp)) # ORDER BY stamp DESC

核心扩展

注意上面的例子中使用的Sequel.descSEO靠我(:stamp),大部分的Sequel DSL使用这种方式,调用Sequel module方法返回SQL表达式实例。Sequel提供了一个核心扩展将Sequel DSL和Ruby语言更好的整合在一起,SEO靠我所以你可以这样写:

:stamp.desc

这个下面是等价的:

Sequel.desc(:stamp)

选择列

select方法可以用于选择列:

posts.select(:stamp) # SESEO靠我LECT stamp FROM posts posts.select(:stamp, :name) # SELECT stamp, name FROM posts

链式的SEO靠我select效果和order类似,最后一个生效,而不是像where:

posts.select(:stamp).select(:name) # SELECT name FROM postSEO靠我s

类似的,select也有一个select_append方法:

posts.select(:stamp).select_append(:name) # SELECT stamp, namSEO靠我e FROM posts

删除记录

使用delete方法即可:

posts.where(stamp < ?, Date.today - 3).delete # DELETE FROM posSEO靠我ts WHERE stamp < 2010-07-11

使用delete时要小心,因为delete会影响数据集中的所有行;先调用select,在调用delete:

# DO THIS: pSEO靠我osts.where(stamp < ?, Date.today - 7).delete # NOT THIS: posts.delete.where(stamp < SEO靠我?, Date.today - 7)

插入数据

使用insert方法:

posts.insert(:category => ruby, :author => david) # INSERT SEO靠我INTO posts (category, author) VALUES (ruby, david)

更新数据

使用update方法:

posts.where(stamp < ?, Date.today -SEO靠我 7).update(:state => archived) # UPDATE posts SET state = archived WHERE stamp < 2010-07-07

SEO靠我可以引用要设置的列:

posts.where{|o| o.stamp < Date.today - 7}.update(:backup_number => Sequel.+(:backup_numberSEO靠我, 1)) # UPDATE posts SET backup_number = backup_number + 1 WHERE stamp < 2010-07-07

和delete类似SEO靠我,update会影响数据集中所有的记录,所以,显示用where,再使用update:

# DO THIS: posts.where(stamp < ?, Date.today - 7).SEO靠我update(:state => archived) # NOT THIS: posts.update(:state => archived).where(stamp SEO靠我< ?, Date.today - 7)

事务

你可以通过Database#transaction方法把代码打包到一个数据库事务中:

DB.transaction doposts.insert(:categSEO靠我ory => ruby, :author => david)posts.where(stamp < ?, Date.today - 7).update(:state => archived) SEO靠我 end

如果代码块没有出现异常,这个事务就会被提交。如果出现了异常,事务就会回滚,异常会被抛出。如果你想回滚事务,但是不想在block外抛出异常,你可以在block里面抛出Sequel::RolSEO靠我lack异常:

DB.transaction doposts.insert(:category => ruby, :author => david)if posts.filter(stamp < ?, SEO靠我Date.today - 7).update(:state => archived) == 0raise Sequel::Rollbackend end

联接表

Sequel中连接表很简单SEO靠我

order_items = DB[:items].join(:order_items, :item_id => :id).where(:order_id => 1234) # SELSEO靠我ECT * FROM items INNER JOIN order_items # ON order_items.item_id = items.id # WHERE SEO靠我order_id = 1234

这里需要注意的是,item_id会自动使用被连接的表限定,id会自动使用上个联接的表进行限定。

在Sequel中,默认的selection是选择所有联接表的所有列。但是SeSEO靠我quel返回的是一个以列名作为key的hash,所有如果有不同表包含相同的列名,返回的hash结果就会有问题。所以使用连接时,通常会使用select、select_all或者select_appendSEO靠我

Sequel中的列引用

Sequel期望指定的列名使用符号,另外,返回的hash结果也使用符号作为key。在很多情况下,这让你可以自由的混用字面值和列引用。下面两行代码产生等价的SQL语句:

itemsSEO靠我.where(:x => 1) # SELECT * FROM items WHERE (x = 1) items.where(1 => :x) # SSEO靠我ELECT * FROM items WHERE (1 = x)"

Ruby的字符串类型也被当做SQL字符串类型处理:

items.where(:x => x) # SELECT * FRSEO靠我OM items WHERE (x = x)

限定标识符

在SQL中,标识符用于表示一个列、表或者数据库的名字。标识符可以使用带双下划线的特殊符号限定:table__column:

items.literaSEO靠我l(:items__price) # items.price

另一种限定列的方式是使用Sequel.qualify方法:

items.literal(Sequel.qualify(:iteSEO靠我ms, :price)) # items.price

通过表名来限定列是比较常见的,你也可以使用数据库名来限定表:

posts = DB[:some_schema__posts] SEO靠我 # SELECT * FROM some_schema.posts

别名

可以使用三下划线来取别名,:column___alias 或者 :table__column___alias::

itemsSEO靠我.literal(:price___p) # price AS p items.literal(:items__price___p) # items.pSEO靠我rice AS p

另一种方式是使用Sequal.as方法:

items.literal(Sequel.as(:price, :p)) # price AS p

你可以使用Sequel.asSEO靠我为任意表达式指定别名,而不只是标识符。

Sequel模型

一个模型类封装了一个数据集,该类的一个实例封装了数据集的一条记录。

Model类是继承自Sequel::Model的普通Ruby类:DB = SeqSEO靠我uel.connect(sqlite://blog.db) class Post < Sequel::Model end

当一个Model类被创建后,它会处理数据库中的表SEO靠我,并且设置表中所有列的存取方法(Sequel::Model实现了active record模式)。

Sequel模型类假定表名是类名的复数形式: Post.table_name #=> :posts

你可以SEO靠我显示的指定表名,或者为数据集指定:

class Post < Sequel::Model(:my_posts) end # or: Post.set_daSEO靠我taset :my_posts

你可以传递给set_dataset一个符号,它假定你要关联到的是同名的表。你也可以通过数据集调用,这将为该model的所有查询设置默认值。

Post.set_datasetSEO靠我 DB[:my_posts].where(:category => ruby) Post.set_dataset DB[:my_posts].select(:id, :name).orSEO靠我der(:date)

这一段表示没看明白:

If you call set_dataset with a symbol, it assumes you are referring to the tableSEO靠我 with the same name. You can also call it with a dataset, which will set the defaults for all retrieSEO靠我vals for that model:

Post.set_dataset DB[:my_posts].where(:category => ruby) Post.set_datasetSEO靠我 DB[:my_posts].select(:id, :name).order(:date)

模型实例

模型实例由主键标识。大多数情况下,Sequel查询数据库来决定主键,如果没有,默认使用id。ModeSEO靠我l.[]方法可以用来根据主键提取数据。

post = Post[123]

pk方法用于返回该记录的主键值:

post.pk #=> 123

Sequel模型允许你使用任何列作为主键,即使是由多个列组成的复合键SEO靠我

class Post < Sequel::Modelset_primary_key [:category, :title] endpost = Post[ruby, hello woSEO靠我rld] post.pk #=> [ruby, hello world]

通过no_primary_key,你也可以定义一个没有主键的模型类,同时你也丧失了简单的更新/删除记录的能力了:SEO靠我

Post.no_primary_key

一个单一模型实例也可以通过指定一个条件获取:

post = Post[:title => hello world] post = Post.firsSEO靠我t{num_comments < 10}

一个model类将很多的方法转发给了底层的数据集,这意味着你可以使用大多数的Dataset API去创建返回模型实例的自定义查询:

Post.where(:catSEO靠我egory => ruby).each{|post| p post}

你也可以操作数据集中的记录:

Post.where{num_comments < 7}.delete Post.wheSEO靠我re(Sequel.like(:title, /ruby/)).update(:category => ruby)

访问记录值

一个模型实例以hash的形式存储了它的值,hash中的key为符号形式的列名SEO靠我,可以通过values方法获取实例的值:

post.values #=> {:id => 123, :category => ruby, :title => hello world}

你可以像访问对象属性SEO靠我一样访问一个记录的值:

post.id #=> 123 post.title #=> hello world

如果记录的属性名在模式能够的数据集中不是有效的列名(比如你使用了select_SEO靠我append方法添加了一个通过计算得到的列),你可以使用Model#[]来访问这些值:

post[:id] #=> 123 post[:title] #=> hello world

你还可SEO靠我以通过以下方式修改记录的值:

post.title = hey there post[:title] = hey there

这只会改变model实例的值,不会更新数据库中的数据。要更新数SEO靠我据库中的数据,必须使用save方法:

post.save

多列赋值

你可以通过一个方法的调用给多个列赋值,例如,set方法更新模型的列值但不保存到数据库中:

post.set(:title=>hey therSEO靠我e, :updated_by=>foo)

update方法完成类似的功能,但是会保存到数据中:

post.update(:title => hey there, :updated_by=>foo)

创建新记SEO靠我

可以通过调用Model.create方法创建新记录:

post = Post.create(:title => hello world)

另一种方式是先创建实例,然后再保存:

post = Post.neSEO靠我w post.title = hello world post.save

你也可以为Model.new和Model.create方法提供一个块:

post = Post.nSEO靠我ew do |p|p.title = hello world endpost = Post.create{|p| p.title = hello world}

回调

你可以通过钩子方法在创SEO靠我建、更新、删除时执行特定方法。钩子方法包括:

before_create and after_createbefore_update and after_updatebefore_save and afSEO靠我ter_savebefore_destroy and after_destroybefore_validation and after_validation class Post < Sequel::SEO靠我Modeldef after_createsuperauthor.increase_post_countenddef after_destroysuperauthor.decrease_post_coSEO靠我untend end

自定义钩子方法时,记得调用super方法。几乎所有的Sequel::Model方法都可以被安全的重写,但一定要调用super方法,否则就有出错的风险。

对于上面的例子SEO靠我,你也快而已使用数据库触发器。钩子可以用于保证数据的完整性,但是只有在通过model实例修改数据库时才会保证,同时还会面临很多竞态条件。最好是使用数据库触发器和约束来保证数据完整性。

删除记录

你可以调用SEO靠我delete或destroy方法删除记录,这两个方法的唯一区别是,destroy方法会调用before_destroy和after_destroy钩子方法,但是delete不会:

post.deleteSEO靠我 # => bypasses hooks post.destroy # => runs hooks

通过delete和destroy也可以一次删除多个符合条件的记录:

Post.whereSEO靠我(:category => 32).delete # => bypasses hooks Post.where(:category => 32).destroy # => runs hSEO靠我ooks

注意,destroy方法会挨个删除记录,但是delete会在一次SQL查询中删除所有符合的记录。

关联

模型类之间的关系使用关联表示,用于反映数据库中表的关系,在数据库中通常通过外键指定。通过如下SEO靠我类方法执行关联:

class Post < Sequel::Modelmany_to_one :authorone_to_many :commentsone_to_one :first_comment,SEO靠我 :class=>:Comment, :order=>:idmany_to_many :tagsone_through_one :first_tag, :class=>:Tag, :order=>:nSEO靠我ame, :right_key=>:tag_id end

many_to_one和one_to_one为每个模型对象创建一个getter和setter方法:

post = Post.creSEO靠我ate(:name => hi!) post.author = Author[:name => Sharon] post.author

one_to_many和many_SEO靠我to_many方法创建一个getter方法,一个添加对象到该关联关系的方法,一个从该关联关系删除对象的方法,一个从该关联关系中删除所有关联对象的方法:

post = Post.create(:name SEO靠我=> hi!) post.commentscomment = Comment.create(:text=>hi) post.add_comment(comment) SEO靠我 post.remove_comment(comment) post.remove_all_commentstag = Tag.create(:tag=>interestiSEO靠我ng) post.add_tag(tag) post.remove_tag(tag) post.remove_all_tags

注意,remove_和reSEO靠我move_all_方法并不从数据库中删除数据,它们只是从接收者解除关联对象。

所有的关联有一个以dataset结尾的方法,可以用于进一步过滤、排序或者是该返回的对象:# Delete all of thSEO靠我is posts comments from the database post.comments_dataset.destroy# Return all tags related tSEO靠我o this post with no subscribers, ordered by the tags name post.tags_dataset.where(:subscribeSEO靠我rs=>0).order(:name).all

预加载

Associations can be eagerly loaded via eager and the :eager association opSEO靠我tion. Eager loading is used when loading a group of objects. It loads all associated objects for allSEO靠我 of the current objects in one query, instead of using a separate query to get the associated objectSEO靠我s for each current object. Eager loading requires that you retrieve all model objects at once via alSEO靠我l (instead of individually by each). Eager loading can be cascaded, loading associations associated SEO靠我objects.

class Person < Sequel::Modelone_to_many :posts, :eager=>[:tags] endclass Post < SequSEO靠我el::Modelmany_to_one :personone_to_many :repliesmany_to_many :tags endclass Tag < Sequel::MoSEO靠我delmany_to_many :postsmany_to_many :replies endclass Reply < Sequel::Modelmany_to_one :persoSEO靠我nmany_to_one :postmany_to_many :tags end# Eager loading via .eager Post.eager(:persoSEO靠我n).all# eager is a dataset method, so it works with filters/orders/limits/etc. Post.where{toSEO靠我pic > M}.order(:date).limit(5).eager(:person).allperson = Person.first # Eager loading via :SEO靠我eager (will eagerly load the tags for this persons posts) person.posts# These are equivalentSEO靠我 Post.eager(:person, :tags).all Post.eager(:person).eager(:tags).all# Cascading via SEO靠我.eager Tag.eager(:posts=>:replies).all# Will also grab all associated posts tags (because ofSEO靠我 :eager) Reply.eager(:person=>:posts).all# No depth limit (other than memory/stack), and wilSEO靠我l also grab posts tags # Loads all people, their posts, their posts tags, replies to those pSEO靠我osts, # the person for each reply, the tag for each reply, and all posts and # repliSEO靠我es that have that tag. Uses a total of 8 queries. Person.eager(:posts=>{:replies=>[:person, SEO靠我{:tags=>[:posts, :replies]}]}).all

In addition to using eager, you can also use eager_graph, which wiSEO靠我ll use a single query to get the object and all associated objects. This may be necessary if you wanSEO靠我t to filter or order the result set based on columns in associated tables. It works with cascading aSEO靠我s well, the API is very similar. Note that using eager_graph to eagerly load multiple *_to_many assoSEO靠我ciations will cause the result set to be a cartesian product, so you should be very careful with youSEO靠我r filters when using it in that case.

You can dynamically customize the eagerly loaded dataset by usiSEO靠我ng using a proc. This proc is passed the dataset used for eager loading, and should return a modifieSEO靠我d copy of that dataset:

# Eagerly load only replies containing foo Post.eager(:replies=>proc{SEO靠我|ds| ds.where(Sequel.like(text, %foo%))}).all

This also works when using eager_graph, in which case tSEO靠我he proc is called with dataset to graph into the current dataset:

Post.eager_graph(:replies=>proc{|dsSEO靠我| ds.where(Sequel.like(text, %foo%))}).all

You can dynamically customize eager loads for both eager aSEO靠我nd eager_graph while also cascading, by making the value a single entry hash with the proc as a key,SEO靠我 and the cascaded associations as the value:

# Eagerly load only replies containing foo, and the persSEO靠我on and tags for those replies Post.eager(:replies=>{proc{|ds| ds.where(Sequel.like(text, %foSEO靠我o%))}=>[:person, :tags]}).all

Joining with Associations

You can use the association_join method to addSEO靠我 a join to the models dataset based on the assocation:

Post.association_join(:author) # SELECSEO靠我T * FROM posts # INNER JOIN authors AS author ON (author.id = posts.author_id)

This comes witSEO靠我h variants for different join types:

Post.association_left_join(:replies) # SELECT * FROM posSEO靠我ts # LEFT JOIN replies ON (replies.post_id = posts.id)

Similar to the eager loading methods, SEO靠我you can use multiple associations and nested associations:

Post.association_join(:author, :replies=>:SEO靠我person).all # SELECT * FROM posts # INNER JOIN authors AS author ON (author.id = posSEO靠我ts.author_id) # INNER JOIN replies ON (replies.post_id = posts.id) # INNER JOIN peopSEO靠我le AS person ON (person.id = replies.person_id)

Extending the underlying dataset

The recommended way tSEO靠我o implement table-wide logic by defining methods on the dataset using dataset_module:

class Post < SeSEO靠我quel::Modeldataset_module dodef posts_with_few_commentswhere{num_comments < 30}enddef clean_posts_wiSEO靠我th_few_commentsposts_with_few_comments.deleteendend end

This allows you to have access to youSEO靠我r model API from filtered datasets as well:

Post.where(:category => ruby).clean_posts_with_few_commenSEO靠我ts

Sequel models also provide a subset class method that creates a dataset method with a simple filteSEO靠我r:

class Post < Sequel::Modelsubset(:posts_with_few_comments){num_comments < 30}subset :invisible, SeSEO靠我quel.~(:visible) end

Model Validations

You can define a validate method for your model, which SEO靠我save will check before attempting to save the model in the database. If an attribute of the model isSEO靠我nt valid, you should add an error message for that attribute to the model objects errors. If an objeSEO靠我ct has any errors added by the validate method, save will raise an error or return false depending oSEO靠我n how it is configured (the raise_on_save_failure flag).

class Post < Sequel::Modeldef validatesupereSEO靠我rrors.add(:name, "cant be empty") if name.empty?errors.add(:written_on, "should be in the past") if SEO靠我written_on >= Time.nowend end

转载于:https://www.cnblogs.com/cuimiemie/p/6442650.html

“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2