2015-08-12 3 views
0

Я хотел бы реализовать проверку на стороне сервера для следующих целей: Подписки для определенной проводки могут быть созданы только в том случае, если количество подписчиков не превышает число мест для этого проводка.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 
+0

В настоящее время ваша проблема: 'Cposting.find_by (id: self.post_id)' this возвращает nil. и когда вы пытаетесь запустить 'spot_left' в классе nil. он дает вам нуль: ошибка класса Nil. Сначала подтвердите наличие 'self.post_id'? а затем также существует 'Cposting' для этого id – Athar

+0

Замена' self.post_id' на '1' также вызывает ошибку nil, а' Cposting.find_by (id: 1) 'возвращает допустимую запись в консоли. Поэтому я считаю, что проблема заключается в том, что метод find_by вызывается из другой модели, чем тот, который предлагается выполнить для поиска. – sso777

+0

попробуйте это и посмотрите, не дает ли он вам ошибки. 'Cposting.find_by_id (1) .try (: spot_left) .to_i> 0', если это будет работать.то мы хороши, что проверка будет работать нормально. иначе мы попытаемся отлаживать другой способ. – Athar

ответ

0

использование сделать из г отношений. Вам не нужно все раз спрашивать.

Попробуйте следующее:

class Cposting < ActiveRecord::Base 
    belongs_to :user 
    has_many :subscriptions, 
      foreign_key: "post_id", 
      dependent: :destroy 

    def spots_left 
    self.spots - self.subscriptions.count # i assume that spots is an integer db field 
    end 
end 

и

И создание подписки:

@cposting.build_subscription(subscriber: @customer2) 

Rails предлагает вам кучу методов, чтобы выбрать из. Вам даже не нужно работать с идентификаторами. Просто используйте отношения. В общем, я обнаружил, что Rails работает так плавно, когда вы придерживаетесь методов AR (было бы неплохо придерживаться правил рельсов при наименовании ваших таблиц) Пожалуйста, внимательно прочитайте this, это очень поможет вам.

0

Ошибка nil была исправлена ​​путем добавления проверки nil и ошибки, если тест не прошел.

validate :class_not_full 

def class_not_full #checks if there are spots left for the posting 
    errors.add(:post, "posting is already full") unless !post.nil? && post.spots > post.subscriptions.count 
end 
Смежные вопросы