具有AR枚举范围的HABTM

时间:2015-07-28 21:47:38

标签: ruby-on-rails activerecord enums associations

如何使用与AR枚举范围定义的同一模型的记录子集关联的模型?

我认为以下内容会起作用,但事实并非如此。我愿意使用<script> $(document).ajaxComplete(function(){ var d1 = [[1, 300], [2, 600], [3, 550], [4, 400], [5, 300]]; var options = { xaxis: { show: true, position: "bottom", min: 0, max: 6, mode: null, tickSize: 1, axisLabel: 'Month', axisLabelUseCanvas: true, axisLabelFontSizePixels: 12, axisLabelFontFamily: 'Verdana, Arial, Helvetica, Tahoma, sans-serif', // axisLabelPadding: 5 }, yaxis: { show: true, axisLabel: 'Temperature (C)', axisLabelUseCanvas: true, axisLabelFontSizePixels: 12, axisLabelFontFamily: 'Verdana, Arial, Helvetica, Tahoma, sans-serif', axisLabelPadding: 5 }, series: { lines: { show: true, fill: true, fillColor: { colors: [{ opacity: 0.7 }, { opacity: 0.1}] } }, points:{ show: true, radius: 3 } }, grid: { borderWidth: 0, labelMargin:10, hoverable: true, clickable: true, mouseActiveRadius:6, }, colors: ["#FF7070", "#0022FF"], legend: { show: true }, }; if ($("#line-chart")[0]) { $.plot($("#line-chart"), [d1], options); } }); </script> ,如果它会简化一些事情,但现在似乎有点矫枉过正。

<DataGrid>
    <DataGrid.Columns>
        <DataGridComboBoxColumn ItemsSource="{Binding options, RelativeSource={RelativeSource AncestorType=DataGrid}"
                        DisplayMemberPath="Name"
                        SelectedValuePath="ID"
                        SelectedValueBinding="{Binding selectedOption}" />
    </DataGrid.Columns>
</DataGrid>

更正建议的版本会出现语法错误;

has_many :through

错误:

class User < ActiveRecord::Base
  enum role: [:doctor, :patient, :clinician]
  has_and_belongs_to_many :doctors, &:doctor?, class_name: "User"
end

使用class User < ActiveRecord::Base enum role: [:doctor, :patient, :clinician] has_and_belongs_to_many :doctors, &:doctor, class_name: "User" end 语法有效,但我想知道SyntaxError: ~/m2/app/models/user.rb:3: syntax error, unexpected ',', expecting keyword_end has_and_belongs_to_many :doctors, &:doctor, class_name: "User" ^ 语法错误的原因。

好的,请看下面为什么->{doctor}语法错误,显然:doctor.to_proc技巧不起作用,因为to_proc将当前对象绑定到proc,而它应该传入proc,这意味着在这种情况下确实需要&&

1 个答案:

答案 0 :(得分:1)

问题是scope proc在类上下文中被评估(从技术上讲,关系上下文是从模型继承类方法)。例如,来自docs for has_and_belongs_to_many

has_and_belongs_to_many :projects, -> { includes :milestones, :manager }

使用此代码,调用SomeModel.projects将等同于调用SomeModel.projects.includes(:milestones, :manager)。现在,这是你的代码:

has_and_belongs_to_many :doctors, &:doctor?, class_name: "User"

使用此代码,调用User.doctors将等同于调用User.doctors.doctor?,这不起作用,因为doctor?是User上的实例方法,而不是类方法。

对于解决方案,我们只需要检查docs for enum。这个例子就在底部:

  

在极少数情况下,您可能需要直接访问映射。映射通过具有复数属性名称的类方法公开:

Conversation.statuses # => { "active" => 0, "archived" => 1 }
     

当您需要知道枚举的序数值时使用该类方法:

Conversation.where("status <> ?", Conversation.statuses[:archived])
     

枚举属性的条件必须使用枚举的序数值。

由于Rails自动为枚举创建范围,例如User.doctor,我们实际上可以做得更好:

has_and_belongs_to_many :doctors, ->{ doctor }, class_name: "User"

您可能会试图将其缩短为以下内容:

has_and_belongs_to_many :doctors, &:doctor, class_name: "User"

...但正如您已经发现的,这会给您一个SyntaxError。原因是&运算符告诉Ruby将给定对象转换为块并将其用作方法的块参数。如果对象不是proc(如:doctor),则首先调用其to_proc方法,这就是为什么[1,2].reduce(&:+)有效。但是块必须始终是最后一个参数(并且只能有一个),因此当您在&:doctor之后放置另一个参数时会出现语法错误。

然而,你可以这样做:

has_and_belongs_to_many :doctors, :doctor.to_proc,
                        class_name: "User"

......但我认为你并没有真正获得任何东西。