2017-02-10 3 views
0

Я пытаюсь создать веб-API, который позволяет создавать FriendShip по электронной почте или по номеру phone_number.Rails web API throwing of error

class Api::FriendshipsController < Api::BaseController 

    respond_to :json 

    def create 
     friend = User.where("email = ? OR phone_number = ?", params[:emailOrPhone], params[:emailOrPhone]).first # create a friend by email or phone_number 
     if friend.valid? # check if the friend exists, if it does we create our new friendship 
      friendship = Friendship.new 
      friendship.user = current_user 
      friendship.friend = friend 
      if friendship.valid? # check if friendship is valid 
       friendship.save # if it is, we save and return a success JSON response 
       render json: {created: true}, status: 200 
      else # if it's not a valid friendship, we display a error JSON response 
       render json: {created: false}, status: 400 
      end 
     end 
    end 
end 

Вот моя FriendShip модель

class Friendship < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :friend, :class_name => "User" 

    validates_uniqueness_of :user_id, scope: :friend_id, :message => '%{friend_id} is already a friend' 

    validate :check_friend_and_user # prevent user trying to add him/herself as friend. 

    def check_friend_and_user 
     errors.add(:friend, "can't be the same as user") if user == friend 
    end 
end 

Всякий раз, когда уникальность Ограничить нарушается, ошибка missing interpolation argument :friend_id in "%{friend_id} is already a friend" ({:model=>"Friendship", :attribute=>"User", :value=>2} given) с кодом ошибки 500

Как мне сделать это не сгенерирует ошибку, но вместо того, чтобы перейти к вернуть ответ «fail json» с кодом состояния 400

Я хочу, чтобы вызывающий агент этого API знал, что они пытаются добавить кого-то, кто уже является другом. Получение кода состояния 500 и куча html, похоже, однозначно не идентифицируют его. Поэтому я хотел бы выслать ошибку в виде JSON и статус 200

ответ

1

Что вы пытаетесь сделать, это определить, связан ли друг с пользователем через класс дружбы. Который вы можете упростить с помощью ассоциации has_many: friendships на объекте User.

Кроме того, способ, которым вы смотрите по электронной почте или телефону, является ИМО излишне двусмысленным и будет проблематичным, если вы хотите отдельно отслеживать один или другой для других целей. Которое вы, похоже, хотите сделать, так как вы их разбили на отдельные столбцы базы данных. Я думаю, вы могли бы просто ввести два входа в форму электронной почты или номер телефона и только передать один на контроллер. Если у вас должен быть только один, вы можете определить, что форма представляет в Javascript или что-то в этом роде.

В этом случае вам лучше отправить тип идентификатора с вашими исходными данными из вашей формы, чтобы вы могли искать тот или иной. Таким образом, ваша форма явно отправит идентификатор поиска столбца, например. что PARAMS будет эквивалентно рубинового хэш

{friendship: {email: "[email protected]"}}

С, что в Params, то вы могли бы делать то, что вы пытаетесь с этим кодом

# assuming you're passing via a params hash that would look like  
# one or the other of the following 
# {friendship: {email: "[email protected]"}} 
# {friendship: {phone_number: "123-123-1234"}} 
def create 
    if current_user.friendships.find_or_create_by(friendship_params) 
    render json: {created: true}, status: 200 
    else # if it's not a valid friendship, we display a error JSON response 
    render json: {created: false}, status: 400 
    end 
end 

protected 


def friendship_params 
    require(:friendship).permit(:email, :phone_number) 
end