nanenj

Ruby things

Feb 25th, 2019
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.09 KB | None | 0 0
  1. class CreateOrders < ActiveRecord::Migration[5.2]
  2. def change
  3. create_table :orders do |t|
  4.  
  5. t.timestamps
  6. end
  7. end
  8. end
  9.  
  10. class CreateItems < ActiveRecord::Migration[5.2]
  11. def change
  12. create_table :items do |t|
  13.  
  14. t.timestamps
  15. end
  16. end
  17. end
  18.  
  19. class CreateAssemblies < ActiveRecord::Migration[5.2]
  20. def change
  21. create_table :assemblies do |t|
  22.  
  23. t.timestamps
  24. end
  25. end
  26. end
  27.  
  28. class CreateOrderItems < ActiveRecord::Migration[5.2]
  29. def change
  30. create_table :order_items do |t|
  31. t.references :order, foreign_key: true
  32. t.references :item, foreign_key: true
  33. t.references :assembly, foreign_key: true
  34.  
  35. t.timestamps
  36. end
  37. end
  38. end
  39.  
  40. class CreateAssemblyItems < ActiveRecord::Migration[5.2]
  41. def change
  42. create_table :assembly_items do |t|
  43. t.references :assembly, foreign_key: true
  44. t.references :item, foreign_key: true
  45.  
  46. t.timestamps
  47. end
  48. end
  49. end
  50.  
  51. class Assembly < ApplicationRecord
  52. has_many :orders, through: :order_items
  53. has_many :assembly_items
  54. has_many :assemblies, through: :assembly_items
  55. has_many :items, through: :assembly_items
  56. end
  57.  
  58. class AssemblyItem < ApplicationRecord
  59. belongs_to :assembly
  60. belongs_to :item
  61. end
  62.  
  63. class Item < ApplicationRecord
  64. has_many :orders, through: :order_items
  65. has_many :assemblies, through: :assembly_items
  66. end
  67.  
  68. class Order < ApplicationRecord
  69. has_many :order_items
  70. has_many :assemblies, through: :order_items
  71. has_many :items, through: :assemblies
  72. end
  73.  
  74. class OrderItem < ApplicationRecord
  75. belongs_to :order
  76. belongs_to :item
  77. belongs_to :assembly
  78. end
  79.  
  80. Running via Spring preloader in process 23837
  81. Loading development environment (Rails 5.2.2)
  82.  
  83. irb(main):001:0> o = Order.first
  84. Order Load (0.3ms) SELECT "orders".* FROM "orders" ORDER BY "orders"."id" ASC LIMIT $1 [["LIMIT", 1]]
  85. => #<Order id: 1, created_at: "2019-02-25 17:26:00", updated_at: "2019-02-25 17:26:00">
  86. irb(main):002:0> a = Assembly.first
  87. Assembly Load (0.3ms) SELECT "assemblies".* FROM "assemblies" ORDER BY "assemblies"."id" ASC LIMIT $1 [["LIMIT", 1]]
  88. => #<Assembly id: 1, created_at: "2019-02-25 17:26:35", updated_at: "2019-02-25 17:26:35">
  89. irb(main):003:0> i = Item.first
  90. Item Load (0.4ms) SELECT "items".* FROM "items" ORDER BY "items"."id" ASC LIMIT $1 [["LIMIT", 1]]
  91. => #<Item id: 1, created_at: "2019-02-25 17:26:27", updated_at: "2019-02-25 17:26:27">
  92.  
  93. irb(main):004:0> o.assemblies
  94. Assembly Load (0.7ms) SELECT "assemblies".* FROM "assemblies" INNER JOIN "order_items" ON "assemblies"."id" = "order_items"."assembly_id" WHERE "order_items"."order_id" = $1 LIMIT $2 [["order_id", 1], ["LIMIT", 11]]
  95. => #<ActiveRecord::Associations::CollectionProxy [#<Assembly id: 1, created_at: "2019-02-25 17:26:35", updated_at: "2019-02-25 17:26:35">]>
  96.  
  97. irb(main):005:0> o.items
  98. Item Load (1.4ms) SELECT "items".* FROM "items" INNER JOIN "assembly_items" ON "items"."id" = "assembly_items"."item_id" INNER JOIN "assemblies" ON "assembly_items"."assembly_id" = "assemblies"."id" INNER JOIN "order_items" ON "assemblies"."id" = "order_items"."assembly_id" WHERE "order_items"."order_id" = $1 LIMIT $2 [["order_id", 1], ["LIMIT", 11]]
  99. => #<ActiveRecord::Associations::CollectionProxy [#<Item id: 1, created_at: "2019-02-25 17:26:27", updated_at: "2019-02-25 17:26:27">]>
  100.  
  101. irb(main):006:0> a.orders
  102. Order Load (0.3ms) SELECT "orders".* FROM "orders" INNER JOIN "order_items" ON "orders"."id" = "order_items"."order_id" WHERE "order_items"."assembly_id" = $1 LIMIT $2 [["assembly_id", 1], ["LIMIT", 11]]
  103. => #<ActiveRecord::Associations::CollectionProxy [#<Order id: 1, created_at: "2019-02-25 17:26:00", updated_at: "2019-02-25 17:26:00">]>
  104.  
  105. irb(main):007:0> a.assemblies
  106. Assembly Load (0.3ms) SELECT "assemblies".* FROM "assemblies" INNER JOIN "assembly_items" ON "assemblies"."id" = "assembly_items"."assembly_id" WHERE "assembly_items"."assembly_id" = $1 LIMIT $2 [["assembly_id", 1], ["LIMIT", 11]]
  107. => #<ActiveRecord::Associations::CollectionProxy [#<Assembly id: 1, created_at: "2019-02-25 17:26:35", updated_at: "2019-02-25 17:26:35">]>
  108.  
  109. irb(main):008:0> a.items
  110. Item Load (0.4ms) SELECT "items".* FROM "items" INNER JOIN "assembly_items" ON "items"."id" = "assembly_items"."item_id" WHERE "assembly_items"."assembly_id" = $1 LIMIT $2 [["assembly_id", 1], ["LIMIT", 11]]
  111. => #<ActiveRecord::Associations::CollectionProxy [#<Item id: 1, created_at: "2019-02-25 17:26:27", updated_at: "2019-02-25 17:26:27">]>
  112.  
  113. irb(main):009:0> i.orders
  114. Order Load (0.4ms) SELECT "orders".* FROM "orders" INNER JOIN "order_items" ON "orders"."id" = "order_items"."order_id" WHERE "order_items"."item_id" = $1 LIMIT $2 [["item_id", 1], ["LIMIT", 11]]
  115. => #<ActiveRecord::Associations::CollectionProxy [#<Order id: 1, created_at: "2019-02-25 17:26:00", updated_at: "2019-02-25 17:26:00">]>
  116.  
  117. irb(main):010:0> i.assemblies
  118. Assembly Load (0.4ms) SELECT "assemblies".* FROM "assemblies" INNER JOIN "assembly_items" ON "assemblies"."id" = "assembly_items"."assembly_id" WHERE "assembly_items"."item_id" = $1 LIMIT $2 [["item_id", 1], ["LIMIT", 11]]
  119. => #<ActiveRecord::Associations::CollectionProxy [#<Assembly id: 1, created_at: "2019-02-25 17:26:35", updated_at: "2019-02-25 17:26:35">]>
  120. irb(main):011:0>
  121.  
  122. Notice that all of these relations (presumably) work and operate as expeted.
  123.  
  124. However, when we try to use them in the way you described.
  125.  
  126. irb(main):011:0> o.items
  127. Item Load (0.9ms) SELECT "items".* FROM "items" INNER JOIN "assembly_items" ON "items"."id" = "assembly_items"."item_id" INNER JOIN "assemblies" ON "assembly_items"."assembly_id" = "assemblies"."id" INNER JOIN "order_items" ON "assemblies"."id" = "order_items"."assembly_id" WHERE "order_items"."order_id" = $1 LIMIT $2 [["order_id", 1], ["LIMIT", 11]]
  128. => #<ActiveRecord::Associations::CollectionProxy [#<Item id: 1, created_at: "2019-02-25 17:26:27", updated_at: "2019-02-25 17:26:27">]>
  129. irb(main):012:0> assemblies = o.assemblies
  130. Assembly Load (0.4ms) SELECT "assemblies".* FROM "assemblies" INNER JOIN "order_items" ON "assemblies"."id" = "order_items"."assembly_id" WHERE "order_items"."order_id" = $1 LIMIT $2 [["order_id", 1], ["LIMIT", 11]]
  131. => #<ActiveRecord::Associations::CollectionProxy [#<Assembly id: 1, created_at: "2019-02-25 17:26:35", updated_at: "2019-02-25 17:26:35">]>
  132. irb(main):013:0> assemblies.items
  133. Traceback (most recent call last):
  134. 1: from (irb):13
  135. Assembly Load (0.6ms) SELECT "assemblies".* FROM "assemblies" INNER JOIN "order_items" ON "assemblies"."id" = "order_items"."assembly_id" WHERE "order_items"."order_id" = $1 LIMIT $2 [["order_id", 1], ["LIMIT", 11]]
  136. NoMethodError (undefined method `items' for #<Assembly::ActiveRecord_Associations_CollectionProxy:0x00007f921ec785a0>)
  137. irb(main):014:0>
  138.  
  139. We get that error because assemblies isn't actually a single thing, so we can't call items on it directly.
  140.  
  141. irb(main):017:0> assemblies.map { |assembly|
  142. irb(main):018:1* assembly.items
  143. irb(main):019:1> }
  144. Item Load (0.5ms) SELECT "items".* FROM "items" INNER JOIN "assembly_items" ON "items"."id" = "assembly_items"."item_id" WHERE "assembly_items"."assembly_id" = $1 LIMIT $2 [["assembly_id", 1], ["LIMIT", 11]]
  145. => [#<ActiveRecord::Associations::CollectionProxy [#<Item id: 1, created_at: "2019-02-25 17:26:27", updated_at: "2019-02-25 17:26:27">]>]
  146. irb(main):020:0>
  147.  
  148. In that way, we can iterate over each of the assemblies and return a value. Much like your later comment suggest where it's assemblies.each. While my models do not have a name, we can pretend we wanted a specific data structure.
  149.  
  150. irb(main):017:0> assemblies.map { |assembly|
  151. irb(main):018:1* assembly.items
  152. irb(main):019:1> }
  153. Item Load (0.5ms) SELECT "items".* FROM "items" INNER JOIN "assembly_items" ON "items"."id" = "assembly_items"."item_id" WHERE "assembly_items"."assembly_id" = $1 LIMIT $2 [["assembly_id", 1], ["LIMIT", 11]]
  154. => [#<ActiveRecord::Associations::CollectionProxy [#<Item id: 1, created_at: "2019-02-25 17:26:27", updated_at: "2019-02-25 17:26:27">]>]
  155. irb(main):020:0>
  156.  
  157. So, you could alternatively, define a method that does the above on order, however, while I may not have the exact API you desired, if I were to create another assembly, item, order_item, and assembly_item, I can achieve...
  158.  
  159. irb(main):058:0> o.items
  160. Item Load (0.8ms) SELECT "items".* FROM "items" INNER JOIN "assembly_items" ON "items"."id" = "assembly_items"."item_id" INNER JOIN "assemblies" ON "assembly_items"."assembly_id" = "assemblies"."id" INNER JOIN "order_items" ON "assemblies"."id" = "order_items"."assembly_id" WHERE "order_items"."order_id" = $1 LIMIT $2 [["order_id", 1], ["LIMIT", 11]]
  161. => #<ActiveRecord::Associations::CollectionProxy [#<Item id: 1, created_at: "2019-02-25 17:26:27", updated_at: "2019-02-25 17:26:27">, #<Item id: 2, created_at: "2019-02-25 18:03:06", updated_at: "2019-02-25 18:03:06">]>
  162. irb(main):059:0>
  163.  
  164. However, you can also achieve what you're after by using a scope.
  165.  
  166. If you add the scope:
  167.  
  168. scope :items, -> { AssemblyItem.where(assembly_id: self.ids).map { |ai|
  169. ai.item
  170. }}
  171.  
  172. to your Assembly model, you should be able to do the following...
  173.  
  174. irb(main):031:0> o = Order.first
  175. Order Load (0.3ms) SELECT "orders".* FROM "orders" ORDER BY "orders"."id" ASC LIMIT $1 [["LIMIT", 1]]
  176. => #<Order id: 1, created_at: "2019-02-25 17:26:00", updated_at: "2019-02-25 17:26:00">
  177. irb(main):032:0> o.assemblies.items
  178. (0.3ms) SELECT "assemblies"."id" FROM "assemblies" INNER JOIN "order_items" ON "assemblies"."id" = "order_items"."assembly_id" WHERE "order_items"."order_id" = $1 [["order_id", 1]]
  179. AssemblyItem Load (0.3ms) SELECT "assembly_items".* FROM "assembly_items" WHERE "assembly_items"."assembly_id" IN ($1, $2) [["assembly_id", 1], ["assembly_id", 2]]
  180. Item Load (3.3ms) SELECT "items".* FROM "items" WHERE "items"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
  181. Item Load (0.3ms) SELECT "items".* FROM "items" WHERE "items"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
  182. => [#<Item id: 1, created_at: "2019-02-25 17:26:27", updated_at: "2019-02-25 17:26:27">, #<Item id: 2, created_at: "2019-02-25 18:03:06", updated_at: "2019-02-25 18:03:06">]
  183. irb(main):033:0>
Add Comment
Please, Sign In to add comment