получить `current_user` в моем классе пользователя - PullRequest
1 голос
/ 16 ноября 2009

Как ни странно, большая часть этого работает так, как было написано, однако я не уверен, как я могу оценить, если current_user имеет значок, (все отношения правильные, у меня только проблемы с моими методами в моем классе (который должен быть частично перемещен в библиотеку или что-то в этом роде), независимо от того, проблема именно в 1) проверке, есть ли у текущего пользователя запись, и 2), если нет, создать соответствующую новую запись.

Если есть более простой или лучший способ сделать это, пожалуйста, поделитесь. Вот что у меня есть:

# Recipe Controller
class RecipesController < ApplicationController
  def create
  # do something
  if @recipe.save
    current_user.check_if_badges_earned(current_user)
  end
end

Так что для этого, это определенно кажется грязным, я бы хотел, чтобы оно было просто check_if_badges_earned и не должно было передавать current_user в метод, но может понадобиться, потому что это может не всегда быть текущим пользователь, инициирующий этот метод.

# User model
class User < ActiveRecord::Base

  def check_if_badges_earned(user)
    if user.recipes.count > 10
      award_badge(1, user)
    end
    if user.recipes.count > 20
      award_badge(2, user)
    end
  end

  def award_badge(badge_id, user)
    #see if user already has this badge, if not, give it to them!
    unless user.badgings.any? { |b| b[:badge_id] == badge_id}
      @badging = Badging.new(:badge_id => badge_id, :user_id => user)
      @badging.save
    end
  end

end

Таким образом, хотя первый метод (check_if_badges_earned), кажется, оправдывает штраф и дает прогон award_badge() только при выполнении условий, проблема возникает в самом методе award_badge(), выражение unless user.badgings.any? { |b| b[:badge_id] == badge_id} всегда оценивается как истинное, поэтому пользователю дается значок, даже если он уже был у него (badge_id), во-вторых, проблема в том, что он всегда сохраняет user_id как 1.

Любые идеи о том, как отладить это, были бы великолепны!

Ответы [ 2 ]

2 голосов
/ 16 ноября 2009

Независимо от того, требуется ли вам поведение current_user, описанное выше, award_badge должен быть просто методом обычного экземпляра, действующим на self вместо того, чтобы действовать на переданный аргумент user (то же самое относится и к check_if_badges_earned). В вашем award_badge методе попробуйте find_or_create_by_... вместо логики, которую вы в настоящее время используете . Например, попробуйте это:

class User < ActiveRecord::Base
  # ...

  def award_badge(badge_id)
    badgings.find_or_create_by_badge_id(badge_id)
  end
end

Чтобы получить доступ к current_user в ваших модельных классах, мне иногда нравится использовать локальные переменные потока . Это, конечно, размывает разделение MVC, но иногда такой тип связи просто необходим в приложении.

В вашем ApplicationController сохраните current_user в локальной переменной потока:

class ApplicationController < ActionController::Base
  before_filter :set_thread_locals

  private

  # Store thread-local variables so models can access them (Hackish, but useful)
  def set_thread_locals
    Thread.current[:current_user] = current_user
  end
end

Добавьте новый метод класса в модель ActiveRecord, чтобы получить current_user (вы также можете расширить ActiveRecord :: Base, чтобы сделать его доступным для всех моделей):

class User < ActiveRecord::Base
  def self.current_user
    Thread.current[:current_user]
  end
end

Тогда вы сможете получить доступ к текущему пользователю в методах экземпляра вашей User модели с помощью self.class.current_user.

1 голос
/ 16 ноября 2009

Прежде всего, вам нужно сделать методы класса методами (вызовом себя), что исключает ненужную передачу пользовательской ссылки.

Затем, в вашем методе award_badge, вы должны добавить Badging в список Badgings пользователя, например: user.badgings << Badging.new(:badge_id => badge_id)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...