Доступ к current_user из моделей Rails? - PullRequest
2 голосов
/ 22 февраля 2012

Я создаю приложение для выставления счетов, которое в основном следует следующему шаблону:

Users < Clients < Projects < Invoices

Теперь, чтобы сгенерировать автоинкрементные номера счетов для каждого пользователя, я поместил его в свой Invoiceмодель:

  before_create :create_invoice_number

  def create_invoice_number
    val = @current_user.invoices.maximum(:number)
    self.number = val + 1
  end

Однако кажется, что переменная current_user не может быть доступна из моделей в Rails?

Что я могу сделать, чтобы решить эту проблему?

Ответы [ 2 ]

9 голосов
/ 22 февраля 2012

Это связано с разделением проблем в Rails и является довольно сложной проблемой.В парадигме Rails модели не должны знать о каком-либо состоянии приложения, кроме того, которое они передали напрямую, поэтому большинство кодировщиков Rails скажут вам, что любая модель, которой нужно знать о current_user, - это запах кода.

Это говоритЕсть три способа сделать это, каждый «более правильный» (или, по крайней мере, я бы их так считал).

Сначала попробуйте создать ассоциацию для пользователя внутри счета-фактуры и связать счет-фактуру с пользователем.в контроллере:

class InvoicesController < ApplicationController

...

def create
  @invoice = current_user.invoices.create(params[:invoice])
  ...
end

и в вашей модели:

belongs_to :user

def create_invoice_number
  self.user.invoices.maximum(:number) + 1
end

Если это не сработает, сделайте это вручную в контроллере.Это правда, что контроллеры всегда должны быть настолько тонкими, насколько вы можете управлять, но, поскольку это, очевидно, проблема уровня приложения, контроллер - это то место, куда нужно их поместить:

class InvoicesController < ApplicationController

...

def create
  @invoice = Invoice.create(params[:invoice])
  @invoice.update_attribute(:number, current_user.invoices.maximum(:number))
  ...
end

Наконец, если вы действительно, действительно хотитеЧтобы соединить контроллер и модель, вы можете сделать это с помощью ActionController :: Sweepers .Они не предназначены для этой цели, но, безусловно, выполнят работу за вас.

1 голос
/ 23 февраля 2012

не должно быть никаких подобных случаев, если вы хотите использовать observers в рельсах

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...