Я хотел бы реализовать проверку на стороне сервера для следующих целей: Подписки для определенной проводки могут быть созданы только в том случае, если количество подписчиков не превышает число мест для этого проводка.Rails поиск модели в методе другой модели
class Cposting < ActiveRecord::Base
belongs_to :user
has_many :subscriptions,
foreign_key: "post_id",
dependent: :destroy
...
def spots_left #returns the number of places left in this class
self.spots.to_i - Subscription.where(post_id: self.id).count.to_i
end
...
end
В модели подписки я попытался вызвать spots_left метод, чтобы определить, есть ли какое-либо пятно осталось на Cposting новый абонемент принадлежит.
class Subscription < ActiveRecord::Base
belongs_to :subscriber, class_name: "User"
belongs_to :post, class_name: "Cposting"
...
validate :class_not_full
def class_not_full
Cposting.find_by(id: self.post_id).spots_left > 0
end
end
Запуск тестов на модели подписки возвращается нулевую ошибку
NoMethodError: undefined method `spots_left' for nil:NilClass
Кажется, я не могу использовать find_by, найти или где методы указывают на это Cposting.
Я хотел бы знать, как ссылаться на Cposting, принадлежащее проверяемой подписке, или альтернативный способ реализации этой проверки.
Благодаря
EDIT добавляя тесты
require 'test_helper'
class SubscriptionTest < ActiveSupport::TestCase
def setup
@cposting = cpostings(:one) #has one spot
@customer = users(:customer)
@customer2 = users(:customer2)
@subscription = Subscription.new(post_id: @cposting.id, subscriber_id: @customer.id)
end
...
test "subscriptions cannot exceed spots" do
@subscription.save
assert @cposting.subscriptions.count == @cposting.spots
@subscription2 = Subscription.new(post_id: @cposting.id, subscriber_id: @customer2.id)
assert_not @subscription2.valid?
end
end
Запуск rake test TEST=test/models/subscription_test.rb
дает
1) Failure:
SubscriptionTest#test_subscriptions_cannot_exceed_spots [/~/test/models/subscription_test.rb:37]:
Expected true to be nil or false
5 runs, 7 assertions, 1 failures, 0 errors, 0 skips
EDIT 2 добавив метод создания
class SubscriptionsController < ApplicationController
def create
@posting = Cposting.find(params[:post_id])
current_user.subscriptions.create(post_id: @posting.id)
flash[:success] = "Subscribed!"
redirect_to subscriptions_path
end
end
В настоящее время ваша проблема: 'Cposting.find_by (id: self.post_id)' this возвращает nil. и когда вы пытаетесь запустить 'spot_left' в классе nil. он дает вам нуль: ошибка класса Nil. Сначала подтвердите наличие 'self.post_id'? а затем также существует 'Cposting' для этого id – Athar
Замена' self.post_id' на '1' также вызывает ошибку nil, а' Cposting.find_by (id: 1) 'возвращает допустимую запись в консоли. Поэтому я считаю, что проблема заключается в том, что метод find_by вызывается из другой модели, чем тот, который предлагается выполнить для поиска. – sso777
попробуйте это и посмотрите, не дает ли он вам ошибки. 'Cposting.find_by_id (1) .try (: spot_left) .to_i> 0', если это будет работать.то мы хороши, что проверка будет работать нормально. иначе мы попытаемся отлаживать другой способ. – Athar