简体   繁体   中英

How to prevent Ruby on Rails Active record from getting default model values from the database?

I'm developing a RoR app, with Firebird with its SQL engine but i cant understand why ActiveRecord (AR) keeps querying the database for default values!

Here is the tables 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)
);

Here is the migration that created this table: ( 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

Here is my model: ( 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

No views or tests or helper are defined!

In rails console if i do:

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

As you can see it seems that AR is trying to get the default values for my model/table, and in this case that is not needed because it's querying the database 3 times, and it should only be doing an insert, and letting the SQL engine take care of the rest. How do i prevent this kind of situation to happen?

Is there any way to prevent AR to fetch defaults for columns?

And another question, in the new method of the GlobalSetting model i am just using columns sKey: and sValue: , why is active record putting all others columns in the insert?

AFAIK: new only creates a model object which accepts a hash as a parameter in which keys are your table attributes. It does not query database at this point of time. Once you call the save method, it first calls valid? method to check if your object passes the validations you have defined. It is independent of database schema except for the uniqueness validation you have defined here. Uniqueness validation queries the database to check if such a value already exists. Once your object passes all the validations, it then calls the query to insert the data into your database. If the data violates some conditions at database level, exception is raised. So when the query is run at the database level, you have no control over it from rails. If there are default values in the database, they'll be assigned. The only way to bypass them is to explicitly passing some other values to the corresponding attribute. And as per the behaviour of t.timestamps, yes, rails will automatically update the updated_at column each time you modify that record and created_at column when you create a new record.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM