lib/vines/storage/sql.rb in vines-0.3.2 vs lib/vines/storage/sql.rb in vines-0.4.0

- old
+ new

@@ -11,14 +11,30 @@ class Fragment < ActiveRecord::Base belongs_to :user end class Group < ActiveRecord::Base; end class User < ActiveRecord::Base - has_many :contacts - has_many :fragments + has_many :contacts, :dependent => :destroy + has_many :fragments, :dependent => :delete_all end + # Wrap the method with ActiveRecord connection pool logic, so we properly + # return connections to the pool when we're finished with them. This also + # defers the original method by pushing it onto the EM thread pool because + # ActiveRecord uses blocking IO. + def self.with_connection(method, args={}) + deferrable = args.key?(:defer) ? args[:defer] : true + old = "_with_connection_#{method}" + alias_method old, method + define_method method do |*args| + ActiveRecord::Base.connection_pool.with_connection do + method(old).call(*args) + end + end + defer(method) if deferrable + end + %w[adapter host port database username password pool].each do |name| define_method(name) do |*args| if args.first @config[name.to_sym] = args.first else @@ -36,34 +52,30 @@ [:username, :password].each {|key| @config.delete(key) if empty?(@config[key]) } establish_connection end def find_user(jid) - ActiveRecord::Base.clear_reloadable_connections! - jid = JID.new(jid).bare.to_s return if jid.empty? xuser = user_by_jid(jid) - return Vines::User.new(:jid => jid).tap do |user| + return Vines::User.new(jid: jid).tap do |user| user.name, user.password = xuser.name, xuser.password xuser.contacts.each do |contact| groups = contact.groups.map {|group| group.name } user.roster << Vines::Contact.new( - :jid => contact.jid, - :name => contact.name, - :subscription => contact.subscription, - :ask => contact.ask, - :groups => groups) + jid: contact.jid, + name: contact.name, + subscription: contact.subscription, + ask: contact.ask, + groups: groups) end end if xuser end - defer :find_user + with_connection :find_user def save_user(user) - ActiveRecord::Base.clear_reloadable_connections! - - xuser = user_by_jid(user.jid) || Sql::User.new(:jid => user.jid.bare.to_s) + xuser = user_by_jid(user.jid) || Sql::User.new(jid: user.jid.bare.to_s) xuser.name = user.name xuser.password = user.password # remove deleted contacts from roster xuser.contacts.delete(xuser.contacts.select do |contact| @@ -72,126 +84,118 @@ # update contacts xuser.contacts.each do |contact| fresh = user.contact(contact.jid) contact.update_attributes( - :name => fresh.name, - :ask => fresh.ask, - :subscription => fresh.subscription, - :groups => groups(fresh)) + name: fresh.name, + ask: fresh.ask, + subscription: fresh.subscription, + groups: groups(fresh)) end # add new contacts to roster jids = xuser.contacts.map {|c| c.jid } user.roster.select {|contact| !jids.include?(contact.jid.bare.to_s) } .each do |contact| xuser.contacts.build( - :user => xuser, - :jid => contact.jid.bare.to_s, - :name => contact.name, - :ask => contact.ask, - :subscription => contact.subscription, - :groups => groups(contact)) + user: xuser, + jid: contact.jid.bare.to_s, + name: contact.name, + ask: contact.ask, + subscription: contact.subscription, + groups: groups(contact)) end xuser.save end - defer :save_user + with_connection :save_user def find_vcard(jid) - ActiveRecord::Base.clear_reloadable_connections! - jid = JID.new(jid).bare.to_s return if jid.empty? if xuser = user_by_jid(jid) Nokogiri::XML(xuser.vcard).root rescue nil end end - defer :find_vcard + with_connection :find_vcard def save_vcard(jid, card) - ActiveRecord::Base.clear_reloadable_connections! - xuser = user_by_jid(jid) if xuser xuser.vcard = card.to_xml xuser.save end end - defer :save_vcard + with_connection :save_vcard def find_fragment(jid, node) - ActiveRecord::Base.clear_reloadable_connections! - jid = JID.new(jid).bare.to_s return if jid.empty? if fragment = fragment_by_jid(jid, node) Nokogiri::XML(fragment.xml).root rescue nil end end - defer :find_fragment + with_connection :find_fragment def save_fragment(jid, node) - ActiveRecord::Base.clear_reloadable_connections! - jid = JID.new(jid).bare.to_s fragment = fragment_by_jid(jid, node) || Sql::Fragment.new( - :user => user_by_jid(jid), - :root => node.name, - :namespace => node.namespace.href) + user: user_by_jid(jid), + root: node.name, + namespace: node.namespace.href) fragment.xml = node.to_xml fragment.save end - defer :save_fragment + with_connection :save_fragment # Create the tables and indexes used by this storage engine. def create_schema(args={}) - ActiveRecord::Base.clear_reloadable_connections! - args[:force] ||= false ActiveRecord::Schema.define do - create_table :users, :force => args[:force] do |t| - t.string :jid, :limit => 2048, :null => false - t.string :name, :limit => 1000, :null => true - t.string :password, :limit => 1000, :null => true - t.text :vcard, :null => true + create_table :users, force: args[:force] do |t| + t.string :jid, limit: 512, null: false + t.string :name, limit: 256, null: true + t.string :password, limit: 256, null: true + t.text :vcard, null: true end - add_index :users, :jid, :unique => true + add_index :users, :jid, unique: true - create_table :contacts, :force => args[:force] do |t| - t.integer :user_id, :null => false - t.string :jid, :limit => 2048, :null => false - t.string :name, :limit => 1000, :null => true - t.string :ask, :limit => 1000, :null => true - t.string :subscription, :limit => 1000, :null => false + create_table :contacts, force: args[:force] do |t| + t.integer :user_id, null: false + t.string :jid, limit: 512, null: false + t.string :name, limit: 256, null: true + t.string :ask, limit: 128, null: true + t.string :subscription, limit: 128, null: false end - add_index :contacts, [:user_id, :jid], :unique => true + add_index :contacts, [:user_id, :jid], unique: true - create_table :groups, :force => args[:force] do |t| - t.string :name, :limit => 1000, :null => false + create_table :groups, force: args[:force] do |t| + t.string :name, limit: 256, null: false end - add_index :groups, :name, :unique => true + add_index :groups, :name, unique: true - create_table :contacts_groups, :id => false, :force => args[:force] do |t| - t.integer :contact_id, :null => false - t.integer :group_id, :null => false + create_table :contacts_groups, id: false, force: args[:force] do |t| + t.integer :contact_id, null: false + t.integer :group_id, null: false end - add_index :contacts_groups, [:contact_id, :group_id], :unique => true + add_index :contacts_groups, [:contact_id, :group_id], unique: true - create_table :fragments, :force => args[:force] do |t| - t.integer :user_id, :null => false - t.string :root, :limit => 1000, :null => false - t.string :namespace, :limit => 1000, :null => false - t.text :xml, :null => false + create_table :fragments, force: args[:force] do |t| + t.integer :user_id, null: false + t.string :root, limit: 256, null: false + t.string :namespace, limit: 256, null: false + t.text :xml, null: false end - add_index :fragments, [:user_id, :root, :namespace], :unique => true + add_index :fragments, [:user_id, :root, :namespace], unique: true end end + with_connection :create_schema, defer: false private def establish_connection + ActiveRecord::Base.logger = Logger.new('/dev/null') ActiveRecord::Base.establish_connection(@config) # has_and_belongs_to_many requires a connection so configure the # associations here rather than in the class definitions above. Sql::Contact.has_and_belongs_to_many :groups Sql::Group.has_and_belongs_to_many :contacts