16

Rails 3でのテストはまだかなり新しいので、RSpecとRemarkableを使用しています。私はすでにたくさんの投稿といくつかの本を読みましたが、協会の名前とそのIDをいつ使用するかについては、まだ不確実なままです。

class Project < ActiveRecord::Base
  has_many :tasks
end

class Task < ActiveRecord::Base
  belongs_to :project
end

良い習慣があるので、自分の属性を大量の割り当てから保護したいと思います。

class Task < ActiveRecord::Base
  attr_accessible :project  # Or is it :project_id??

  belongs_to :project
end

まず第一に、有効なタスクなしでプロジェクトが存在しないことを確認したいと思います。

class Task < ActiveRecord::Base
  validates :project, :presence => true      # Which one is the...
  validates :project_id, :presence => true   # ...right way to go??
end

また、割り当てられたプロジェクトまたはプロジェクトIDが常に有効であることを確認したいと思います。

class Task < ActiveRecord::Base
  validates :project, :associated => true     # Again, which one is...
  validates :project_id, :associated => true  # ...the right way to go?
end

...そして:associatedを使用する場合、:presenceの検証が必要ですか?

明確にしてくれてありがとう、RSpec / shoulda / Remarkableを使って何時間も読んでテストしようとした後、もうすべての木があるので森が見えなくなったようです...

4

4 に答える 4

11

これは正しい方法のようです:

attr_accessible :project_id

あなたも:projectそこに置く必要はありません!とにかくできるtask.project=(Project.first!)

次に:project_id、次を使用して の存在を確認します ( を使用する:project_idと も設定さtask.project=(...)れます)。

validates :project_id, :presence => true

関連するプロジェクトが次のように有効であることを確認してください。

validates :project, :associated => true

そう:

t = Task.new
t.project_id = 1 # Value is accepted, regardless whether there is a Project with ID 1
t.project = Project.first # Any existing valid project is accepted
t.project = Project.new(:name => 'valid value') # A new valid project is accepted
t.project = Project.new(:name => 'invalid value') # A new invalid (or an existing invalid) project is NOT accepted!

t.project_id =ID を割り当てるときに、この特定の ID が実際に存在するかどうかがチェックされないのは少し残念です。カスタム検証またはValidates Existence GEMを使用してこれを確認する必要があります。

RSpec と Remarkable マッチャーを使用してこれらの関連付けをテストするには、次のようにします。

describe Task do
  it { should validate_presence_of :project_id }
  it { should validate_associated :project }
end
于 2012-07-04T12:49:39.300 に答える
4
validates :project, :associated => true  
validates :project_id, :presence => true

関連付けが存在することを確認したい場合は、関連付けられたオブジェクト自体ではなく、関連付けをマップするために使用される外部キーが存在するかどうかをテストする必要があります。 http://guides.rubyonrails.org/active_record_validations_callbacks.html

attr_accessible :project_id
于 2012-07-04T10:48:17.880 に答える
3

EDIT:関連付けがオプションではないと仮定して...

完全に検証するための唯一の方法は次のとおりです。

validates_associated :project
validates_presence_of :project_id, 
    :unless => Proc.new {|o| o.project.try(:new_record?)}
validates_presence_of :project, :if => Proc.new {|o| o.project_id}

最初の行は、関連付けられたプロジェクトが有効かどうかを検証します (存在する場合)。2 行目は、関連付けられたプロジェクトが存在し、新しいものでない限り、存在することを主張しますproject_id(新しいレコードの場合、まだ ID はありません)。3 行目は、ID が存在する場合、つまり、関連付けられたプロジェクトが既に保存されている場合に、プロジェクトが存在することを保証します。

project_id保存したプロジェクトを に割り当てると、ActiveRecord はタスクに を割り当てますproject。保存されていない/新しいプロジェクトを に割り当てると、空白のままprojectになります。project_idしたがって、それが存在することを確認したいのですproject_idが、保存されたプロジェクトを扱う場合のみです。これは、上記の 2 行目で実行されます。

逆に、project_id実際の Project を表す番号を に割り当てると、ActiveRecord はproject対応する Project オブジェクトを入力します。ただし、割り当てた ID が偽の場合はproject、nil のままになります。projectしたがって、上記の 3 行目で、 ifproject_idが満たされていることが保証されます。偽の ID を指定すると、これは失敗します。

これらの検証をテストする RSpec の例を参照してください: https://gist.github.com/kianw/5085085

于 2013-03-04T20:01:19.777 に答える
2

Joshua Muheim のソリューションは機能しますが、プロジェクトを次のような ID を持つタスクに単純にリンクできないのは嫌いです。

t = Task.new
t.project_id = 123 # Won't verify if it's valid or not.

だから私は代わりにこれを思いついた:

class Task < ActiveRecord:Base

    belongs_to :project

    validates :project_id, :presence => true
    validate :project_exists

    private
    def project_exists
        # Validation will pass if the project exists
        valid = Project.exists?(self.project_id)
        self.errors.add(:project, "doesn't exist.") unless valid
    end

end
于 2013-06-13T14:18:43.467 に答える