Skip to content

Instantly share code, notes, and snippets.

@fredrikhenne
Forked from jimeh/README.md
Created October 7, 2011 01:31
Show Gist options
  • Save fredrikhenne/1269222 to your computer and use it in GitHub Desktop.
Save fredrikhenne/1269222 to your computer and use it in GitHub Desktop.
A simple key/value store model for Rails using the database and memcache

Rails Setting model

This is a semi-quick key/value store I put together for a quick way to store temporary data related to what's in my database, in a reliable way. For example, I'm using it to keep track of where a hourly and a daily crontask that processes statistics left off, so it can resume only processing and summarizing new data on the next run.

Code quality most likely is not great, but it works. And I will update this gist as I update my project.

How It Works

The settings table has two columns, a key and a value column. The value column is serialized, so you can technically store almost anything in there. Memcache is also used as a caching layer to minimize database calls.

Example usage

# fetching a value
>> Setting.hello
=> nil

# setting a value, writes it to memcache, and saves or updates a database
# record is the form of {:key => "hello", :value => serialize(["world"])}
>> Setting.hello = ["world"]
=> ["hello"]

# fetching the value again, which will only read from memcache
>> Setting.hello
=> ["hello"]

# force fetch from database and update memcache
>> Setting.hello!
=> ["hello"]

# remove the hello key from memcache and the database
>> Setting.hello = nil
=> nil

# default memcache expire_in option is 6.hours, you can change it...
>> Setting.__cache_expires_in = 1.hour
=> 3600 seconds
class CreateSettings < ActiveRecord::Migration
def self.up
create_table :settings, :options => "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string :key
t.text :value
end
add_index :settings, :key, :unique => true
end
def self.down
drop_table :settings
end
end
class Setting < ActiveRecord::Base
serialize :value
class << self
attr_accessor :__cache
attr_accessor :__cache_expires_in
end
def self.method_missing(method, *args)
# init memcache if needed
@__cache = ActiveSupport::Cache::MemCacheStore.new if @__cache.nil?
@__cache_expires_in = 6.hours if @__cache_expires_in.nil?
method = method.to_s
# set mode
if method[-1,1] == "="
if args.size > 0
# key/value setup
method = method.chop
method = method.chop if method[-1,1] == "!"
value = {:value => args[0]}
@__cache.write(method, value, :expires_in => @__cache_expires_in)
setting = self.find(:first, :conditions => {:key => method})
if value[:value].nil?
setting.destroy if setting
@__cache.write(method, nil, :expires_in => 0.seconds)
else
setting = self.new if !setting
setting.key = method.to_s if setting.key.blank?
setting.value = value
if setting.save
return value[:value]
end
end
end
# get mode
else
# skip memcache?
if method[-1,1] == "!"
method = method.chop
skip_cache = true
end
if skip_cache.nil? && (result = @__cache.read(method.to_s))
return result[:value]
else
result = self.find(:first, :conditions => {:key => method})
if result
@__cache.write(method, result.value, :expires_in => @__cache_expires_in)
return result.value[:value]
end
end
end
return nil
end
end
@mm580486
Copy link

i using rails 5 and postgresql
i get this error after execute rails db:migrate
i want store and single record into project like setting but i dont want create a table for that
used by:
ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: syntax error at or near "ENGINE"
LINE 1: ...imary key, "key" character varying, "value" text) ENGINE=Inn...
^
: CREATE TABLE "confs" ("id" bigserial primary key, "key" character varying, "value" text) ENGINE=InnoDB DEFAULT CHARSET=utf8
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:75:in async_exec' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:75:in block (2 levels) in execute'
/usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/dependencies/interlock.rb:48:in block in permit_concurrent_loads' /usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/concurrency/share_lock.rb:187:in yield_shares'
/usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/dependencies/interlock.rb:47:in permit_concurrent_loads' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:74:in block in execute'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract_adapter.rb:579:in block (2 levels) in log' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract_adapter.rb:578:in block in log'
/usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/notifications/instrumenter.rb:23:in instrument' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract_adapter.rb:569:in log'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:73:in execute' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract/schema_statements.rb:311:in create_table'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:871:in block in method_missing' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:840:in block in say_with_time'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:840:in say_with_time' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:860:in method_missing'
/app/back/dorino/BE/db/migrate/20181231155726_create_confs.rb:3:in up' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:817:in exec_migration'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:798:in block (2 levels) in migrate' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:797:in block in migrate'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:416:in with_connection' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:796:in migrate'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:977:in migrate' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1292:in block in execute_migration_in_transaction'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1343:in block in ddl_transaction' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract/database_statements.rb:259:in block in transaction'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract/transaction.rb:239:in block in within_new_transaction' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract/transaction.rb:236:in within_new_transaction'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract/database_statements.rb:259:in transaction' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/transactions.rb:212:in transaction'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1343:in ddl_transaction' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1291:in execute_migration_in_transaction'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1263:in block in migrate_without_lock' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1262:in each'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1262:in migrate_without_lock' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1210:in block in migrate'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1363:in with_advisory_lock' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1210:in migrate'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1036:in up' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1011:in migrate'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/tasks/database_tasks.rb:172:in migrate' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/railties/databases.rake:60:in block (2 levels) in

'
/usr/local/bundle/gems/railties-5.2.2/lib/rails/commands/rake/rake_command.rb:23:in block in perform' /usr/local/bundle/gems/railties-5.2.2/lib/rails/commands/rake/rake_command.rb:20:in perform'
/usr/local/bundle/gems/railties-5.2.2/lib/rails/command.rb:48:in invoke' /usr/local/bundle/gems/railties-5.2.2/lib/rails/commands.rb:18:in '
/usr/local/bundle/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in require' /usr/local/bundle/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in block in require_with_bootsnap_lfi'
/usr/local/bundle/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/loaded_features_index.rb:65:in register' /usr/local/bundle/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:20:in require_with_bootsnap_lfi'
/usr/local/bundle/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in require' /usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:291:in block in require'
/usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:257:in load_dependency' /usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:291:in require'
/usr/local/bundle/gems/railties-5.2.2/lib/rails/app_loader.rb:59:in block in exec_app' /usr/local/bundle/gems/railties-5.2.2/lib/rails/app_loader.rb:48:in loop'
/usr/local/bundle/gems/railties-5.2.2/lib/rails/app_loader.rb:48:in exec_app' /usr/local/bundle/gems/railties-5.2.2/lib/rails/cli.rb:7:in <top (required)>'
/usr/local/bundle/gems/railties-5.2.2/exe/rails:10:in require' /usr/local/bundle/gems/railties-5.2.2/exe/rails:10:in <top (required)>'
bin/rails:29:in load' bin/rails:29:in '

Caused by:
PG::SyntaxError: ERROR: syntax error at or near "ENGINE"
LINE 1: ...imary key, "key" character varying, "value" text) ENGINE=Inn...
^
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:75:in async_exec' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:75:in block (2 levels) in execute'
/usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/dependencies/interlock.rb:48:in block in permit_concurrent_loads' /usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/concurrency/share_lock.rb:187:in yield_shares'
/usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/dependencies/interlock.rb:47:in permit_concurrent_loads' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:74:in block in execute'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract_adapter.rb:579:in block (2 levels) in log' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract_adapter.rb:578:in block in log'
/usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/notifications/instrumenter.rb:23:in instrument' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract_adapter.rb:569:in log'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:73:in execute' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract/schema_statements.rb:311:in create_table'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:871:in block in method_missing' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:840:in block in say_with_time'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:840:in say_with_time' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:860:in method_missing'
/app/back/dorino/BE/db/migrate/20181231155726_create_confs.rb:3:in up' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:817:in exec_migration'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:798:in block (2 levels) in migrate' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:797:in block in migrate'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:416:in with_connection' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:796:in migrate'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:977:in migrate' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1292:in block in execute_migration_in_transaction'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1343:in block in ddl_transaction' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract/database_statements.rb:259:in block in transaction'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract/transaction.rb:239:in block in within_new_transaction' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract/transaction.rb:236:in within_new_transaction'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/connection_adapters/abstract/database_statements.rb:259:in transaction' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/transactions.rb:212:in transaction'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1343:in ddl_transaction' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1291:in execute_migration_in_transaction'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1263:in block in migrate_without_lock' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1262:in each'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1262:in migrate_without_lock' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1210:in block in migrate'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1363:in with_advisory_lock' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1210:in migrate'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1036:in up' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/migration.rb:1011:in migrate'
/usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/tasks/database_tasks.rb:172:in migrate' /usr/local/bundle/gems/activerecord-5.2.2/lib/active_record/railties/databases.rake:60:in block (2 levels) in

'
/usr/local/bundle/gems/railties-5.2.2/lib/rails/commands/rake/rake_command.rb:23:in block in perform' /usr/local/bundle/gems/railties-5.2.2/lib/rails/commands/rake/rake_command.rb:20:in perform'
/usr/local/bundle/gems/railties-5.2.2/lib/rails/command.rb:48:in invoke' /usr/local/bundle/gems/railties-5.2.2/lib/rails/commands.rb:18:in '
/usr/local/bundle/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in require' /usr/local/bundle/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in block in require_with_bootsnap_lfi'
/usr/local/bundle/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/loaded_features_index.rb:65:in register' /usr/local/bundle/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:20:in require_with_bootsnap_lfi'
/usr/local/bundle/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in require' /usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:291:in block in require'
/usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:257:in load_dependency' /usr/local/bundle/gems/activesupport-5.2.2/lib/active_support/dependencies.rb:291:in require'
/usr/local/bundle/gems/railties-5.2.2/lib/rails/app_loader.rb:59:in block in exec_app' /usr/local/bundle/gems/railties-5.2.2/lib/rails/app_loader.rb:48:in loop'
/usr/local/bundle/gems/railties-5.2.2/lib/rails/app_loader.rb:48:in exec_app' /usr/local/bundle/gems/railties-5.2.2/lib/rails/cli.rb:7:in <top (required)>'
/usr/local/bundle/gems/railties-5.2.2/exe/rails:10:in require' /usr/local/bundle/gems/railties-5.2.2/exe/rails:10:in <top (required)>'
bin/rails:29:in load' bin/rails:29:in '
Tasks: TOP => db:migrate
(See full trace by running task with --trace)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment