Как переопределить «новый» метод для модели рельсов - PullRequest
8 голосов
/ 07 декабря 2010

В моем приложении rails у меня есть модель с start_date и end_date. Если пользователь выберет 1 января 2010 года в качестве даты начала и 5 января 2010 года в качестве даты окончания, я хочу создать 5 экземпляров моей модели (по одному на каждый выбранный день). Так это будет выглядеть примерно так:

Jan 1, 2010
Jan 2, 2010
Jan 3, 2010
Jan 4, 2010
Jan 5, 2010

Я знаю, что один из способов справиться с этим - сделать цикл в контроллере. Что-то вроде ...

# ...inside controller
start_date.upto(end_date) { my_model.new(params[:my_model]) }

Тем не менее, я хочу сохранить свой контроллер в скине, плюс хочу сохранить логику модели вне его. Я предполагаю, что мне нужно переопределить «новый» метод в модели. Какой лучший способ сделать это?

Ответы [ 7 ]

17 голосов
/ 07 декабря 2010

Как говорит @brad, вы определенно не хотите переопределять инициализацию. Хотя вы можете переопределить after_initialize, на самом деле это не похоже на то, что вы хотите. Вместо этого вы, вероятно, захотите добавить фабричный метод в класс, как предлагает @Pasta. Так что добавьте это к вашей модели:

def self.build_for_range(start_date, end_date, attributes={})
  start_date.upto(end_date).map { new(attributes) }
end

А затем добавьте это в свой контроллер:

models = MyModel.build_for_range(start_date, end_date, params[:my_model])
if models.all?(:valid?)
  models.each(&:save)
  # redirect the user somewhere ...
end
10 голосов
/ 07 декабря 2010

Не переопределяйте initialize Это может привести к поломке многих вещей в ваших моделях. Если бы мы знали, зачем вам нужно, мы могли бы помочь лучше (не до конца понимаете ваше объяснение формы как скелета, вам нужны атрибуты формы для создания других атрибутов - см. Ниже). Я часто использую крючок, как предложил Марсель. Но если вы хотите, чтобы это происходило постоянно, а не перед созданием или сохранением объекта, используйте хук after_initialize.

def after_initialize
  # Gets called right after Model.new
  # Do some stuff here
end

Также, если вы просто ищете некоторые значения по умолчанию, вы можете предоставить средства доступа по умолчанию, например: (где some_attribute соответствует имени столбца атрибута вашей модели)

def some_attribute
  attributes[:some_attribute] || "Some Default Value"
end

или писатель

def some_attribute=(something)
  attributes[:some_attribute] = something.with_some_changes
end

Если я правильно понимаю ваш комментарий, похоже, вы предоставляете форму, которая сделает вашу модель неполной, а другие атрибуты основаны на частях этой формы? В этом случае вы можете использовать любой из вышеперечисленных методов after_initialize или some_attribute=, чтобы затем создать другие атрибуты в вашей модели.

2 голосов
/ 19 сентября 2017

Строго, хотя и поздно, правильный способ переопределить новый в модели -

def initialize(args)
    #
    # do whatever, args are passed to super
    #
    super
end
2 голосов
/ 07 декабря 2010

Это пахнет фабричным методом Паттерном ... ищи его.

Если по какой-то причине вы не хотите использовать create_date для @Pasta, то, возможно, создайте просто простой объект ruby ​​(без поддержки ActiveRecord) с именем YourModelFactory / Template / Wh независимо от двух экземпляров vars - вы можете использоватьваши стандартные параметры [: foo] для их назначения - затем определите и вызовите метод для этого класса, который возвращает ваши реальные объекты.

Логика вашего контроллера теперь выглядит примерно так:

mmf  = MyModelFactory.new(params[:foo])
objs = mmf.create_real_deal_models

Удачи.

2 голосов
/ 07 декабря 2010

Вы можете использовать:

def initialize(attributes = nil)
  # do your stuff...
end

Хотя где-то я читал, что это не рекомендуется ...

2 голосов
/ 07 декабря 2010

Полагаю, вы хотите установить значения по умолчанию для атрибута модели?

Есть иное решение, кроме переопределения;Вы можете установить обратные вызовы:

class Model

before_create :default_values
def default_values
  ...
end
2 голосов
/ 07 декабря 2010

почему бы вам просто не создать метод в вашей модели, подобный этому

 def self.create_dates(params) 
   [...] 
  end

, содержащий эту логику (в основном ваш цикл?)

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