Ruby on rails 无法将datetime\u select与Mongoid一起使用
每次我尝试在视图中使用Datetime_select时,应用程序都会抛出一个属性错误Ruby on rails 无法将datetime\u select与Mongoid一起使用,ruby-on-rails,ruby,mongodb,mongoid,Ruby On Rails,Ruby,Mongodb,Mongoid,每次我尝试在视图中使用Datetime_select时,应用程序都会抛出一个属性错误 Mongoid::Errors::UnknownAttribute: Problem: Attempted to set a value for 'fromtime(1i)' which is not allowed on the model Event. Summary: Without including Mongoid::Attributes::Dynamic in yo
Mongoid::Errors::UnknownAttribute:
Problem:
Attempted to set a value for 'fromtime(1i)' which is not allowed on the model Event.
Summary:
Without including Mongoid::Attributes::Dynamic in your model and the attribute does not already exist in the attributes hash, attempting to call Event#fromtime(1i)= for it is not allowed. This is also triggered by passing the attribute to any method that accepts an attributes hash, and is raised instead of getting a NoMethodError.
Resolution:
You can include Mongoid::Attributes::Dynamic if you expect to be writing values for undefined fields often.
我经常遇到的解决方案是在模型中包含Mongoid::multiparametertributes。不幸的是,该模块已被删除
我已经尝试过分叉gem并重新添加multiparametertributes模块,但是gem不会从lib文件中读取代码。有没有办法将DateTime\u select与Mongoid一起使用?
您需要在Mongoid模型中包含include Mongoid::multiparametertattributes
看
我在任何地方都找不到具体的文档记录~
那会教我读书不好的 不幸的是,多参数分配是ActiveRecord中的一种实现,而不是ActiveModel。因此,Mongoid必须有自己的实现,但他们放弃了对该特性的支持,让ActiveSupport和ActiveModel来弥补不足。好吧,看看Rails源代码,它仍然保存在ActiveRecord中 幸运的是,您可以在process_attributes方法中挂接自己的实现,该方法在Mongoid对象上分配属性时调用,例如在创建或更新操作期间 要进行测试,只需创建一个config/initializer/multi_parameter_attributes.rb,并添加下面的代码,将必要的功能添加到Mongoid::Document模块中:
module Mongoid
module MultiParameterAttributes
module Errors
class AttributeAssignmentError < Mongoid::Errors::MongoidError
attr_reader :exception, :attribute
def initialize(message, exception, attribute)
@exception = exception
@attribute = attribute
@message = message
end
end
class MultiparameterAssignmentErrors < Mongoid::Errors::MongoidError
attr_reader :errors
def initialize(errors)
@errors = errors
end
end
end
def process_attributes(attrs = nil)
if attrs
errors = []
attributes = attrs.class.new
attributes.permit! if attrs.respond_to?(:permitted?) && attrs.permitted?
multi_parameter_attributes = {}
attrs.each_pair do |key, value|
if key =~ /\A([^\(]+)\((\d+)([if])\)$/
key, index = $1, $2.to_i
(multi_parameter_attributes[key] ||= {})[index] = value.empty? ? nil : value.send("to_#{$3}")
else
attributes[key] = value
end
end
multi_parameter_attributes.each_pair do |key, values|
begin
values = (values.keys.min..values.keys.max).map { |i| values[i] }
field = self.class.fields[database_field_name(key)]
attributes[key] = instantiate_object(field, values)
rescue => e
errors << Errors::AttributeAssignmentError.new(
"error on assignment #{values.inspect} to #{key}", e, key
)
end
end
unless errors.empty?
raise Errors::MultiparameterAssignmentErrors.new(errors),
"#{errors.size} error(s) on assignment of multiparameter attributes"
end
super attributes
else
super
end
end
protected
def instantiate_object(field, values_with_empty_parameters)
return nil if values_with_empty_parameters.all? { |v| v.nil? }
values = values_with_empty_parameters.collect { |v| v.nil? ? 1 : v }
klass = field.type
if klass == DateTime || klass == Date || klass == Time
field.mongoize(values)
elsif klass
klass.new(*values)
else
values
end
end
end
module Document
include MultiParameterAttributes
end
end
因此,我们正在迭代属性散列,以便将数据结构构建为多参数属性:
attrs.each_pair do |key, value|
...
end
记住我们在正则表达式中使用了捕获组。稍后,我们可以使用Ruby的$1、$2等全局变量来引用捕获的组。key是属性的名称,例如starttime。index是指datetime中属性的一部分,例如年、月、日等,而$3保存第三个捕获组中的i,因为我们希望获取字符串值并将其转换为整数:
key, index = $1, $2.to_i
(multi_parameter_attributes[key] ||= {})[index] = value.empty? ? nil : value.send("to_#{$3}")
最终,我们得到了如下良好的数据结构:
{ starttime: { 1 => 2019, 2 => 6, 3 => 28, 4 => 19, 5 => 18 } }
现在我们做一些智能的事情来获取实际的日期部分:
values = (values.keys.min..values.keys.max).map { |i| values[i] }
这将使我们:
[2019, 6, 28, 19, 18]
好吧,现在我们有了我们想要的日期。其余部分是使用Mongoid API生成一个字段对象来存储日期。能否提供有关数据结构以及如何访问数据的更多信息?
[2019, 6, 28, 19, 18]