Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails “如何覆盖”;新";一种rails模型的构造方法_Ruby On Rails - Fatal编程技术网

Ruby on rails “如何覆盖”;新";一种rails模型的构造方法

Ruby on rails “如何覆盖”;新";一种rails模型的构造方法,ruby-on-rails,Ruby On Rails,在我的rails应用程序中,我有一个带有开始日期和结束日期的模型。如果用户选择2010年1月1日作为开始日期,选择2010年1月5日作为结束日期,我希望创建的模型有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.n

在我的rails应用程序中,我有一个带有开始日期和结束日期的模型。如果用户选择2010年1月1日作为开始日期,选择2010年1月5日作为结束日期,我希望创建的模型有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]) }

但是,我希望保持控制器的精简,并且我希望将模型逻辑保持在它之外。我猜我需要覆盖模型中的“新”方法。最好的方法是什么?

为什么不像这样在模型中创建一个方法呢

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

包含此逻辑(基本上是您的循环?

我想您想为模型属性设置默认值

还有另一种解决办法,而不是凌驾于一切之上;您可以设置回调:

class Model

before_create :default_values
def default_values
  ...
end
您可以使用:

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

虽然我在某个地方读到了不推荐使用的内容…

不要覆盖
初始化
它可能会破坏模型中的许多内容。如果我们知道您为什么需要这样做,我们可以提供更好的帮助(如果我们不完全理解您对表单是骨架的解释,您希望表单属性创建其他属性??请参见下文)。我经常按照马塞尔的建议用钩子。但是,如果您希望它一直发生,而不仅仅是在创建或保存对象之前,请使用
after\u initialize
hook

def after_initialize
  # Gets called right after Model.new
  # Do some stuff here
end
另外,如果您只是寻找一些默认值,您可以提供默认访问器,例如:(其中
some_属性
与模型属性的列名相对应)

还是作家

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

如果我正确理解了您的评论,那么您似乎公开了一个表单,该表单会使您的模型不完整,而其他属性基于该表单的某些部分?在这种情况下,您可以在初始化后使用上述任何方法
某些属性=
,然后在您的模型上创建其他属性。

这散发出工厂方法模式的气味…找到它

如果您出于某种原因不愿意使用create_date per@意大利面食,那么可能只创建一个简单的ruby对象(不支持ActiveRecord),名为YourModelFactory/Template/随便什么,带有两个实例变量-您可以使用标准参数[:foo]来分配它们-然后在该类上定义并调用一个返回真实对象的方法

控制器逻辑现在如下所示:

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

祝你好运。

正如@brad所说,你肯定不想覆盖初始化。虽然您可以在初始化后重写,但这看起来并不是您想要的。相反,您可能希望向类添加一个工厂方法,如@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

严格地说,尽管很晚,但在模型中覆盖的正确方法是

def initialize(args)
    #
    # do whatever, args are passed to super
    #
    super
end

我希望它出现在模型中,因为这就是创建它自己的逻辑所在,不是吗?我的模型只需要一个开始和结束日期,然后就可以创建自己的“实例”。(这个实例恰好是数据库表中的多行)所以我会按照我在回答中说的做。create_dates类方法,循环调用new inside。对不起,我需要更好地回答我的问题。但基本上,我只是想知道如何覆盖我的模型。新(属性)如果我是你,我不会这么做,但也许我错了。对答案感兴趣+1无论您希望模型的行为如何,您都不必覆盖新的。如果在模型中绝对有必要这样做,我会在创建前结合使用上述建议和
回调。然而,回调将需要一些额外的故障保护,以防止spanwed实例生成它们自己的实例。但那个表格只是一个框架,用来填充我模型的细节。该表单包含“开始”和“结束”点等详细信息。要创建完整的模型,需要填写起点和终点。我可以在控制器中执行此操作,但我认为这种类型的逻辑应该放在模型中。查看ActiveRecord::Base source()查看initialize方法,看看发生了什么,它从db中获取列,分配实例变量等,如果您覆盖此项,但不设置这些属性,无法保证活动的_记录会正常工作。请注意,在Rails 3.2.x中,
属性中的键是字符串,而不是符号。因此,您需要在上面的
属性[“some_attribute”]
。没有理由不覆盖初始化。相反,如果您查看rails源代码,就会明白initialize是要被重写的。你所需要做的就是在重写的初始化中调用super,但这是一条规则,所有ruby开发人员和rails开发人员都会默默地期待你这么做。ActiveRecord做了很多疯狂的事情,并且这个方法不能保证按你的预期运行。我同意这一点,现在他解释说他实际上想要创建多个模型,我认为工厂是合适的。我发现模型上的工厂作为类方法比单独的类做得更好。因此,def.make\u me\u things over MakeMeThings.new.我完全是def.make\u me\u things的+1-只是想让原创海报有一种模特的感觉。也许
**args
ans
super(args)
。我想在Rails中使用不同的默认模型,而不是传统应用程序在DB中的默认模型。
def initialize(args)
    #
    # do whatever, args are passed to super
    #
    super
end