如何在ruby on rails模型中使用Active Record Callbacks为列添加动态值?

问题描述 投票:1回答:2

我有一个模型 Document 在我的rails应用程序中。它的列数是 namekey.

在我的控制器 create 动作,我从前台获取文档名称,并动态地设置一个值作为 keysecurerandom.

我对这个案例的实现是。

文件模型

class Document < ApplicationRecord
    belongs_to :user
    validates :key, presence: true, uniqueness: true
end

文件管理员

class DocumentsController < ApplicationController
    def create
        current_user.documents.create(create_document_params)
        redirect_to '/'
    end

    private
    def create_document_params
        params.require(:document).permit(:name).merge(key: "#{SecureRandom.hex(6)}#{Time.now.to_i}")
    end
end

这种方法的问题是,动态键逻辑在控制器中,我认为它应该是Document模型的一部分。

为此,我尝试使用 Active Record Callbacks 里面 Document 模型与 before_create.我把securerandom密钥逻辑移到了Document模型中,就像这样。

class Document < ApplicationRecord
    belongs_to :user
    validates :key, uniqueness: true


    before_create do
        self.key = "#{SecureRandom.hex(6)}#{Time.now.to_i}"
    end
end

但现在我的问题是,每当我调用 createnew key 值总是相同的。但它应该在每次 create 呼叫。

在rails控制台

u = User.find_by(user_name: "random")
u.documents.new(name: 'Yolo 1') // key: "89c9013c191a1589398865"
u.documents.new(name: 'Yolo 2') // key: "89c9013c191a1589398865"

我做错了什么?

编辑:添加了Gemfile.NET文件。

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.3'

gem 'rails', '~> 6.0.3'
gem 'sqlite3', '~> 1.4'
gem 'puma', '~> 4.1'
gem 'sass-rails', '>= 6'
gem 'webpacker', '~> 4.0'
gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.7'
gem 'bcrypt', '~> 3.1.7'
gem 'bootsnap', '>= 1.4.2', require: false

group :development, :test do
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
gem 'web-console', '>= 3.3.0'
gem 'listen', '~> 3.2'
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
end

group :test do
gem 'capybara', '>= 2.15'
gem 'selenium-webdriver'
gem 'webdrivers'
end

gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

gem "rspec-rails", "~> 4.0"

DB迁移。

class CreateDocuments < ActiveRecord::Migration[6.0]
    def change
        create_table :documents do |t|
            t.string :name,
            t.string :key, index: {unique: true}, null: false
            t.references :user
            t.timestamps
        end
    end
end
ruby-on-rails activerecord rails-activerecord ruby-on-rails-6 rails-models
2个回答
0
投票

我在我的应用程序中复制了你的场景,并且可以重现你的错误.这种行为是关于验证方法。我删除了该方法,它的工作。

为了保留验证方法,我 找到这个其他答案

# frozen_string_literal: true

class Document < ApplicationRecord
  before_create :assing_key

  belongs_to :user

  validates :key, presence: true, uniqueness: true, allow_blank: true

  private

  def assing_key
    self.key = "#{SecureRandom.hex(6)}#{Time.now.to_i}"
  end
end

我加 allow_blank: true.

您可以测试只删除 presence 而不是添加 allow_blank 还。欣赏一下。


0
投票

我不知道你是如何能够创建一个文档的,因为你有验证的 presence: true 在...上 key. 你会得到错误 {:key=>["can't be blank"]} 创建文档时,用 doc = current_user.documents.create(name: 'some name')因为验证是在回调之前执行的。before_create. 你所需要做的就是删除 presence: true 因为你总是在创建新记录之前设置它。

© www.soinside.com 2019 - 2024. All rights reserved.