用户可以拥有多辆车 -
User: has_many :cars
Car: belongs_to :user
每次拨打@user.cars
时,都会返回默认搜索顺序中的cars
列表。
如果我希望关联在某个任意字段上排序,我可以
class User < ActiveRecord::Base
has_many :cars, -> { order :num_wheels }
end
但是,让我们说我的排序逻辑很复杂,我想重写关联getter来实现我自己的逻辑
我尝试了类似的东西 -
class User < ActiveRecord::Base
has_many :cars
def cars
# Pretend this is complex logic
cars.order(:num_wheels)
end
end
然而,这显然会失败,因为您无法在被覆盖的cars
方法中引用原始cars
而不会无限循环。
有没有办法引用&#34;原作&#34;从被覆盖的吸气剂里面吸气?
谢谢!
答案 0 :(得分:10)
使用super:
class User < ActiveRecord::Base
has_many :cars
def cars
# Pretend this is complex logic
super.order(:num_wheels)
end
end
当您使用像has_many这样的宏时,Rails会动态创建一个模块(可以通过User.generated_association_methods访问)。在您的情况下,定义访问者和读者(例如&#34; cars&#34;在您的情况下) ,可以通过User.generated_association_methods.instance_methods访问。此模块成为User类的祖先,因此您可以通过&#34; super&#34;访问读取器方法(汽车)。在你自己的汽车方法。
答案 1 :(得分:2)
根据我的理解,我相信has_many本质上正在做的是:
Class User < ActiveRecord::Base
has_many :cars
# is essentially
def cars
Car.where(user_id: self.id)
end
end
因此,当用户想要列出所有汽车时,它仍然是User.cars。当使用ActiveRecord时,has_many假设汽车的方法名称和相关的外键。
答案 2 :(得分:0)
试试这个:
template <typename C, typename E> std::false_type has_event_handler_impl(...);
template <typename C, typename E>
auto has_event_handler_impl(int)
-> decltype(static_cast<void>(std::declval<C>().receive(std::declval<const E>())),
std::true_type{});
template <typename C, typename E>
using has_event_handler = decltype(has_event_handler_impl<C, E>(0));
template <class... Es>
class Emitter {
public:
template<class C>
void reg(C& callback) {
const int dummy[] = { 0, (regT<Es>(callback), 0)...};
static_cast<void>(dummy); // Avoid unused variable warning
}
template <typename E>
void emit(const E& event)
{
for (auto const& handler : get_vector<E>()) {
handler(event);
}
}
private:
template <typename E, typename C>
std::enable_if_t<has_event_handler<C, E>::value>
regT(C& callback)
{
auto lambda = [&callback](const E& event) { return callback.receive(event); };
get_vector<E>().push_back(lambda);
}
template <typename E, typename C>
std::enable_if_t<!has_event_handler<C, E>::value>
regT(C&)
{
/* Empty */
}
template <typename E>
std::vector<std::function<void(const E&)>>& get_vector()
{
return std::get<std::vector<std::function<void(const E&)>>>(handlers_);
}
private:
std::tuple<std::vector<std::function<void(const Es&)>>...> handlers_;
};