Hi,
I have three Models
User, Group and File.
User habtm group
Group habtm File
How can I find all that files that a particular user has access to?
eg user.groups.files ?
Hi,
I have three Models
User, Group and File.
User habtm group
Group habtm File
How can I find all that files that a particular user has access to?
eg user.groups.files ?
On May 31, 2006, at 12:28, Daniel wrote:
eg user.groups.files ?
The Rails-specific list (http://lists.rubyonrails.org/mailman/
listinfo/rails) and wiki and things may give you a better answer
(particularly in terms of things like query optimisation) than you’ll
get here, but…
user.groups is an array, it’s not the array which has a file
attribute, but each individual group in it, so maybe something like
this:
class User
def files
self.groups.inject([]) { |arr, group| arr + group.files }
end
end
matt smillie.
On Wednesday 31 May 2006 5:28 am, Daniel wrote:
I have three Models
User, Group and File.
User habtm group
Group habtm FileHow can I find all that files that a particular user has access to?
eg user.groups.files ?
Step back from the problem a step. Forget that you are working with
models or
that you are dealing with habtm relationships in Rails.
user.groups returns an array. And each of the elements in that array,
if you
call files() on it, returns another array.
So all you are really looking at here is a requirement to iterate over
an
array of arrays, creating a set consisting of each of the unique values
from
those arrays. Strip all the Rails stuff away, and it’s just a simple
data
problem.
So, create a simple surrogate to think about:
a = [[1,2,3],
[2,3,4],
[3,4,5],
[4,5,6],
[5,6,7],
[6,7,8]]
That’s just an array of arrays. Arrays in Ruby provide some handy
methods for
treating them like sets. And what you want is the union of all of your
sets.
With an array, | performs a union operation. So:
[1.,2,3] | [2,3,4]
returns
[1,2,3,4]
So all that you need to do now is iterate through your array applying
each sub
array to a common array with the union operator.
arr = []
a.each {|elem| arr = arr | elem}
That works. You get:
[1,2,3,4,5,6,7,8]
FYI, Ruby also provides a method, inject(), that is perfect for this
kind of
operation. So, the above code can be rewritten like so:
a.inject([]) {|arr,elem| arr | elem}
inject() just takes a starting value and a block. The arguments to the
block
are an accumulator variable, which is initialized to the starting value
passed to inject, and each successive element of the array inject it
iterating over. The code in the block is evaluated and the result of
the
code is inserted into the accumulator variable. When all values of the
array
have been iterated over, inject() returns the final value of the
accumulator.
It’s the loop for code that needs to accumulate values.
Anyway, that’s the way to solve the problem with an arbitrary set of
arrays.
So, now just apply it to your model.
Something like this, probably:
class User
def files
groups.inject([]) {|all_files, some_files| all_files | some_files}
end
end
Hope this helps,
Kirk H.
-----Original Message-----
From: Kirk H. [mailto:[email protected]]
[…nice breakdown…]
a.inject([]) {|arr,elem| arr | elem}
a.flatten.uniq ?
[…]
Something like this, probably:class User
def files
groups.inject([]) {|all_files, some_files| all_files |
some_files}
end
end
Should be equivalent to:
groups.flatten.uniq
But does probably not work because (as you explained)
“…And each of the elements in that array, if you
call files() on it, returns another array”
class User
def files
groups.inject([]) {|all_files, group| all_files | group.files}
end
end
Hope this helps,
Kirk H.
cheers
Simon
class User
def files
groups.inject([]) {|all_files, group| all_files | group.files}
end
endDoh! Yeah. I goofed. Thanks.
Kirk H.
We all do that - from time to time
As Rails implements Symbol#to_proc one should be able to do
myuser.groups.map(&:files).flatten.uniq
but that is getting esotheric.
cheers
Simon
On Wednesday 31 May 2006 7:23 am, Kroeger, Simon (ext) wrote:
Should be equivalent to:
groups.inject([]) {|all_files, group| all_files | group.files}
end
end
Doh! Yeah. I goofed. Thanks.
Kirk H.
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.
Sponsor our Newsletter | Privacy Policy | Terms of Service | Remote Ruby Jobs