Установите переменную в application_controller и получите доступ к модели - PullRequest
0 голосов
/ 01 июля 2018

В моем Application Controller я установил переменную валюты на основе геолокации:

class ApplicationController < ActionController::Base

  before_action :currency

  protected

  def currency
    cookies[:country] ||= request.location.country
    case cookies[:country]
    when "MY"
      c = "MYR"
    when "SG"
      c = "SGD"
    else
      c = "USD"
    end
    @currency = Currency.find_by(name: c)
  end
end

У меня есть Модель продукта с методом цены и многими валютами, многими ценами, т. Е. Один продукт может иметь несколько валют с индивидуальной ценой.

class Product < ApplicationRecord
  has_many :prices
  has_many :currencies, through: :prices

  def price
    # how to access @currency?
  end

end

class Price < ApplicationRecord
  belongs_to :product
  belongs_to :currency
end

class Currency < ApplicationRecord
  has_many :prices
  has_many :products, through: :prices
end

Как лучше всего получить доступ к @currency в Model Product.price? Или как я могу сказать методу, чтобы он возвращал цену только в @currency? Вероятно, это не лучший способ справиться с этим, поэтому, пожалуйста, совет.

Ответы [ 3 ]

0 голосов
/ 01 июля 2018

У вас есть вещи немного задом наперед, поэтому вы пытаетесь решить не ту проблему. Модели не должны пытаться получить информацию из уровня контроллера, контроллер должен посылать эту информацию в модель:

class Product < ApplicationRecord
  #...
  def price_in(currency)
    # Access the associations however you need to and handle missing
    # information however fits your application in here...
  end
end

и затем в вашем контроллере или представлении:

price = product.price_in(@currency)

Вы должны иметь возможность вызывать методы на своих моделях из любого места (контроллеры, задачи rake, задания, консоль и т. Д.), Не беспокоясь обо всех состояниях, связанных с запросом.

0 голосов
/ 01 июля 2018

Ты не должен. Тем самым вы нарушаете множество принципов проектирования, и в будущем вы только разочаруетесь.

Ваша модель не должна заботиться о контексте вашего контроллера. Он должен заботиться только о данных, поскольку они относятся к себе.

Что вы можете сделать, тем не менее, это использовать ActiveModel::Attributes API.

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

class Product < ApplicationRecord
  has_many :prices
  has_many :currencies, through: :prices

  attribute :currency 

  def price
    self.currency 
  end

end

В вашем контроллере:

class ProductsController < ApplicationController
  def show
    @product = Product.find(params[:id])
    @product.currency = @currency 
  end 
end

С API ActiveModel::Attributes можно сделать гораздо больше, например, установить значения по умолчанию, выполнить проверки и даже установить, какой это тип объекта (логический / true / false, целое число, строка и т. Д.) - он ведет себя так же, как ваши обычные атрибуты в модели, они не поддерживаются вашей базой данных.

Подробнее об этом замечательном API https://apidock.com/rails/ActiveRecord/Attributes/ClassMethods/attribute

0 голосов
/ 01 июля 2018

Посмотрите на этот ответ для получения информации о том, как получить доступ к файлам cookie в модели. Но вы должны рассмотреть возможность перемещения этого метода из контроллера в класс Currency, который кажется более логичным для него. Затем вы можете вызвать метод из вашего класса Product как Currency.get_currency, например.

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