我正在开发一个RoR应用程序,Firebird及其SQL引擎,但我不明白为什么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)
);
以下是创建此表的迁移:(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
这是我的模型:( 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
没有定义任何视图或测试或帮助器!
如果我这样做在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
正如您所看到的,AR似乎正在尝试获取我的模型/表的默认值,在这种情况下,这是不需要的,因为它要查询数据库3次,而且它应该只是在做插入,并让SQL引擎处理其余的事情。 我如何防止这种情况发生?
有没有办法阻止AR获取列的默认值?
另一个问题,在GlobalSetting
模型的新方法中,我只使用列sKey:
和sValue:
,为什么活动记录会将所有其他列放入插入?
答案 0 :(得分:0)
AFAIK:new只创建一个模型对象,它接受一个哈希作为一个参数,其中键是你的表属性。它此时不会查询数据库。一旦调用save方法,它首先调用有效?检查对象是否通过了已定义的验证的方法。除了您在此处定义的唯一性验证外,它独立于数据库模式。唯一性验证查询数据库以检查此类值是否已存在。一旦您的对象通过了所有验证,它就会调用查询将数据插入到您的数据库中。如果数据违反了数据库级别的某些条件,则会引发异常。因此,当查询在数据库级别运行时,您无法从rails控制它。如果数据库中有默认值,则会分配它们。绕过它们的唯一方法是将一些其他值显式传递给相应的属性。 并且根据t.timestamps的行为,是的,每当您在创建新记录时修改该记录和created_at列时,rails将自动更新updated_at列。