Module: DatabaseSlave::Relation
- Defined in:
- lib/database_slave/relation.rb
Instance Attribute Summary collapse
-
#slave_name ⇒ Object
Returns the value of attribute slave_name.
Instance Method Summary collapse
-
#calculate(operation, column_name, options = {}) ⇒ Object
Supports ActiveRecord::Calculations: count, average, minimun, maximum, sum, calculate.
-
#except(*skips) ⇒ Object
junk hack: except会重新生成一个ActiveRecord::Relation对象, 所以except之前的using_slave就会失效, 这里hack一下添加进来.
-
#exists?(id = false) ⇒ Boolean
Supports ActiveRecord::FinderMethods: exists?.
- #initialize(klass, table) ⇒ Object
-
#pluck(column_name) ⇒ Object
Supports ActiveRecord::Calculations: pluck.
-
#to_a ⇒ Object
Description.
- #unusing_slave ⇒ Object
- #using_slave(slave_name) ⇒ Object (also: #using)
- #using_slave? ⇒ Boolean
Instance Attribute Details
#slave_name ⇒ Object
Returns the value of attribute slave_name.
3 4 5 |
# File 'lib/database_slave/relation.rb', line 3 def slave_name @slave_name end |
Instance Method Details
#calculate(operation, column_name, options = {}) ⇒ Object
Supports ActiveRecord::Calculations:
count, average, minimun, maximum, sum, calculate
151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/database_slave/relation.rb', line 151 def calculate(operation, column_name, = {}) if !DatabaseSlave::RuntimeRegistry.current_slave_name begin DatabaseSlave::RuntimeRegistry.current_slave_name = slave_name if using_slave? super ensure DatabaseSlave::RuntimeRegistry.current_slave_name = nil end else super end end |
#except(*skips) ⇒ Object
junk hack:
except
这里hack一下添加进来.
(
168 169 170 171 172 |
# File 'lib/database_slave/relation.rb', line 168 def except(*skips) slave_name_snake = slave_name.to_s.underscore.split('/').last return super if slave_name_snake.blank? using_slave? ? super.using(slave_name_snake.to_sym) : super end |
#exists?(id = false) ⇒ Boolean
Supports ActiveRecord::FinderMethods:
exists?
119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/database_slave/relation.rb', line 119 def exists?(id = false) if !DatabaseSlave::RuntimeRegistry.current_slave_name begin DatabaseSlave::RuntimeRegistry.current_slave_name = slave_name if using_slave? super ensure DatabaseSlave::RuntimeRegistry.current_slave_name = nil end else super end end |
#initialize(klass, table) ⇒ Object
5 6 7 8 9 10 11 12 |
# File 'lib/database_slave/relation.rb', line 5 def initialize(klass, table) slave_name = nil if (slave = ActiveRecord::Relation.class_variable_get(:@@slave_block_given)).present? self.slave_name = slave end super end |
#pluck(column_name) ⇒ Object
Supports ActiveRecord::Calculations:
pluck
135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/database_slave/relation.rb', line 135 def pluck(column_name) if !DatabaseSlave::RuntimeRegistry.current_slave_name begin DatabaseSlave::RuntimeRegistry.current_slave_name = slave_name if using_slave? super ensure DatabaseSlave::RuntimeRegistry.current_slave_name = nil end else super end end |
#to_a ⇒ Object
Description
Rails中所有的relation最后都是调用to_a后返回最终结果.
这里我们重写ActiveRecord::Relation的to_a方法只是为了做一件事:
对应到代码即:
DatabaseSlave::RuntimeRegistry.current_slave_name = nil
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/database_slave/relation.rb', line 77 def to_a # 该if语句的作用是: 确保在一条使用从库的查询中存在的其他先决条件的 # 查询也使用从库。例如: # # class Book < ActiveRecord::Base # default_scope lambda { where(:tag_id => Tag.published.pluck(:id)) } # end # # 当我们使用如下查询 # # Book.order('id DESC').limit(2).pluck(:id) # # 时, default_scope中的Tag需要被先查询出来. 为了Book和Tag的查询都使用从库, # 避免查询Tag后便释放了从库连接而导致Book的查询使用的还是主库. 故在这里 # 加了条件判断: 如果父查询已经设置了使用从库, 那么内部的所有查询都使用从库, # 直到父查询返回. # # Supports ActiveRecord::QueryMethods: # select, group, order, reorder, joins, where, having, # limit, offset, uniq # # And ActiveRecord::FinderMethods: # first, first!, last, last!, find, all # # And ActiveRecord::Batches: # find_each, find_in_batches # if !DatabaseSlave::RuntimeRegistry.current_slave_name begin DatabaseSlave::RuntimeRegistry.current_slave_name = slave_name if using_slave? super ensure DatabaseSlave::RuntimeRegistry.current_slave_name = nil end else super end end |
#unusing_slave ⇒ Object
18 19 20 21 22 |
# File 'lib/database_slave/relation.rb', line 18 def unusing_slave slave_name = nil self end |
#using_slave(slave_name) ⇒ Object Also known as: using
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/database_slave/relation.rb', line 24 def using_slave(slave_name) if Settings.using_slave if block_given? db_name = "DatabaseSlave::ConnectionHandler::#{slave_name.to_s.strip.camelize}" unless ActiveRecord::Base.slave_connections.include? db_name raise DatabaseSlave::SlaveConnectionNotExists, "#{slave_name} is not exists." end ActiveRecord::Relation.class_variable_set(:@@slave_block_given, db_name) DatabaseSlave::RuntimeRegistry.current_slave_name ||= db_name begin yield ensure ActiveRecord::Relation.class_variable_set(:@@slave_block_given, nil) DatabaseSlave::RuntimeRegistry.current_slave_name = nil end else # 不能使用抽象类级联式查询, 即不能使用ActiveRecord::Base.using().where() if self.name.eql? DatabaseSlave::NoneActiveRecord.name raise DatabaseSlave::AbstractClassWithoutBlockError, 'a block must be given to abstract class, or you can use a specific class.' end self.slave_name = "DatabaseSlave::ConnectionHandler::#{slave_name.to_s.strip.camelize}" relation = clone if ActiveRecord::Base.slave_connections.include? self.slave_name relation else raise DatabaseSlave::SlaveConnectionNotExists, "#{slave_name} is not exists." end end else # using master database if Settings.using_slave == false or nil block_given? ? yield : clone end end |
#using_slave? ⇒ Boolean
14 15 16 |
# File 'lib/database_slave/relation.rb', line 14 def using_slave? slave_name.to_s.present? end |