Skip to content

Instantly share code, notes, and snippets.

@robertsosinski
Created October 11, 2012 00:36
Show Gist options
  • Save robertsosinski/3869435 to your computer and use it in GitHub Desktop.
Save robertsosinski/3869435 to your computer and use it in GitHub Desktop.
A Postgres ActiveRecord::SessionStore::SqlBypass library for Rails
class PostgresSessionStore < ActiveRecord::SessionStore::SqlBypass
@@session_id_column = 'id'
@@schema_name = 'system'
cattr_accessor :schema_name
class << self
def marshal(data)
::Base64.encode64(Marshal.dump(data)).chomp if data
end
def unmarshal(data)
Marshal.load(::Base64.decode64(data)) if data
end
def create_table!
connection.execute <<-SQL
do $$
begin
perform schema_name from information_schema.schemata where schema_name = '#{schema_name}';
if not found then
create schema #{schema_name};
end if;
end;
$$ language 'plpgsql';
create unlogged table #{connection.quote_table_name(schema_name)}.#{connection.quote_table_name(table_name)} (
#{session_id_column} varchar primary key,
data text,
created_at timestamp,
updated_at timestamp
);
SQL
end
def drop_table!
connection.execute <<-SQL
drop table #{schema_name}.#{table_name};
SQL
end
def find_by_session_id(session_id)
if record = connection.select_one("select * from #{connection.quote_table_name(schema_name)}.#{connection.quote_table_name(table_name)} where #{connection.quote_column_name(session_id_column)} = #{connection.quote(session_id)} limit 1")
new(:session_id => session_id, :marshaled_data => record['data'])
end
end
end
def initialize(attributes)
@current_marshaled_data = attributes[:marshaled_data]
super
end
def save
return false unless loaded?
marshaled_data = self.class.marshal(data)
return if @current_marshaled_data == marshaled_data
if @new_record
@new_record = false
connection.update <<-SQL, 'Create session'
insert into #{connection.quote_table_name(schema_name)}.#{connection.quote_table_name(table_name)} (#{connection.quote_column_name(session_id_column)}, #{connection.quote_column_name(data_column)}, "created_at", "updated_at")
values (#{connection.quote(session_id)}, #{connection.quote(marshaled_data)}, now(), now())
SQL
else
connection.update <<-SQL, 'Update session'
update #{connection.quote_table_name(schema_name)}.#{connection.quote_table_name(table_name)}
set #{connection.quote_column_name(data_column)} = #{connection.quote(marshaled_data)}, "updated_at" = now()
where #{connection.quote_column_name(session_id_column)} = #{connection.quote(session_id)}
SQL
end
end
def destroy
return if @new_record
connect = connection
connect.delete <<-SQL, 'Destroy session'
delete from #{connection.quote_table_name(schema_name)}.#{connection.quote_table_name(table_name)} where #{connect.quote_column_name(session_id_column)} = #{connect.quote(session_id)}
SQL
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment