REcupero dati più associazioni Molti a molti

Ciao a tutti,

stavo facendo delle prove su alcune tabelle che ho nel DB.
Cerco di illustrare al meglio la situazione:

USER - ROLES - OPERATIONS

Un utente può avere più ruoli, un ruolo può fare più operazioni, quindi
in pratica 2 associazioni molti-a-molti.
In più nel db ho le relative tabelle diciamo di join, roles_users e
operations_roles.

Come posso recuperare tutte le operazioni di un determinato utente, che
appartiene ad un determinato ruolo?
Io ho fatto in un detemrinato modo ma nn mi sembra per niente elegante,
avete dei consigli?

GRAZIEE!!!

On Apr 24, 2008, at 3:59 PM, Alessandro Del coco wrote:

In più nel db ho le relative tabelle diciamo di join, roles_users e
operations_roles.

Come posso recuperare tutte le operazioni di un determinato utente,
che
appartiene ad un determinato ruolo?

Dato che non c’e’ legame diretto fra utenti e operazioni, direi che la
tua
domanda non ha molto senso… oppure non ti sei spiegato bene :slight_smile:

S.

Rapidissimo, a occhio non so se funziona, aggiungi ad User:
has_many :operations, :through => :roles

http://wiki.rubyonrails.org/rails/pages/Beginner+Howto+on+has_many+:through


blog: www.lucaguidi.com
Pro-Netics: www.pro-netics.com
Sourcesense - making sense of Open Source: www.sourcesense.com

On Apr 24, 2008, at 3:59 PM, Alessandro Del coco wrote:

In più nel db ho le relative tabelle diciamo di join, roles_users e
operations_roles.

Ah, quindi sono in relazione molti-a-molti… ecco cosa mi era sfuggito.

Come posso recuperare tutte le operazioni di un determinato utente,
che
appartiene ad un determinato ruolo?
Io ho fatto in un detemrinato modo ma nn mi sembra per niente
elegante,
avete dei consigli?

In teoria “has_many :operations, :through => :roles”, ma…

“You can only use a :through query through a belongs_to or has_many
association on the join model.”

S.

Spiego meglio la situazione:

  1. model USER

has_and_belongs_to_many :roles
attr_accessible :roles

2)model ROLE

has_and_belongs_to_many :operations
attr_accessible :operations

3)model OPERATION

has_and_belongs_to_many :roles
attr_accessible :roles

Premetto che l’autenticazione è gestita da RESTful Authentication che
crea current_user quindi io ho pensato di fare in questo modo:

current_user.roles.operations

L’errore che mi da è il seguente:
undefined method `operations’ for Role(id: integer, name: string):Class

Ho provato anche con :through, ma mi restituisce sempre un errore
Invalid source reflection macro :has_and_belongs_to_many for has_many
:operations, :through => :roles. Use :source to specify the source
reflection.

allora, la tua pare essere una doppia associazione molti a molti,
dunque l’has many through deve passare per i join model (N.B. con has
many through le tabelle di join devono diventare veri e propri
modelli)

class User
has_many :roles, :through=>:user_roles
has_many :user_roles
end

class UserRole
belongs_to :user
belongs_to :role
end

class Roles
has_many :users, :through=>:user_roles
has_many :user_roles

has_many :operations, :through=>:role_operations
has_many :role_operations
end

class RoleOperation
belongs_to :role
belongs_to :operation
end

class Operation
has_many :roles, :through=>:role_operations
has_many :role_operations
end

ora per trovare tutte le operations dovrebbe essere possibile
semplicemente definire nel modello User:

has_many :operations, :through => :roles

N.B. non ho provato con una relazione tipo has_many through mentre con
la has_many semplice dal join model funziona

In alternativa puoi usare una has_many operations con un :finder_sql:

has_many :operations, , :finder_sql =>
'SELECT DISTINCT operations.* ’ +
'FROM operations o, role_operations ro, user_roles ur ’ +
‘WHERE ur.user_id = #{id} AND ro.role_id = ur.role_id and
o.id=ro.operation_id’

ciao,
Luca

Ciao Luca,

ti ringrazio della spiegazione.
Smanettando un pò, sono riuscito ad avere lo stesso risultato
semplicemnte facendo così:

roles = current_user.roles
@oper = roles.first.operations

Adesso sto cercando di scoprire bene il funzionamento di first.
GRAZIE!!!

Luca M. wrote:

allora, la tua pare essere una doppia associazione molti a molti,
dunque l’has many through deve passare per i join model (N.B. con has
many through le tabelle di join devono diventare veri e propri
modelli)

class User
has_many :roles, :through=>:user_roles
has_many :user_roles
end

class UserRole
belongs_to :user
belongs_to :role
end

class Roles
has_many :users, :through=>:user_roles
has_many :user_roles

has_many :operations, :through=>:role_operations
has_many :role_operations
end

class RoleOperation
belongs_to :role
belongs_to :operation
end

class Operation
has_many :roles, :through=>:role_operations
has_many :role_operations
end

ora per trovare tutte le operations dovrebbe essere possibile
semplicemente definire nel modello User:

has_many :operations, :through => :roles

N.B. non ho provato con una relazione tipo has_many through mentre con
la has_many semplice dal join model funziona

In alternativa puoi usare una has_many operations con un :finder_sql:

has_many :operations, , :finder_sql =>
'SELECT DISTINCT operations.* ’ +
'FROM operations o, role_operations ro, user_roles ur ’ +
‘WHERE ur.user_id = #{id} AND ro.role_id = ur.role_id and
o.id=ro.operation_id’

ciao,
Luca

On Mon, Apr 28, 2008 at 11:49 AM, Alessandro Del coco
[email protected] wrote:

Ciao Luca,

ti ringrazio della spiegazione.
Smanettando un pò, sono riuscito ad avere lo stesso risultato
semplicemnte facendo così:

roles = current_user.roles
@oper = roles.first.operations

first ti da il primo ruolo nell’enumerable roles
dunque roles.first.operations sono le operazioni associate al primo
ruolo, i.e. se hai due ruoli con operazioni associate diverse cosi
trovi solo le operazioni del primo e non quelle del secondo.

ciao,
Luca

Grazie ancora,

ma allora non c’è qualcosa che a posto di first riprende tutti i ruoli?

Luca M. wrote:

On Mon, Apr 28, 2008 at 11:49 AM, Alessandro Del coco
[email protected] wrote:

Ciao Luca,

ti ringrazio della spiegazione.
Smanettando un p�, sono riuscito ad avere lo stesso risultato
semplicemnte facendo cos�:

roles = current_user.roles
@oper = roles.first.operations

first ti da il primo ruolo nell’enumerable roles
dunque roles.first.operations sono le operazioni associate al primo
ruolo, i.e. se hai due ruoli con operazioni associate diverse cosi
trovi solo le operazioni del primo e non quelle del secondo.

ciao,
Luca

oppure, piu’ rubioso ancora:

@oper = roles.collect(&:operations).flatten.uniq

Alessandro Del coco wrote:

Grazie ancora,

ma allora non c’è qualcosa che a posto di first riprende tutti i ruoli?

@oper = roles.collect {|r| r.operations}.flatten.uniq

Puoi aggiungere al modello User un metodo operations:

def self.operations
roles.collect(&:operations).flatten.uniq
end

Così avrai direttamente il metodo operations per ogni istanza. Stile

pino = User.find(:first)
pino.operations (ritorna array di operations…)

  • Show quoted text -
    On Mon, Apr 28, 2008 at 2:54 PM, Claudio Petasecca D. <

anche se collect usato così non l’ho capito… a me dice expected Proc in
irb. Che uso è esattamente?

On Mon, Apr 28, 2008 at 3:48 PM, giovanni lion [email protected]

giovanni lion wrote:

anche se collect usato cos� non l’ho capito… a me dice expected Proc in
irb. Che uso � esattamente?

On Mon, Apr 28, 2008 at 3:48 PM, giovanni lion [email protected]

Rails estende la classe Symbol con un metodo to_proc:

class Symbol
def to_proc
Proc.new { |*args| args.shift.send(self, *args) }
end
end

Chiamare

roles.collect(&:operations)

equivale a chiamare

roles.collect(:operations.to_proc)

ovvero

roles.collect {|r| r.send(:operations) }

quindi

roles.collect {|r| r.operations }

Questa estensione della classe Symbol e’ definita solo in Rails, non in
Ruby.
Sara’ integrata nel prossimo Ruby 1.9

Ecco perche’ non ti funziona in irb

Infatti stavo giusto cercando ruby 1.9 e le novità sui lambda… Buono a
sapersi grazie!

2008/4/28 Claudio Petasecca D. [email protected]: