【问题标题】:Rails API - accessing methods located in a model?Rails API - 访问模型中的方法?
【发布时间】:2020-07-12 03:30:24
【问题描述】:

我在 Rails 中构建了一个一次性的 Web 应用程序来测试一些新概念。在此过程中,我创建了属于模型的方法,以保持控制器轻巧简单的原则。

但是,现在我正在测试同一个应用程序,但通过 Rails API。我还能在模型中保留这些方法吗?

  1. 我不确定如何路由 API 以访问这些方法。
  2. 因为它涉及一个嵌套模型(通过用户联系),我不知道从哪里开始,甚至将它放入控制器中。我可以为嵌套模型制作控制器吗?

这是一个用户模型,可以让您了解我在说什么。大多数方法对于添加/接受和创建联系人的过程都是必不可少的。

class User < ApplicationRecord

  has_many :contactships, dependent: :destroy
  has_many :contacts, -> { where contactships: { status: :accepted }}, through: :contactships
  has_many :requested_contacts, -> { where contactships: { status: :requested }}, through: :contactships, source: :contact
  has_many :pending_contacts, -> { where contactships: { status: :pending }}, through: :contactships, source: :contact
  has_many :blocked_contacts, -> { where contactships: { status: :blocked }}, through: :contactships, source: :contact

  has_many :contactships_inverse, class_name: 'Contactship', foreign_key: :contact_id
  has_many :contacts_inverse, through: :contactships_inverse, source: :user

  has_one_attached :avatar

  validates_presence_of :first_name, :last_name

  def full_name
    "#{first_name} #{last_name}"
  end

  def all_contacts
    contacts + contacts_inverse
  end

  def has_contactship?(contact)
      #return true if the user is a contact
      return true if self == contact
      contactships.map(&:contact_id).include?(contact.id)
  end

  def requested_contacts_with?(contact)
      return false if self == contact
      #we are going to map requested contacts with list of users to see if they include contact_id
      requested_contacts.map(&:id).include?(contact.id)
  end

  def pending_contacts_with?(contact)
      return false if self == contact
      pending_contacts.map(&:id).include?(contact.id)
  end

  def contacts_with?(contact)
      return false if self == contact
      contacts.map(&:id).include?(contact.id)
  end

  def contact_request(contact)
    #unless the contact is not equal to self and contactship does not already exist
    unless self == contact || Contactship.where(user: self, contact: contact).exists?
        #transaction means that if one fails they both are rolled back
        transaction do
            #for user to another user (sent request)
            Contactship.create(user: self, contact: contact, status: :pending)
            #from another user to user (recieve request)
            Contactship.create(user: contact, contact: self, status: :requested)
        end
     end
  end

  def accept_request(contact)
      transaction do
        Contactship.find_by(user: self, contact: contact, status: [:requested])&.accepted!
        Contactship.find_by(user: contact, contact: self, status: [:pending])&.accepted!
      end
  end

  def reject_request(contact)
      transaction do
        Contactship.find_by(user: self, contact: contact)&.destroy!
        Contactship.find_by(user: contact, contact: self)&.destroy!
      end
  end

end

谢谢!

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    您需要创建对控制器的调用。让我们考虑下面的例子。

    class UsersController < ApplicationController
    
      def method_name
        @user = User.find(params[:id])
        # Now you can access all the user model methods using @user.model_method_name
        @user.all_contacts
      end
    
    end
    

    您需要在routes.rb中为这个控制器定义routes

    您在user 模型中创建了instance methods。你可以通过user的实例来访问它们

    【讨论】:

    • 当然,控制器本身不是模型,应该叫什么? contactships_controller?
    • 因为你已经在用户模型中添加了方法。您应该从用户控制器调用它们,但这不是强制性的。您可以在任何控制器中创建 User 的实例,并可以访问该控制器中的所有方法
    • 无需移动模型方法,只需在任意控制器中创建用户实例,即可访问所有模型实例方法。
    • 您在模型文件中定义的任何公共方法都可用于整个代码库中该模型的任何实例。
    • @JamesStirrat 不要挂断控制器的名称,您可以将其称为任何描述它正在做什么的名称。如果将它命名为 UsersController 让您感到麻烦,那么给它起一个您喜欢的名称,只要 config/routes.rb 正确指向控制器即可。有意义的描述比(弱)rails 命名约定更重要。有时我有多个控制器来控制单个模型,对应于不同的工作流程,这样做比重载单个控制器更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-07
    • 1970-01-01
    • 2023-03-21
    相关资源
    最近更新 更多