如何访问所有创建的对象并更新属性

时间:2016-06-16 03:57:54

标签: ruby oop object

我有一个员工班,我可以存储员工详细信息,如年龄,DOB和赚取的积分。

class Employee
  attr_accessor :id, :dob, :points

  def initialize
    @id = id
    @dob = dob
    @points = points
  end

  def tranfer_points
  # Access both employee objects and add points to one and remove points from other
  end
end


emp_one = Employee.new(1,"2 Jan 1990",400)
emp_two = Employee.new(2,"12 Jan 1986",700)

emp_two.transfer()

我想知道维护所有已创建对象的最佳做法是什么,以便我可以将点从一个员工转移到另一个员工。

我应该在这里使用类变量,这是一个很好的解决方案,它是一个标准做法吗?

如下所示

class Employee
  @@all_employee = Hash.new
  attr_accessor :id, :dob, :points

  def initialize
    @id = id
    @dob = dob
    @points = points
    add_all_employee
  end

  def add_all_employee
    @@all_employee[id] = self
  end

  def tranfer_points(i,points)
    b = @@all_employee[i]
    self.balance -= points
    b.points += points
  end
end

这里的任何帮助将不胜感激。感谢。

2 个答案:

答案 0 :(得分:1)

以下是如何执行此操作的示例。

使用数据库:

class Employee
  def tranfer_points_to(recipient, num_points)
    Employee.transaction do
      self.update!(points: self.points - num_points)
      recipient.update!(points: recipient.points + num_points)
    end
  end
end

使用Rails Transaction是一种很好的方法,可以确保您不会意外更新一个而不是另一个,以防此块中出现异常。

没有数据库:

class Employee
  def tranfer_points_to(recipient, num_points)
    self.points -= num_points
    recipient.points += num_points
  end
end

更新: 回答你的意见:

如果您考虑使用数据库,那么它就不用了,只需保存模型即可。 没有数据库,使用某些父类来保持"保持"员工实例。一个例子:

class Company
  attr_reader :employees

  def initialize
    @employees = []
  end

  def add_employee(id, dob, points)
    employees.push(Employee.new(id, dob, points))
  end

  def tranfer_points(from_employee_id, to_employee_id, num_points)
    find_employee_by_id(from_employee_id).points -= num_points
    find_employee_by_id(to_employee_id).points += num_points
  end

  def find_employee_by_id(id)
    employees.find { |e| e.id == id }
  end
end

company = Company.new
company.add_employee(1, "2 Jan 1990", 400)
company.add_employee(2, "2 Jan 1991", 400)
company.transfer_points(1, 2, 200)

company.find_employee_by_id(1).points => 200
company.find_employee_by_id(2).points => 600

答案 1 :(得分:0)

以下是一个例子:

require 'singleton'
require 'forwardable'
require 'thread'

class EmployeeStore
  include Singleton

  class << self
    extend Forwardable
    def_delegator :instance, :employees, :employees
    def_delegator :instance, :find, :find
    def_delegator :instance, :add, :add
    def_delegator :instance, :transfer_points, :transfer_points
    def_delegator :instance, :remove, :remove
  end

  def employees
    @employees.dup
  end

  def find(id)
    @employees[id].dup
  end

  def add(employee)
    @employees[employee.id] = employee
  end

  def remove(employee)
    case employee
      when Employee
        @employees.delete(employee.id)
      when Fixnum
        @employees.delete(employee)
      else
        raise "Don't know how to delete #{employee}"
    end
  end

  def transfer_points(from, to, points)
    # EmployeeStore is the only way to modify @employees
    real_from, real_to = find(from.id), find(to.id)

    # synchronize for thread-safe
    @mutex.synchronize do
      f_points, t_points = from.points, to.points

      begin
        real_from.instance_variable_set(:@points, f_points - points)
        real_to.instance_variable_set(:@points, t_points + points)
          # do something else
      rescue
        real_from.instance_variable_set(:@points, f_points)
        real_to.instance_variable_set(:@points, t_points)
      ensure
        from.instance_variable_set(:@points, real_from.points)
        to.instance_variable_set(:@points, real_to.points)
      end
    end
  end

  private
  def initialize
    @employees = {}
    @mutex = Mutex.new
    super
  end
end

class Employee
  attr_reader :id, :dob, :points

  def initialize(id, dob, points)
    @id, @dob, @points = id, dob, points
    EmployeeStore.add(self)
  end

  def transfer_points_to(employee, points)
    EmployeeStore.transfer_points(self, employee, points)
  end
end


Employee.new(1, "2 Jan 1990", 400)
Employee.new(2, "12 Jan 1986", 700)

emp_one = EmployeeStore.find(1)
emp_two = EmployeeStore.find(2)

1.upto(10).map do
  Thread.new do
    emp_one.transfer_points_to(emp_two, 30)
  end
end.map(&:join)

p emp_one.points # => 100
p emp_two.points # => 1000

类变量不是线程安全的