Robert Klemme
5/29/2008 2:06:00 PM
2008/5/29 John Butler <johnnybutler7@gmail.com>:
> Yes ive figured that out. Its proving a bit of pain especially with has
> many through relationships.
>
> For the above i have a company that has many employees through
> company_employees so what i basically want to do is.
>
> companyA has 2 employees "a", "b"
>
> companyB has 3 employees "a", "b", "c"
>
> Copy any employees from companyB that are not in companyA
> Delete all reference to employees from companyB
>
> So
>
> companyA will have 3 employees "a", "b", "c"
>
> companyB will have no employees
>
> Ive tried various tings as there are a lot of associations i need to
> copy over so im trying to create one method that will deal with this
> passing through the 2 objects and the relationship in dyn_method:
>
> dyn_method = 'employees'
> myarray = Array.new
> myarray = companyA.send(dyn_method) | company_b.send(dyn_method)
> companyA.send(dyn_method + '=',myarray)
>
> The below works as in it updates all the company_id links in the
> company_employees table with companyA's id so the employees are only
> linked to companyA and not referenced by companyB anymore. The
> duplicates causes an issue here though.
> dyn_method = 'company_employees'
> companyA.send(dyn_method + '=',companyB.send(dyn_method))
>
> Im still looking for the best solution for adding to a company which has
> no employees and then to a company that already has employees but
> ignoring the duplicates.
Here is one way with a slightly different setting: I used a Struct
generated class because that has attribute access similar to a Hash:
Parameters are
1. the symbol of the relationship
2. the other instance
3. an optional list of key fields, if missing the object is the key
irb(main):001:0> Company = Struct.new :rel_a, :rel_b do
irb(main):002:1* def merge(rel, from, keys = nil)
irb(main):003:2> from_r = from[rel]
irb(main):004:2> return if from_r.nil? || from_r.empty?
irb(main):005:2>
irb(main):006:2* tmp = ((self[rel] || []) + from_r).inject({}) do |h,o|
irb(main):007:3* k = keys ? keys.map {|k| o.send(k)} : o
irb(main):008:3> h[k] ||= o
irb(main):009:3> h
irb(main):010:3> end
irb(main):011:2>
irb(main):012:2* self[rel] = tmp.values
irb(main):013:2> from_r.clear
irb(main):014:2> end
irb(main):015:1> end
=> Company
irb(main):016:0> c1 = Company.new [1,2,3]
=> #<struct Company rel_a=[1, 2, 3], rel_b=nil>
irb(main):017:0> c2 = Company.new [2,3,4]
=> #<struct Company rel_a=[2, 3, 4], rel_b=nil>
irb(main):018:0> c1.merge :rel_a, c2
=> []
irb(main):019:0> c1
=> #<struct Company rel_a=[1, 2, 3, 4], rel_b=nil>
irb(main):020:0> c2
=> #<struct Company rel_a=[], rel_b=nil>
Now an example with key fields:
irb(main):021:0> Person = Struct.new :id, :name
=> Person
irb(main):022:0> c1 = Company.new [1,2,3].map {|i| Person.new i, "name #{i}"}
=> #<struct Company rel_a=[#<struct Person id=1, name="name 1">,
#<struct Person id=2, name="name 2">, #<struct Person i
d=3, name="name 3">], rel_b=nil>
irb(main):023:0> c2 = Company.new [2,3,4].map {|i| Person.new i, "name #{i}"}
=> #<struct Company rel_a=[#<struct Person id=2, name="name 2">,
#<struct Person id=3, name="name 3">, #<struct Person i
d=4, name="name 4">], rel_b=nil>
irb(main):024:0> c1.merge :rel_a, c2, [:id]
=> []
irb(main):025:0> c1
=> #<struct Company rel_a=[#<struct Person id=1, name="name 1">,
#<struct Person id=2, name="name 2">, #<struct Person i
d=3, name="name 3">, #<struct Person id=4, name="name 4">], rel_b=nil>
irb(main):026:0> c2
=> #<struct Company rel_a=[], rel_b=nil>
irb(main):027:0>
Kind regards
robert
--
use.inject do |as, often| as.you_can - without end