如何防止Ruby on Rails Active记录从数据库获取默认模型值?

Cra*_*ted 5 ruby firebird ruby-on-rails rails-activerecord

我正在使用Firebird及其SQL引擎开发RoR应用程序,但我不明白为什么ActiveRecord(AR)不断查询数据库的默认值!

这是表DDL:

CREATE TABLE GLOBAL_SETTINGS
(
  SKEY varchar(64) NOT NULL,
  SVALUE varchar(256) NOT NULL,
  OBS blob sub_type 1,
  IS_SYSTEM "BOOLEAN" DEFAULT 1 NOT NULL,
  CREATED_AT timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
  UPDATED_AT timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
  CONSTRAINT PK_GLOBAL_SETTINGS_SKEY PRIMARY KEY (SKEY)
);
Run Code Online (Sandbox Code Playgroud)

这是创建此表的迁移:(create_global_settings.rb

class CreateGlobalSettings < ActiveRecord::Migration
  def up
    create_table :global_settings, :id => false do |t|
      t.string :skey, :null => false, :limit => 64
      t.string :svalue, :null  => false, :limit => 256
      t.text :obs
      t.boolean :is_system, :null  => false, :default => true
      t.timestamps :null  => false
    end

    # defaults on timestamp columns
    execute("alter table GLOBAL_SETTINGS alter column CREATED_AT set default     CURRENT_TIMESTAMP;")
    execute("alter table GLOBAL_SETTINGS alter column UPDATED_AT set default     CURRENT_TIMESTAMP;")    

    # our custom PK naming
    execute("alter table GLOBAL_SETTINGS add constraint PK_GLOBAL_SETTINGS_SKEY primary     key (SKEY)")    
  end

  def down
    drop_table :global_settings
  end
end
Run Code Online (Sandbox Code Playgroud)

这是我的模型:(global_Settings.rb

class GlobalSettings < ActiveRecord::Base
  #model validations!
  validates :skey, presence: true
  validates :skey, uniqueness: { case_sensitive: false, message: 'Global setting key     allready exists!'}

  validates :svalue, presence: true        
end
Run Code Online (Sandbox Code Playgroud)

没有定义视图,测试或帮助器!

在Rails控制台中,如果我这样做:

gs = GlobalSettings.new(skey: 'testKey', svalue: 'testValue')
D, [2014-11-21T13:11:18.547669 #7215] DEBUG -- :    (192.2ms)  SELECT CAST(1 AS SMALLINT)   FROM RDB$DATABASE
D, [2014-11-21T13:11:18.564272 #7215] DEBUG -- :    (16.3ms)  SELECT CAST(CURRENT_TIMESTAMP   AS TIMESTAMP) FROM RDB$DATABASE
D, [2014-11-21T13:11:18.580900 #7215] DEBUG -- :    (16.4ms)  SELECT CAST(CURRENT_TIMESTAMP AS TIMESTAMP) FROM RDB$DATABASE
#<GlobalSettings skey: "testKey", svalue: "testValue", obs: nil, is_system: true,   created_at: nil, updated_at: nil>
gs.save
D, [2014-11-21T13:11:24.403986 #7215] DEBUG -- :   GlobalSettings Exists (13.2ms)  SELECT    1 AS one FROM "GLOBAL_SETTINGS"  WHERE LOWER("GLOBAL_SETTINGS"."SKEY") = LOWER(?) ROWS 1,   testKey
D, [2014-11-21T13:11:24.543674 #7215] DEBUG -- :   SQL (89.4ms)  INSERT INTO   "GLOBAL_SETTINGS" ("CREATED_AT", "SKEY", "SVALUE", "UPDATED_AT") VALUES (?, ?, ?, ?), 2014-  11-21 13:11:24, testKey, testValue, 2014-11-21 13:11:24
true
Run Code Online (Sandbox Code Playgroud)

如您所见,AR似乎正在尝试获取我的模型/表的默认值,在这种情况下,这是不需要的,因为它要查询数据库3次,并且只应执行插入操作并让SQL引擎负责其余的工作。我如何防止这种情况发生?

有什么方法可以防止AR获取列的默认值吗?

还有一个问题,在GlobalSetting模型的新方法中,我仅使用列sKey:sValue:,为什么活动记录将所有其他列放入插入中?

udi*_*tal 0

AFAIK: new 仅创建一个模型对象,该对象接受哈希作为参数,其中键是表属性。此时它不会查询数据库。一旦调用 save 方法,它首先调用 valid? 方法来检查您的对象是否通过您定义的验证。除了您在此处定义的唯一性验证之外,它独​​立于数据库模式。唯一性验证查询数据库以检查这样的值是否已存在。一旦您的对象通过了所有验证,它就会调用查询将数据插入到数据库中。如果数据违反数据库级别的某些条件,则会引发异常。因此,当查询在数据库级别运行时,您无法从 Rails 控制它。如果数据库中有默认值,则会分配它们。绕过它们的唯一方法是显式地将一些其他值传递给相应的属性。根据 t.timestamps 的行为,是的,每次您修改该记录时,rails 都会自动更新 Updated_at 列,并在创建新记录时自动更新created_at 列。