簡體   English   中英

如何在Rails中實施“業務規則”?

[英]How to implement “business rules” in Rails?

在Rails中實現“業務規則”的方式是什么?

假設我有一輛車要出售:

car = Cars.find(24)
car.sell

car.sell方法將檢查一些內容:

does current_user own the car?
    check: car.user_id == current_user.id
is the car listed for sale in the sales catalog?
    check: car.catalogs.ids.include? car.id

if all o.k. then car is marked as sold.

我當時正在考慮創建一個名為Rules的類:

class Rules
    def initialize(user,car)
        @user = user
        @car = car
    end

    def can_sell_car?
        @car.user_id == @user.id && @car.catalogs.ids.include? @car.id
    end
end

並像這樣使用它:

def Car
    def sell
        if Rules.new(current_user,self).can_sell_car
            ..sell the car...
        else
            @error_message = "Cannot sell this car"
            nil
        end
    end
end

至於獲取current_user ,我正在考慮將其存儲在全局變量中? 我認為無論何時調用控制器操作,始終都是“新鮮”調用,對嗎? 如果是這樣,那么將當前用戶存儲為全局變量應該不會帶來任何風險。(就像其他一些用戶能夠訪問其他用戶的詳細信息一樣)

任何見解表示贊賞!

UPDATE

因此,全局變量路由出局了! 感謝PeterWong指出全局變量仍然存在!

我現在正在考慮使用這種方式:

class Rules
    def self.can_sell_car?(current_user, car)
       ......checks....
    end
end

然后從控制器操作中調用Rules.can_sell_car?(current_user,@car) 對這種新方式有什么想法嗎?

我將使用以下表格:

對於買賣雙方:

人(ID:INT,名稱:字符串)

class Person << ActiveRecord::Base
  has_many :cars, :as => :owner
  has_many :sales, :as => :seller, :class_name => 'Transfer'
  has_many :purchases, :as => :buyer, :class_name => 'Transfer'
end

汽車(id:int,owner_id:int,vin:string,year:int,make:string,model:string,listed_at:datetime)

listing_at是查看汽車是否出售的標志

class Car << ActiveRecord::Base
  belongs_to :owner, :class_name => 'Person'
  has_many :transfers

  def for_sale?
    not listed_at.nil?
  end
end

傳送(ID:INT,car_id:INT,seller_id:INT,buyer_id:整數)

class Transfer << ActiveRecord::Base
  belongs_to :car
  belongs_to :seller, :class_name => 'Person'
  belongs_to :buyer, :class_name => 'Person

  validates_with Transfer::Validator

  def car_owned_by_seller?
     seller_id == car.owner_id
  end
end

然后,您可以使用此自定義驗證程序來設置規則。

class Transfer::Validator << ActiveModel::Validator
  def validate(transfer)
     transfer.errors[:base] = "Seller doesn't own car" unless transfer.car_owned_by_seller?
     transfer.errors[:base] = "Car isn't for sale" unless transfer.car.for_sale?
  end
end

首先,標准的Rails做法是將所有業務邏輯(而不是控制器)保留在模型中。 看起來您正朝着這個方向發展,所以很好-但是:請注意,沒有一種很好的干凈方法可以從模型中獲取current_user

我不會創建新的規則模型(盡管如果您真的想那樣做,可以這樣做),但我只會涉及用戶模型和汽車。 因此,例如:

class User < ActiveRecord::Base
...
  def sell_car( car )
    if( car.user_id == self.id && car.for_sale? )
      # sell car
    end
  end
...
end

class Car < ActiveRecord::Base
...
  def for_sale?
    !catalog_id.nil?
  end
...
end

顯然,我正在對目錄的工作方式進行假設,但是如果for_sale的belong_to屬於目錄,那么該方法將起作用-否則,根據需要調整方法,以檢查汽車是否在目錄中列出。 坦率地說,在Car模型本身上設置布爾值可能是個好主意,這樣用戶就可以在需要時直接切換要出售或不出售的汽車(通過標記要出售的汽車或將汽車添加到目錄等)。

我希望這會給您一些指導! 請隨時提問。


編輯:另一種方法是在模型中使用如下方法:

user.buy_car( car )
car.transfer_to( user )

有很多方法可以將邏輯放入與其交互的對象中。

我認為這將是使用數據庫的主要候選人,然后您可以使用Ruby查詢不同的表。

您可以看一下聲明式授權gem- https://github.com/stffn/declarative_authorization

盡管已為CRUD操作預先配置了該操作,但您可以輕松添加自己的操作(購買,出售),並將其業務邏輯放入authorization_rules.rb配置文件中。 然后,在您的控制器,視圖甚至模型中!,您可以輕松地問allowed_to? :買,@車

我正在與用戶做類似的事情,以及他們可以對照相館做些什么。 我將devise用於用戶和身份驗證,然后在用戶模型中設置了幾種方法,以確定用戶是否具有對該畫廊采取行動的各種權限(用戶通過權限擁有許多畫廊)。 我認為您面臨的最大問題是確定當前用戶,這可以通過Devise輕松處理,然后可以向用戶模型添加方法並檢查current_user.can_sell? 授權銷售。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM