简体   繁体   中英

Ruby on Rails: using nested named_scopes

I just got referred to stackoverflow by a friend here to help with a problem I am having. I am fairly new to ruby on rails and I am working on a collaborative project where we have a script (medal_worker.rb) that is scheduled to run at a fixed intervals to award people various medals based on various participation and success on our website. One of the new medals I am working on rewards people for "milestones". For the purpose of this problem, let's say we want to give them medals when they make 100, 1000, and 10000 comments. I would like to do this by using named_scopes from the User model (user.rb) to give me filtered lists of the users I am looking for.

My question is: How do I find the users who do not have the respective medals for the respective milestone comment level (preferably using the named_scopes from the User model)?

Here is an exerpt from my model_worker.rb file:

def award_comment_milestone(comments)
   users = Users.frequent_comment_club_members(comments).not_awarded_medal(Medal.find_by_id(medal.id))
   for user in users do
      award_medal(medal, nil, user) if @award
   end
end

Here is where I am at with the named_scopes in the user model (user.rb):

named_scope :frequent_comment_club_members, lambda { |*args|
        {:include => comment_records, :conditions => ['comment_records.comment_type = ? and comment_records.comments >= ?', 'User', (args.first || 0)]}
}

named_scope :not_awarded_medal, lambda { |medal|
    {:include => :awards, :conditions => ['awards.medal_id not in (select awards.medal_id from awards where awards.medal_id = ?)", medal.id] }
}

This is not working as I would like, but I don't know if the problem is in the named_scopes or how I am passing arguements or what. Thanks.

Your named_scopes look fine. Except you are starting with a single apostrophe and ending with a double apostrophe in the not_awarded_medal condition statement.

EDIT :

Take it back. Your not_awarded_medal named_scope is off.

Try something like this:

named_scope :not_awarded_medal, lambda { |medal_id|
  { :include => :awards,
    :conditions => [
      "? not in (select awards.id from awards where awards.user_id = users.id)", medal_id
    ]
  }
}

untested

Now this is assuming that you have the following relationships:

User: has_many :awards Award: belongs_to :user

If you are using has_many :through then you are going to have to change the SQL to look at the join (users_awards) table.

--

But I do see a couple of things in the award_comment_milestone function.

What is the parameter coming into award_comment_milestone ? Is it an array of comments or is it a count of comments? Also where is medal defined?

If comments is an array then you need to pass comments.length into frequent_comment_club_members . If it's the count then I would rename it to comments_count so the next person can understand the logic more quickly.

Some general observations:

  • not_awarded_medal should just take a medal_id and not the whole object (no need to do multiple queries)
  • Why are you doing Medal.find_by_id(medal.id) ? You already have the medal object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM