Ruby ActiveRecord 对象的减号运算符
Ruby minus operator with ActiveRecord objects
你能解释一下吗,Ruby 的减号运算符是如何工作的?不仅仅是像 5 - 2 这样的小案例。
有点复杂——我们有 2 个带有 ActiveRecord 对象的数组:
数组 A = User.where(...)
,数组 B = User.where(...)
,我想制作 A - B,它是如何工作的?它只是比较对象 ID 或所有属性,还是其他?
Is it just comparing objects IDs?
类型和 ID,是的。
pry(main)> show-source User#eql?
From: /Users/sergio/.gem/ruby/2.5.1/gems/activerecord-5.2.0/lib/active_record/core.rb @ line 420:
Owner: ActiveRecord::Core
Visibility: public
Number of lines: 6
def ==(comparison_object)
super ||
comparison_object.instance_of?(self.class) &&
!id.nil? &&
comparison_object.id == id
end
Sergio 回答的更多细节:
我缩小了 -
方法(运算符)对 ActiveRecord::Relation
对象的作用,因为我自己也很好奇:
Rails 5:
回溯:
# rails console (pry-rails)
users_a = User.where(...)
users_b = User.where(...)
puts users_a.class
# => `User::ActiveRecord_Relation`
show-source users_a.-
# From: /Users/jrpolidario/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/activerecord-5.2.0/lib/active_record/relation/delegation.rb @ line 41:
# Owner: ActiveRecord::Delegation
# Visibility: public
# Number of lines: 4
#
# delegate :to_xml, :encode_with, :length, :each, :uniq, :join,
# :[], :&, :|, :+, :-, :sample, :reverse, :rotate, :compact, :in_groups, :in_groups_of,
# :to_sentence, :to_formatted_s, :as_json,
# :shuffle, :split, :slice, :index, :rindex, to: :records
# since the `-` method as seen above is delegated to #records, let's see what the return type is the return value of `#records` is, of which is supposed to respond to the `-` operator.
puts users_a.records.class
# => Array
# ...because it's an Array type, then let's see if the Array type responds to the delegated `-` method.
show-source users_a.records.-
# From: array.c (C Method):
# Owner: Array
# Visibility: public
# Number of lines: 17
#
# static VALUE
# rb_ary_diff(VALUE ary1, VALUE ary2)
# {
# VALUE ary3;
# VALUE hash;
# long i;
#
# hash = ary_make_hash(to_ary(ary2));
# ary3 = rb_ary_new();
#
# for (i=0; i<RARRAY_LEN(ary1); i++) {
# if (st_lookup(rb_hash_tbl_raw(hash), RARRAY_AREF(ary1, i), 0)) continue;
# rb_ary_push(ary3, rb_ary_elt(ary1, i));
# }
# ary_recycle_hash(hash);
# return ary3;
# }
... 这只是简单的意思,我引用 Array
Returns a new array that is a copy of the original array, removing any items that also appear in other_ary. The order is preserved from the original array.
Rails 4
P.S。我也尝试在 rails 4.2 中跟踪这个,并且 show-source users_a.-
没有显示任何方法,这意味着它使用了 method_missing
(因此也意味着在 4 和 5 之间有变化关于这个),然后,进一步追踪,我得到以下结果:
回溯:
[127, 136] in /Users/jrpolidario/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-4.2.10/lib/active_record/relation/delegation.rb
127:
128: def method_missing(method, *args, &block)
129: if @klass.respond_to?(method)
130: scoping { @klass.public_send(method, *args, &block) }
131: elsif array_delegable?(method)
=> 132: to_a.public_send(method, *args, &block)
133: elsif arel.respond_to?(method)
134: arel.public_send(method, *args, &block)
135: else
136: super
... 如您所见,.to_a
在 ActiveRecord::Relation
对象上被调用,这意味着它成为一个数组,然后 method
(即 '-'
) 在该 Array 对象上被调用,这也意味着最后它也会调用上面 Rails 5 中相同的 Array#-
方法。
你能解释一下吗,Ruby 的减号运算符是如何工作的?不仅仅是像 5 - 2 这样的小案例。
有点复杂——我们有 2 个带有 ActiveRecord 对象的数组:
数组 A = User.where(...)
,数组 B = User.where(...)
,我想制作 A - B,它是如何工作的?它只是比较对象 ID 或所有属性,还是其他?
Is it just comparing objects IDs?
类型和 ID,是的。
pry(main)> show-source User#eql?
From: /Users/sergio/.gem/ruby/2.5.1/gems/activerecord-5.2.0/lib/active_record/core.rb @ line 420:
Owner: ActiveRecord::Core
Visibility: public
Number of lines: 6
def ==(comparison_object)
super ||
comparison_object.instance_of?(self.class) &&
!id.nil? &&
comparison_object.id == id
end
Sergio 回答的更多细节:
我缩小了 -
方法(运算符)对 ActiveRecord::Relation
对象的作用,因为我自己也很好奇:
Rails 5:
回溯:
# rails console (pry-rails)
users_a = User.where(...)
users_b = User.where(...)
puts users_a.class
# => `User::ActiveRecord_Relation`
show-source users_a.-
# From: /Users/jrpolidario/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/activerecord-5.2.0/lib/active_record/relation/delegation.rb @ line 41:
# Owner: ActiveRecord::Delegation
# Visibility: public
# Number of lines: 4
#
# delegate :to_xml, :encode_with, :length, :each, :uniq, :join,
# :[], :&, :|, :+, :-, :sample, :reverse, :rotate, :compact, :in_groups, :in_groups_of,
# :to_sentence, :to_formatted_s, :as_json,
# :shuffle, :split, :slice, :index, :rindex, to: :records
# since the `-` method as seen above is delegated to #records, let's see what the return type is the return value of `#records` is, of which is supposed to respond to the `-` operator.
puts users_a.records.class
# => Array
# ...because it's an Array type, then let's see if the Array type responds to the delegated `-` method.
show-source users_a.records.-
# From: array.c (C Method):
# Owner: Array
# Visibility: public
# Number of lines: 17
#
# static VALUE
# rb_ary_diff(VALUE ary1, VALUE ary2)
# {
# VALUE ary3;
# VALUE hash;
# long i;
#
# hash = ary_make_hash(to_ary(ary2));
# ary3 = rb_ary_new();
#
# for (i=0; i<RARRAY_LEN(ary1); i++) {
# if (st_lookup(rb_hash_tbl_raw(hash), RARRAY_AREF(ary1, i), 0)) continue;
# rb_ary_push(ary3, rb_ary_elt(ary1, i));
# }
# ary_recycle_hash(hash);
# return ary3;
# }
... 这只是简单的意思,我引用 Array
Returns a new array that is a copy of the original array, removing any items that also appear in other_ary. The order is preserved from the original array.
Rails 4
P.S。我也尝试在 rails 4.2 中跟踪这个,并且 show-source users_a.-
没有显示任何方法,这意味着它使用了 method_missing
(因此也意味着在 4 和 5 之间有变化关于这个),然后,进一步追踪,我得到以下结果:
回溯:
[127, 136] in /Users/jrpolidario/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-4.2.10/lib/active_record/relation/delegation.rb
127:
128: def method_missing(method, *args, &block)
129: if @klass.respond_to?(method)
130: scoping { @klass.public_send(method, *args, &block) }
131: elsif array_delegable?(method)
=> 132: to_a.public_send(method, *args, &block)
133: elsif arel.respond_to?(method)
134: arel.public_send(method, *args, &block)
135: else
136: super
... 如您所见,.to_a
在 ActiveRecord::Relation
对象上被调用,这意味着它成为一个数组,然后 method
(即 '-'
) 在该 Array 对象上被调用,这也意味着最后它也会调用上面 Rails 5 中相同的 Array#-
方法。