简体   繁体   English

has_many通过rails的所有记录

[英]all records of has_many through rails

I am a beginner to RoR and have been doing some coding recently myself using the guides. 我是RoR的初学者,最近我自己使用这些指南进行了一些编码。 I am currently stuck at a point and have done some googling around to find the reason, but with no luck. 我目前停留在某个位置,并做了一些谷歌搜索以查找原因,但是没有运气。 Can somebody please help me with this ? 有人可以帮我吗?

My scenario: 我的情况:

class Enum < ActiveRecord::Base
  establish_connection :common
  attr_accessible :name, :description, :updated_at
  has_many :enumlists
  has_many :enumvalues, :through => :enumlists
  validates :name, presence: true, length: { maximum:20}
  validates :description, length: {maximum: 100}
end

class Enumlist < ActiveRecord::Base
  establish_connection :common
  belongs_to :enums
  belongs_to :enumvalues
  attr_accessible :updated_at
end

class Enumvalue < ActiveRecord::Base
  establish_connection :common
  attr_accessible :category, :description, :updated_at
  has_many :enumlists
  has_many :enums, :through => :enumlists
end

and the migration entry is: 迁移条目为:

class CreateEnums < ActiveRecord::Migration
  def change
    create_table :enums do |t|
        t.string :name, :limit=>20
        t.string :description, :limit=>100
        t.timestamps
    end
    add_index :enums, [:name], :unique => true

    create_table :enumvalues do |t|
      t.string :category, :limit=>50
      t.string :description, :limit=>50
      t.timestamps
    end

    create_table :enumlists do |t|
        t.integer :enum_id
        t.integer :enumvalue_id
        t.timestamps
    end
    add_index :enumlists, [:enum_id, :enumvalue_id], :unique => true
  end
end

Now, i would like to view all the Enums with their values in the controller. 现在,我想在控制器中查看所有枚举及其值。 From the examples i have seen, i can do Enum.find(params[:id]).enumlists , however i dont find a way to get all the enums with the linked tables. 从我所看到的示例中,我可以执行Enum.find(params [:id])。enumlists ,但是我没有找到一种方法来获取所有带有链接表的枚举。 I'm obviously missing something simple here, but i'm unable to figure out what it is.. 我显然在这里缺少简单的东西,但是我无法弄清楚它是什么。

Thanks.. 谢谢..

Update: I can use @enums = Enum.includes(:enumlists) and it does return the correct entries, however i cannot get 1 level deeper.. ie @enums = Enum.includes(:enumlists, :enumvalues) and then use @enums.enumlists.enumvalues to get the list of all enumeration values. 更新:我可以使用@enums = Enum.includes(:enumlists)并返回正确的条目,但是我不能再深入1级。即@enums = Enum.includes(:enumlists,:enumvalues)然后使用@ enums.enumlists.enumvalues获取所有枚举值的列表。

To help, the data is structured as below:
Enums:
-----------------------------------------------------------------------------------
id           name              description
-----------------------------------------------------------------------------------
1            App1 OS            Operating systems for Application 1
2            App2 OS            Operating systems for Application 2

Enumvalues:
-----------------------------------------------------------------------------------
id           category              description
-----------------------------------------------------------------------------------
1            Operating Systems     AIX
2            Operating Systems     Linux
3            Operating Systems     Windows

Enumlists:
-----------------------------------------------------------------------------------
id           enum_id              enumvalue_id
-----------------------------------------------------------------------------------
1            1                    1
2            1                    2
3            2                    1

What i need in the output is:
enums = [ [1, [Operating Sysetms, AIX, Operating Systems, Linux], 2,[Operating Sysetms, AIX] ]

Update: 更新:

The following should work. 以下应该工作。

 @enums = Enum.includes({:enumlists => :enumvalues}) 

Note, the names enum_lists and enum_values would be more idiomatic Ruby 注意,名称enum_lists和enum_values会更惯用Ruby

@AlexBlakemore - Thanks. @AlexBlakemore-谢谢。 Your input made me believe that there was an issue in the model and once i found it, your method and the method i was using earlier both appear to be working fine.. 您的输入使我相信模型中存在问题,一旦找到问题,您的方法和我以前使用的方法都可以正常工作。

I think i found the reason for the failure. 我想我找到了失败的原因。 It was due to the class Enumlist which had an incorrect definition. 这是由于类Enumlist定义不正确。 It should have been 应该是

class Enumlist < ActiveRecord::Base
  establish_connection :common
  belongs_to :enum   <-- Renamed to enum instead of enums
  belongs_to :enumvalue <-- Renamed to enumvalue instead of enumvalues
  attr_accessible :updated_at
end

After making the above change, i tried using the following ways to link the tables and both of them work perfectly.. Method1: 进行上述更改之后,我尝试使用以下方式链接表,并且它们都可以正常工作。方法1:

@enums = Enum.includes(:enumlists, :enumvalues)
  [1m[36mEnum Load (0.4ms)[0m  [1mSELECT `enums`.* FROM `enums` [0m
  [1m[35mEnumlist Load (0.3ms)[0m  SELECT `enumlists`.* FROM `enumlists` WHERE `enumlists`.`enum_id` IN (1, 2)
  [1m[36mEnumvalue Load (0.3ms)[0m  [1mSELECT `enumvalues`.* FROM `enumvalues` WHERE `enumvalues`.`id` IN (1, 2)[0m
@enums = Enum.includes(:enumlists, :enumvalues)
[#<Enum id: 1, name: "WMB OS", description: "Operating System (WMB)", created_at: "2000-01-01 09:00:00", updated_at: "2000-01-01 09:00:00">, #<Enum id: 2, name: "4690 OS", description: "Operating System (DEC)", created_at: "2008-01-01 09:00:00", updated_at: "2008-01-01 09:00:00">]

Method2: Using the suggestion from @AlexBlakemore also i am getting a similar output. 方法2:使用@AlexBlakemore的建议,我也得到了类似的输出。

@enums = Enum.includes({:enumvalues=>:enumlists})
  [1m[36mEnum Load (0.2ms)[0m  [1mSELECT `enums`.* FROM `enums` [0m
  [1m[35mEnumlist Load (0.3ms)[0m  SELECT `enumlists`.* FROM `enumlists` WHERE `enumlists`.`enum_id` IN (1, 2)
[#<Enum id: 1, name: "WMB OS", description: "Operating System (WMB)", created_at: "2000-01-01 09:00:00", updated_at: "2000-01-01 09:00:00">, #<Enum id: 2, name: "4690 OS", description: "Operating System (DEC)", created_at: "2008-01-01 09:00:00", updated_at: "2008-01-01 09:00:00">]
  [1m[36mEnumvalue Load (0.6ms)[0m  [1mSELECT `enumvalues`.* FROM `enumvalues` WHERE `enumvalues`.`id` IN (1, 2)[0m
  [1m[35mEnumlist Load (0.4ms)[0m  SELECT `enumlists`.* FROM `enumlists` WHERE `enumlists`.`enumvalue_id` IN (1, 2)

There are no errors so clearly the list is getting populated by both methods. 没有错误,因此很明显,两种方法都填充了列表。 But when i try to access the enumlist/enumvalues, i get the a NoMethodError. 但是,当我尝试访问枚举列表/枚举值时,出现了NoMethodError。 I have tried various combinations, none worked.. 我尝试了各种组合,但均无效果。

@enums.enumlists
@enums.enumlist
@enums.enumvalues
@enums.enumvalue

Not sure what is missing in here.. Any suggestions please ?? 不知道这里缺少什么。 Once i get this to work, i can confirm which of the above two methods returns the correct result. 一旦我使它起作用,我就可以确认上述两种方法中的哪一种返回正确的结果。 Fingers crossed !! 手指交叉!

The following should tell ActiveRecord to eagerly fetch enumlists and enumvalues when fetching Enums. 下面的内容应该告诉ActiveRecord在获取枚举时急切地获取枚举和枚举。

@enums = Enum.includes({:enumlists => :enumvalues})

Note, the names enum_lists and enum_values would be more idiomatic Ruby 注意,名称enum_lists和enum_values会更惯用Ruby

or you could try just 或者你可以尝试

@enums = Enum.includes(:enumvalues)

if you really just mean to have a has_and_belongs_to_many association. 如果您真的只是想拥有has_and_belongs_to_many关联。 (HABTM) (HABTM)

Ok.. Here's the solution to the problem. 好的,这是解决问题的方法。

The first mistake was that the join table was linking the table names in singular form, due to which the join was broken. 第一个错误是联接表以单数形式链接表名,因此联接被破坏了。 Ie The table models should be as below. 即表模型应如下所示。 It contains 3 changes to my original model posted in the query. 它包含对查询中发布的原始模型的3个更改。 a. 一种。 Renamed the join table fields to use singular form. 重命名联接表字段以使用单数形式。 b. As suggested by @Alex, the original table names have been renamed to more idomatic ruby ctinteger is changed it to t.reference to make it explicit. 正如@Alex所建议的那样,原始表名已重命名为更多idomatic ruby​​ ctinteger,将其更改为t.reference以使其明确。

class Enum < ActiveRecord::Base
  establish_connection :common
  attr_accessible :name, :description, :updated_at
  has_many :enum_lists
  has_many :enum_values, :through => :enum_lists
  validates :name, presence: true, length: { maximum:20}
  validates :description, length: {maximum: 100}
end

class Enum_list < ActiveRecord::Base
  establish_connection :common
  belongs_to :enum   <-- Renamed to enum instead of enums
  belongs_to :enum_value <-- Renamed to enum_value instead of enum_values
  attr_accessible :updated_at
end

class Enum_value < ActiveRecord::Base
  establish_connection :common
  attr_accessible :category, :description, :updated_at
  has_many :enum_lists
  has_many :enums, :through => :enum_lists
end

The second issue was that i was trying to use find(:all) in the controller to get the results. 第二个问题是我试图在控制器中使用find(:all)来获取结果。 Instead it could easily be done using one of the below 相反,可以使用以下方法之一轻松完成此操作

@enums = Enum.includes(:enum_lists, :enum_values) or 
@enums = Enum.includes(:enum_values) or 
@enums = Enum.includes({:enum_lists => :enum_values}), 

bearing in mind the number of queries generated by each usage. 注意每种用法生成的查询数。

The last issue was that i couldn't print the values on ruby console by using @enums.enum_lists. 最后一个问题是我无法使用@ enums.enum_lists在ruby控制台上打印值。 This would rather need to be written within a loop to print the values. 宁愿需要在循环中编写代码以打印值。 Hence, i coded the following in my view to print the enumeration name and its corresponding values as: 因此,我在自己的视图中编写了以下代码,以将枚举名称及其对应的值打印为:

<% @enums.each do |enum| %>
<h4><%= enum.name %></h4>
<table width="100%">
  <tr class="<%= cycle('odd','even', :name=>"line") %>"><td>Description</td><td><%= enum.description %></td></tr>
  <table>
    <% enum.enum_values.each do |enum_value| %>
      <tr class="<%= cycle('odd','even', :name=>"line") %>"><td><%=  enum_value.category %></td><td><%=  enum_value.description %></td></tr>
    <% end %>
      <tr class="<%= cycle('odd','even', :name=>"line") %>"><td colspan="2"><span class="greyed">Last updated <%= time_ago_in_words(enum.updated_at) %> ago</span></td></tr>
  </table>
</table>

Thanks a lot to @Alex for his inputs.. !! 非常感谢@Alex的投入。 I can continue my work on RoR further !! 我可以继续我在RoR上的工作!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM