Rails多表筛选活动报错:ActiveRecord::Relation无id方法
Hey there! The error you're seeing happens because your activities array is filled with ActiveRecord::Relation objects (not individual Activity instances) when you run activities << Activity.where(group: group). Each Activity.where(...) returns a query object, not the actual records. So when you loop through activities.each do |activity|, you're trying to call id on a relation—which doesn't have that method (it has ids instead, which returns an array of IDs for the relation).
Your goal is to fetch activities that exist in both the current user's groups and their user_activity records. Instead of loading all group activities and filtering in Ruby (which is inefficient and error-prone), we can do this directly with a database query that's faster and cleaner.
Corrected Efficient Solution
Here's a revised method that fixes the error and optimizes the logic:
def fetch_maj_activities user = current_user # Get all activity IDs linked to the user in user_activity user_activity_ids = user.user_activities.pluck(:activity_id).uniq # Get all group IDs the user belongs to group_ids = user.groups.pluck(:id) # Fetch only activities that meet both criteria, sorted by update time @all_activities = Activity.where(id: user_activity_ids, group_id: group_ids) .order(updated_at: :desc) respond_to do |format| format.js end end
Why this works:
pluck(:id)efficiently retrieves just the necessary IDs from the database without loading full objects, which saves memory and speed.- The
whereclause combines both conditions: we only get activities whose ID is in the user'suser_activityrecords AND whose group ID is in the user's groups. order(updated_at: :desc)replaces your in-memory sort with a database-level sort, which is far more efficient for large datasets.
Fixed Version of Your Original Approach
If you prefer to stick closer to your initial code structure (though not recommended for performance), you can fix the error by loading actual activity records instead of relations:
def fetch_maj_activities user = current_user activities = [] user.groups.each do |group| # Convert the relation to an array of Activity instances with .to_a activities += Activity.where(group: group).to_a end usersactivities_id = current_user.user_activities.select('activity_id').map(&:activity_id).uniq # Filter to keep only activities present in usersactivities_id activities = activities.select { |activity| usersactivities_id.include?(activity.id) } @all_activities = activities.sort_by(&:updated_at).reverse respond_to do |format| format.js end end
内容的提问来源于stack exchange,提问作者Benjamin Barbé

