王筝的博客
ruby学习

 

 

 

  def create
    @subjection = @subject.subjections.new
    if params[:video_or_show_id].length == 20
      show = Show.where(:showid => params[:video_or_show_id]).try(:first)
      if show.present?
        @show = show
      else
        begin
          @show = Show.build_from_show_id(params[:video_or_show_id])
          @subjection.subjectable_type = "show"
          @subjection.subjectable_id = @show.id
          @subjection.title = @show.showname
          @subjection.sub_title = @show.showsubtitle
          @subjection.description = @show.showdesc
          @subjection.save
          if @show.save
            img_v = @subjection.pictures.new(:url => @show.show_vthumburl,
                                             :name => "img_v")
            img_v.save
            img_h = @subjection.pictures.new(:url => @show.show_thumburl,
                                             :name => "img_h")
            img_h.save
          end
        rescue ArgumentError, Youku::DS::Error => e
          @show = Show.new
          @show.errors.add(:base, e.message)
          redirect_to new_subject_subjection_path(@subject), :notice => "视频没有版权"
        end
      end
    else
      video = Video.where(:videoid => params[:video_or_show_id]).try(:first)
      if video.present?
        @video = video
      else
        begin
          @video = Video.build_from_video_id(params[:video_or_show_id])
          if @video.videoid.present?
            @subjection.subjectable_type = "video"
            @subjection.subjectable_id = @video.id
            @subjection.description = @video.desc
            @subjection.title = @video.title
            @subjection.save
            if @video.save
              img_h = @subjection.pictures.new(:url => @video.thumburl,
                                               :name => "img_h")
              img_h.save
            end
          end
        rescue ArgumentError, Youku::DS::Error => e
          @video = Video.new
          @subjection.errors.add(:base, e.message)
          render :error and return
        end
      end
    end

    if @subjection.save
      redirect_to subject_subjections_url(@subject), notice: '新建成功'
    else
      render :new
    end
  end

 

 

修改后

if persisted? # 如果是已经保存到数据库的 ActiveRecord 对象
  super # 则调用原始的 subjectable= 方法
只有在新建一个 subjection 时,调用 subjectable= 方法的时做一些特殊处理,
比如给 title, sub_title 和 description 赋值
def create
  @subjection = @subject.subjections.build
  id = params[:video_or_show_id]

  subjectable = if id.length == 20
                  find_or_create_show_from_show_id(id)
                else
                  find_or_create_video_from_video_id(id)
                end

  @subjection.subjectable = subjectable

  if @subjection.save
    redirect_to subject_subjections_url(@subject), notice: '新建成功'
  else
    render :error
  end
rescue ArgumentError, Youku::DS::Error => e
  @subjection.errors.add(:base, e.message)
  render :error
end

private
  def find_or_create_show_from_show_id(id)
    if show = Show.find_by_showid(id)
      show
    else
      show = Show.build_from_show_id(id)
      show.save
      show
    end
  end

  def find_or_create_video_from_video_id(id)
    if video = Video.find_by_videoid(id)
      video
    else
      video = Video.build_from_video_id(id)
      video.save
      video
    end
  end

 

 

def subjectable=(subjectable)
  if persisted?
    super
  else
    self.attributes = {
      subjectable_type: subjectable.class.name,
      subjectable_id: subjectable.id
    }

    case subjectable
    when Show
      self.attributes = {
        title: subjectable.showname,
        sub_title: subjectable.showsubtitle,
        description: subjectable.showdesc,
        pictures_attributes: [{ name: 'img_h', url: subjectable.show_thumburl },
                              { name: 'img_v', url: subjectable.show_vthumburl }]
      }
    when Video
      self.attributes = {
        title: subjectable.title,
        description: subjectable.desc,
        pictures_attributes: [{ name: 'img_h', url: subjectable.thumburl }]
      }
    else
      super  
    end
  end
end

 

 

原代码

  def get_type
    type_list = ""
    if categories.include?"movie"
      type_list += "电影,"
    end 
    if categories.include?"tv"
      type_list += "电视剧,"
    end 
    if categories.include?"comic"
      type_list += "动漫,"
    end 
    if categories.include?"entertainment"
      type_list += "综艺"
    end 
    type_list
  end

存储的数据格式为  categories: “[\”tv\”, \”entertainment\”]”,

修改为

  serialize :categories, Array
  def get_type
    categories_hash = {
      movie: '电影',
      tv: '电视剧',
      comic: '动漫',
      entertainment: '综艺'
    }
    type_list = categories.map { |category| categories_hash[category.to_sym] }.join(',')
  end

存储的数据格式为 categories: “—\n- tv\n- comic\n”, YAML 序列化后的样子,YAML 的数组相关文档,可看 YAML 的文档:http://yaml.org/

 

https://gist.github.com/stream7/1069589

 

:limit        Numeric Type    Column Size    Max value
1             tinyint           1 byte        127
2             smallint          2 bytes       32767
3             mediumint         3 byte        8388607
nil, 4, 11    int(11)           4 byte        2147483647
5..8          bigint            8 byte        9223372036854775807

 

关于sequence 字段limit: 2 是两个字节,16 位,2 的 15 次方是 32767

class CreateTableSubjections < ActiveRecord::Migration[5.0]
  def change
    create_table :table_subjections do |t| 
      t.belongs_to :subject, index: true
      t.belongs_to :video, index: true
      t.string :title, limit: 40
      t.string :sub_title, limit: 40
      t.string :description, limit: 500
      t.integer :status, limit: 1
      t.integer :sequence, limit: 2

      t.timestamps
    end 
  end 
end

 

对于多态关联的表

class CreateSubjections < ActiveRecord::Migration[5.0]
  def change
    create_table :subjections do |t| 
      t.belongs_to :subject, index: true
      t.string :title, limit: 40
      t.string :sub_title, limit: 40
      t.string :description, limit: 500 
      t.string :subjectable_type, limit: 20
      t.integer :subjectable_id
      t.integer :status, limit: 1
      t.integer :sequence, limit: 2

      t.timestamps
    end 

    add_index :subjections, [:subjectable_type, :subjectable_id]
  end 
end

t.integer :subjectable_id 不需要设置limit,因为这个是用来做外键的,存储的是数据库的自增主键

 

http://api.rubyonrails.org/classes/ActiveRecord/Enum.html

 

新的项目中有一个字段是展示类型,可以用下拉框去做,用string存储具体的类型字段。

尝试了一下把展示类型修改为integer,用Rails enum枚举来做。

使用枚举(整型)来存储类似于下拉框选择的这类的值, 比起直接存储类型的字符串,能减少表中存储字段的大小。

 

建表语句如下

class CreateSubjects < ActiveRecord::Migration[5.0]
  def change
    create_table :subjects do |t| 
      t.string :title, limit: 40
      t.string :sub_title, limit: 40
      t.string :categories, limit: 30
      t.string :description, limit: 500 
      t.integer :status, limit: 1
      t.integer :type, limit: 1
      t.integer :use_default_image, limit: 1
      t.integer :has_ranking_list, limit: 1

      t.timestamps
    end 
  end 
end

model中定义了enum的字段值。

class Subject < ApplicationRecord

  TYPES = [ :'变化标题描述', :'固定标题描述', :'播放器专题', :'无文案专题' ]
  enum type: TYPES

  self.inheritance_column = '_disable'
end

在console里修改当前type的值,rails会自动显示成对应的字符串

[6] pry(main)> Subject.last.update_attribute :type, 2
  Subject Load (0.2ms)  SELECT  `subjects`.* FROM `subjects` ORDER BY `subjects`.`id` DESC LIMIT 1
   (0.2ms)  BEGIN
  SQL (0.4ms)  UPDATE `subjects` SET `type` = 2, `updated_at` = '2016-09-13 06:06:49' WHERE `subjects`.`id` = 3
  SQL (14.3ms)  INSERT INTO `versions` (`item_type`, `item_id`, `event`, `object`, `created_at`, `object_changes`) VALUES ('Subject', 3, 'update', '{\"id\":3,\"title\":\"谢谢\",\"sub_title\":\"1\",\"categories\":\"1\",\"description\":\"1\",\"status\":null,\"type\":1,\"use_default_image\":1,\"has_ranking_list\":1,\"created_at\":\"2016-09-13T04:35:23.000Z\",\"updated_at\":\"2016-09-13T04:35:23.000Z\"}', '2016-09-13 06:06:49', '{\"type\":[1,2],\"updated_at\":[\"2016-09-13T04:35:23.000Z\",\"2016-09-13T06:06:49.000Z\"]}')
   (54.0ms)  COMMIT
=> true
[7] pry(main)> Subject.last
  Subject Load (0.4ms)  SELECT  `subjects`.* FROM `subjects` ORDER BY `subjects`.`id` DESC LIMIT 1
=> #<Subject:0x00558622d04d98
 id: 3,
 title: "谢谢",
 sub_title: "1",
 categories: "1",
 description: "1",
 status: nil,
 type: "播放器专题",
 use_default_image: 1,
 has_ranking_list: 1,
 created_at: Tue, 13 Sep 2016 12:35:23 CST +08:00,
 updated_at: Tue, 13 Sep 2016 14:06:49 CST +08:00>

而直接查询mysql会发现,这个字段里存的是2.

$ bundle exec rails db -p
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 72
Server version: 5.5.47-0ubuntu0.14.04.1 (Ubuntu)

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select * from subjects;
+----+--------+-----------+------------+-------------+--------+------+-------------------+------------------+---------------------+---------------------+
| id | title  | sub_title | categories | description | status | type | use_default_image | has_ranking_list | created_at          | updated_at          |
+----+--------+-----------+------------+-------------+--------+------+-------------------+------------------+---------------------+---------------------+
|  3 | 谢谢   | 1         | 1          | 1           |   NULL |    2 |                 1 |                1 | 2016-09-13 04:35:23 | 2016-09-13 06:06:49 |
+----+--------+-----------+------------+-------------+--------+------+-------------------+------------------+---------------------+---------------------+
1 row in set (0.00 sec)

在_form中的代码如下

  <div class="form-group">
    <%= f.label :type, class: 'col-sm-2 control-label' %>

    <div class="col-sm-4">
      <%= f.select :type, Subject::TYPES %>
    </div>
  </div>

在index和show页面直接读取数据就ok了

<%= subject.type %>

 

 

type 字段在 Rails 中默认使用来做 STI(single-table inheritance),
当 type 作为普通字段来使用时,可以把SIT的列设置成别的列名(比如不存在的某个列)。

文档在这里

http://api.rubyonrails.org/classes/ActiveRecord/ModelSchema/ClassMethods.html#method-i-inheritance_column,
使用下面的方法就是设置 STI 使用的列名,默认是‘type',既然不想使用 STI了,可以设置一个不太可能和以后的列名冲突的名字,比如使用 ’_disable‘。

比如可以在 Model 中设置为
self.inheritance_column = '_disable'

Defines the name of the table column which will store the class name on single-table inheritance situations.

The default inheritance column name is type, which means it’s a reserved word inside Active Record. To be able to use single-table inheritance with another column name, or to use the column type in your own model for something else, you can set inheritance_column:

self.inheritance_column = 'zoink'

关于single table inheritance, 可以查看下面的文档
http://api.rubyonrails.org/classes/ActiveRecord/Inheritance.html




以下是建表语句
class CreateSubjects < ActiveRecord::Migration[5.0]
  def change
    create_table :subjects do |t| 
      t.string :title, limit: 40
      t.string :sub_title, limit: 40
      t.string :categories, limit: 30
      t.string :description, limit: 500 
      t.integer :status, limit: 1
      t.integer :type, limit: 1
      t.integer :use_default_image, limit: 1
      t.integer :has_ranking_list, limit: 1

      t.timestamps
    end
  end 
end

 

 

使用 callback 确保创建,更新和删除 Picture 时,touch 关联的 imageable,使得其缓存能正确过期

这个update的方法用来把update时间强制更新成当前时间

http://guides.rubyonrails.org/association_basics.html

4.1.2.9 :touch

If you set the :touch option to true, then the updated_at or updated_on timestamp on the associated object will be set to the current time whenever this object is saved or destroyed:

class Book < ApplicationRecord
  belongs_to :author, touch: true
end
 
class Author < ApplicationRecord
  has_many :books
end

由于在多态关联中直接写touch :true没有起作用,写了另一个方法

class Picture < ApplicationRecord
  belongs_to :imageable, polymorphic: true                             
                                                                       
  validates_uniqueness_of :name, scope: [:imageable_id, :imageable_type]
                                                                       
  after_save :touch_imagable
  after_destroy :touch_imagable
                                                                       
  def touch_imagable
    imageable.touch                                                    
  end                                                                  
end  

 

 

https://github.com/rails/jbuilder  的set!方法重构接口,

因为grape没法使用 jBuilder 的缓存,所以直接用 Rails 写 API

(1)多个图片

images: {
  poster: {
    url: "http://r4.ykimg.com/0510000057CD17166714C04FDC0628CE",
    md5: "ee63b0a11cb1e39331d5ce11d38fceec"
},
  right_top_corner: {
    url: "http://r1.ykimg.com/0510000057CEA19C6714C063660BEB44",
    md5: "e50d520de494538d4633086d46845a81"
  }
},

原来的方法为

 json.images do
    component.pictures.each do |p|
      if p.name == 'poster'
        json.poster do
          json.url "http://r#{rand(4) + 1}.xxx.com/#{p.url}"
          json.md5 p.md5
        end
      end
      if p.name == 'icon'
        json.icon do
          json.url "http://r#{rand(4) + 1}.xxx.com/#{p.url}"
          json.md5 p.md5
        end
      end
      if p.name == 'background'
        json.background do
          json.url "http://r#{rand(4) + 1}.xxx.com/#{p.url}"
          json.md5 p.md5
        end
      end
  end 
end

精简后为

  json.images do
    component.pictures.each do |p| 
      json.set! p.name do
        json.set! :url, "http://r#{rand(4) + 1}.ykimg.com/#{p.url}"
        json.set! :md5, p.md5
      end 
    end 
  end 

(2)hints 是一个 hash,遍历 Hash 的文档 http://ruby-doc.org/core-2.3.1/Hash.html#method-i-each

hint: {
  left: "left",
  right: "111"
},

精简前

  json.hint do
    if component.hints.key?("left")
      json.left component.hints["left"]
    end 
    if component.hints.key?("center")
      json.center component.hints["center"]
    end 
    if component.hints.key?("right")
      json.right component.hints["right"]
    end 
  end

精简后

  json.hint do
    component.hints.each do |key,value|
      json.set! key, value
    end
  end

 

(0)之所以有第0步,是因为第一次倒入失败,所以从删除上次倒入的数据开始~

开始删除数据。

启动Intelli J,点击右键删除上次的导入的项目

 

把配置拷贝到.m2文件夹下,并且删除上次下载的一些依赖包

$ cd ~/.m2
$ cp ~/Downloads/settings.xml .
$ cd repository/
$ rm -rf *

 

回到程序所在的目录,删除上次导入生成的 后缀名为.iml的文件

rm -rf play-service.iml

 

停掉刚才的java进程

$ ps -ef |grep java

 

 

(1)打开intelli J,点击iimport project,选择相应的工程文件目录。

 

(2)import project from external model, 之后一路next下去,别忘了到填写project name的时候修改一下名字

 

(3)配置启动选项:RUN -> Edit Configuration, 点击加号,添加application

(4)点击主面板上的运行按钮开始运行,可以在网页看到效果localhost:8080

 

 

(1)Download IntelliJ IDEA

https://www.jetbrains.com/idea/download/

 

(2)找了个激活码

http://www.oschina.net/code/snippet_2303434_57174

 

43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiIiwiYXNzaWduZWVFbWFpbCI6IiIsImxpY2Vuc2VSZXN0cmljdGlvbiI6IkZvciBlZHVjYXRpb25hbCB1c2Ugb25seSIsImNoZWNrQ29uY3VycmVudFVzZSI6ZmFsc2UsInByb2R1Y3RzIjpbeyJjb2RlIjoiSUkiLCJwYWlkVXBUbyI6IjIwMTctMDItMjUifSx7ImNvZGUiOiJBQyIsInBhaWRVcFRvIjoiMjAxNy0wMi0yNSJ9LHsiY29kZSI6IkRQTiIsInBhaWRVcFRvIjoiMjAxNy0wMi0yNSJ9LHsiY29kZSI6IlBTIiwicGFpZFVwVG8iOiIyMDE3LTAyLTI1In0seyJjb2RlIjoiRE0iLCJwYWlkVXBUbyI6IjIwMTctMDItMjUifSx7ImNvZGUiOiJDTCIsInBhaWRVcFRvIjoiMjAxNy0wMi0yNSJ9LHsiY29kZSI6IlJTMCIsInBhaWRVcFRvIjoiMjAxNy0wMi0yNSJ9LHsiY29kZSI6IlJDIiwicGFpZFVwVG8iOiIyMDE3LTAyLTI1In0seyJjb2RlIjoiUEMiLCJwYWlkVXBUbyI6IjIwMTctMDItMjUifSx7ImNvZGUiOiJSTSIsInBhaWRVcFRvIjoiMjAxNy0wMi0yNSJ9LHsiY29kZSI6IldTIiwicGFpZFVwVG8iOiIyMDE3LTAyLTI1In0seyJjb2RlIjoiREIiLCJwYWlkVXBUbyI6IjIwMTctMDItMjUifSx7ImNvZGUiOiJEQyIsInBhaWRVcFRvIjoiMjAxNy0wMi0yNSJ9XSwiaGFzaCI6IjMzOTgyOTkvMCIsImdyYWNlUGVyaW9kRGF5cyI6MCwiYXV0b1Byb2xvbmdhdGVkIjpmYWxzZSwiaXNBdXRvUHJvbG9uZ2F0ZWQiOmZhbHNlfQ==-keaxIkRgXPKE4BR/ZTs7s7UkP92LBxRe57HvWamu1EHVXTcV1B4f/KNQIrpOpN6dgpjig5eMVMPmo7yMPl+bmwQ8pTZaCGFuLqCHD1ngo6ywHKIQy0nR249sAUVaCl2wGJwaO4JeOh1opUx8chzSBVRZBMz0/MGyygi7duYAff9JQqfH3p/BhDTNM8eKl6z5tnneZ8ZG5bG1XvqFTqWk4FhGsEWdK7B+He44hPjBxKQl2gmZAodb6g9YxfTHhVRKQY5hQ7KPXNvh3ikerHkoaL5apgsVBZJOTDE2KdYTnGLmqxghFx6L0ofqKI6hMr48ergMyflDk6wLNGWJvYHLWw==-MIIEPjCCAiagAwIBAgIBBTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTE1MTEwMjA4MjE0OFoXDTE4MTEwMTA4MjE0OFowETEPMA0GA1UEAwwGcHJvZDN5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxcQkq+zdxlR2mmRYBPzGbUNdMN6OaXiXzxIWtMEkrJMO/5oUfQJbLLuMSMK0QHFmaI37WShyxZcfRCidwXjot4zmNBKnlyHodDij/78TmVqFl8nOeD5+07B8VEaIu7c3E1N+e1doC6wht4I4+IEmtsPAdoaj5WCQVQbrI8KeT8M9VcBIWX7fD0fhexfg3ZRt0xqwMcXGNp3DdJHiO0rCdU+Itv7EmtnSVq9jBG1usMSFvMowR25mju2JcPFp1+I4ZI+FqgR8gyG8oiNDyNEoAbsR3lOpI7grUYSvkB/xVy/VoklPCK2h0f0GJxFjnye8NT1PAywoyl7RmiAVRE/EKwIDAQABo4GZMIGWMAkGA1UdEwQCMAAwHQYDVR0OBBYEFGEpG9oZGcfLMGNBkY7SgHiMGgTcMEgGA1UdIwRBMD+AFKOetkhnQhI2Qb1t4Lm0oFKLl/GzoRykGjAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBggkA0myxg7KDeeEwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4ICAQC9WZuYgQedSuOc5TOUSrRigMw4/+wuC5EtZBfvdl4HT/8vzMW/oUlIP4YCvA0XKyBaCJ2iX+ZCDKoPfiYXiaSiH+HxAPV6J79vvouxKrWg2XV6ShFtPLP+0gPdGq3x9R3+kJbmAm8w+FOdlWqAfJrLvpzMGNeDU14YGXiZ9bVzmIQbwrBA+c/F4tlK/DV07dsNExihqFoibnqDiVNTGombaU2dDup2gwKdL81ua8EIcGNExHe82kjF4zwfadHk3bQVvbfdAwxcDy4xBjs3L4raPLU3yenSzr/OEur1+jfOxnQSmEcMXKXgrAQ9U55gwjcOFKrgOxEdek/Sk1VfOjvS+nuM4eyEruFMfaZHzoQiuw4IqgGc45ohFH0UUyjYcuFxxDSU9lMCv8qdHKm+wnPRb0l9l5vXsCBDuhAGYD6ss+Ga+aDY6f/qXZuUCEUOH3QUNbbCUlviSz6+GiRnt1kA9N2Qachl+2yBfaqUqr8h7Z2gsx5LcIf5kYNsqJ0GavXTVyWh7PYiKX4bs354ZQLUwwa/cG++2+wNWP+HtBhVxMRNTdVhSm38AknZlD+PTAsWGu9GyLmhti2EnVwGybSD2Dxmhxk3IPCkhKAK+pl0eWYGZWG3tJ9mZ7SowcXLWDFAk0lRJnKGFMTggrWjV8GYpw5bq23VmIqqDLgkNzuoog==

 

 

(3)select project SDK, 选择JDK

 

(4)java select  directory is not a valid home for jdk

因为还没装jdk,下载地址为

http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

我选择的是mac版本的

(5) 下载tomcat, 我下载的是后缀名为tar.gz的这个

http://tomcat.apache.org/download-80.cgi#8.5.5

 

(6)把tomcat移动到/Library里并修改权限、启动

 

$ cd /Library/
$ sudo mv ~/Downloads/apache-tomcat-8.5.5 .
$ sudo mv apache-tomcat-8.5.5/   Tomcat/
$ sudo chmod 755 /Library/Tomcat/bin/*.sh
$ cd Tomcat/
$ cd bin
$  ./startup.sh 

查看日志

$ cd ../logs/
$ tail -500 catalina.out

这时候可以查看下localhost:8080看下效果

 

 

最近在处理一个小功能,每个元素可以有多个图片,每个图片的name表示了它是背景图还是海报图,

需要对每个元素的图片name做一个唯一性验证,一个元素不能添加两个海报图,

使用的是validates_uniqueness_of

 

http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_uniqueness_of

Validates whether the value of the specified attributes are unique across the system. Useful for making sure that only one user can be named “davidhh”.

class Person < ActiveRecord::Base
  validates_uniqueness_of :user_name
end

It can also validate whether the value of the specified attributes are unique based on a :scope parameter:

class Person < ActiveRecord::Base
  validates_uniqueness_of :user_name, scope: :account_id
end

Or even multiple scope parameters. For example, making sure that a teacher can only be on the schedule once per semester for a particular class.

class TeacherSchedule < ActiveRecord::Base
  validates_uniqueness_of :teacher_id, scope: [:semester_id, :class_id]
end

It is also possible to limit the uniqueness constraint to a set of records matching certain conditions. In this example archived articles are not being taken into consideration when validating uniqueness of the title attribute:

class Article < ActiveRecord::Base
  validates_uniqueness_of :title, conditions: -> { where.not(status: 'archived') }
end

When the record is created, a check is performed to make sure that no record exists in the database with the given value for the specified attribute (that maps to a column). When the record is updated, the same check is made but disregarding the record itself.

Configuration options:

  • :message – Specifies a custom error message (default is: “has already been taken”).
  • :scope – One or more columns by which to limit the scope of the uniqueness constraint.
  • :conditions – Specify the conditions to be included as a WHERE SQL fragment to limit the uniqueness constraint lookup (e.g. conditions: -> { where(status: 'active') }).
  • :case_sensitive – Looks for an exact match. Ignored by non-text columns (true by default).
  • :allow_nil – If set to true, skips this validation if the attribute is nil (default is false).
  • :allow_blank – If set to true, skips this validation if the attribute is blank (default is false).
  • :if – Specifies a method, proc or string to call to determine if the validation should occur (e.g. if: :allow_validation, or if: Proc.new { |user| user.signup_step > 2 }). The method, proc or string should return or evaluate to a true or false value.
  • :unless – Specifies a method, proc or string to call to determine if the validation should not occur (e.g. unless: :skip_validation, or unless: Proc.new { |user| user.signup_step <= 2 }). The method, proc or string should return or evaluate to a true or false value.

 

class Picture < ApplicationRecord
  belongs_to :imageable, polymorphic: true

  validates_uniqueness_of :name, scope: [:imageable_id, :imageable_type]
end