Comment gérer les has_many avec activere source?

Salut à tous,
J’ai deux models:
Profile et Email avec Profiles has_many :emails et Emails belongs_to
:profile

J’ai une autre application client qui accède à ces deux models avec
ActiveResource:

class Profile < ActiveResource::Base
self.site = “http://0.0.0.0:3000
end

class Email < ActiveResource::Base
self.site = “http://0.0.0.0:3000
end

J’arrive à créer des emails et des profils et à faire du CRUD. Mais
si, depuis l’application client activeresource, je fais:
p=Profile.find :first
et que je tape:
p.emails
j’ai une erreur qui me dis que la fonction emails n’existe pas.

J’ai donc créer une fonction dans Profile:

def getmodels(model_name)
model_name=model_name.constantize
model_name.find :all,
:from=>model_name.collection_path(:profile_id=>self.id)
end

ça me permet de faire: p.getmodels(‘Email’) et ça me renvoie tous les
emails de ce profile p.

Je voudrais savoir si il y a plus simple ou mieux comme solution?

Merci d’avance

Pat

Patrick :
[…]

Je voudrais savoir si il y a plus simple ou mieux comme solution?
Moins générique et plus orientée ressources imbriquées (nested
resources)

class Email < ARes::B
self.site = “http://0.0.0.0:3000/profiles/:profile_id
end

class Profile < ARes::B
def emails
Email.find :all, :params => { :profile_id => id }
end
end

– Jean-François.


À la renverse.

On 6/25/07, Jean-François [email protected] wrote:

emails de ce profile p.
class Profile < ARes::B
def emails
Email.find :all, :params => { :profile_id => id }
end
end

par contre c’est vrai que :params => { :profile_id => id } est plus
sympa (et nested resources oriented :slight_smile: que
collection_path(:profile_id=>self.id). J’ai modifié ça. Merci!

On 6/25/07, Jean-François [email protected] wrote:

emails de ce profile p.
class Profile < ARes::B
def emails
Email.find :all, :params => { :profile_id => id }
end
end

oui c’est ce que j’avais fait en premier, mais vu qu’un profile n’as
pas seulement des emails mais aussi des phones, fax, invites,
adresses, urls etc, je me suis dit que quelque chose de plus générique
ferait mieux l’affaire plutôt que d’avoir 50 fonctions qui font la
même chose. C’est plus DRY comme ça :slight_smile:
C’est vrai que j’aurai du préciser dans ma question que le profile
n’avait pas que des emails.

On 6/25/07, Jean-François Trân [email protected] wrote:

end
end

ARes::Base.extend Castafiore

class Profile < ARes::Base
babar :profiles, :phones, :addresses, :invites
end

ok merci beaucoup. Si je veux pouvoir configurer le ‘profile_id’ et
utiliser ‘user_id’ à la place, tu sais comment je pourrais faire ça?

Merci d’avance

Pat

Le 25/06/07, Patrick A.[email protected] a écrit :

J’ai donc créer une fonction dans Profile:

def getmodels(model_name)
model_name=model_name.constantize
model_name.find :all, :from=>model_name.collection_path(:profile_id=>self.id)
end
[…]
même chose. C’est plus DRY comme ça :slight_smile:
C’est vrai que j’aurai du préciser dans ma question que le profile
n’avait pas que des emails.

Il faut faire un peu de métaprogrammation alors. T’en étais pas
loin.

module Castafiore
def babar *args
args.map(&:to_s).each do |name|
define_method(name.underscore.pluralize) do
name.classify.constantize.find :all, :params => { :profile_id =>
id }
end
end
end
end

ARes::Base.extend Castafiore

class Profile < ARes::Base
babar :profiles, :phones, :addresses, :invites
end

  • choisir des noms plus appropriés :slight_smile:

    – Jean-François.


membre du CA de Ruby France.
Ruby ( http://www.rubyfrance.org ) on Rails ( http://www.railsfrance.org
)

Ok super, encore merci. Je me rend compte qu’avec un peu d’effort on
pourrait implémenter un belongs_to et un has_many dans ARes sans trop
de difficulté. Si c’est aussi simple que ça, tu sais pourquoi DHH & co
ont choisi de ne pas le faire?

Patrick :

end
utiliser ‘user_id’ à la place, tu sais comment je pourrais faire ça?
Pour une interface :

class Profile < ARes::Base
babar :profiles, :phones, :addresses, :invites, :foreign_key =>
‘rackham_le_rouge’
end

cela nécessite de modifier un peu babar.

module Castafiore
def babar *args
if args.last.is_a? Hash
options = args.pop
foreign_key = options[:foreign_key] if options.include?
:foreign_key
end
foreign_key ||= :profile_id

args.map(&:to_s).each do |name|
  define_method(name.underscore) do
    name.classify.constantize.find :all, :params => {

foreign_key.to_sym => id }
end
end
end
end

après foreign_key… ou primary_key ? ça dépend depuis quelle ressource
on se place.

-- Jean-François.


membre du CA de Ruby France.
Ruby ( http://www.rubyfrance.org ) on Rails ( http://www.railsfrance.org
)

Salut Jean-François,
au lieu de faire:

foreign_key ||= :profile_id

j’éssais de faire:

foreign_key ||= self.class.to_s.downcase+’_id’

pour automatiser le truc selon le model que j’utilise.
Comme ça si j’ai:

class Profile < ARes::Base
babar addresses, :invites
end

et

class User < ARes::Base
babar :profiles, :phones
end

ça va automatiquement chercher :profile_id ou :user_id, mais sans
succès pour le moment :confused:

tu sais quelle serait la ligne exacte?

Merci d’avance

Pat

c’est bon ça marche, j’ai mis la ligne dans le define_method:

define_method(name.underscore) do
foreign_key ||= self.class.to_s.downcase+’_id’
name.classify.constantize.find :all, :params =>
{foreign_key.to_sym => id }
end

Patrick :

c’est bon ça marche, j’ai mis la ligne dans le define_method:

define_method(name.underscore) do
foreign_key ||= self.class.to_s.downcase+‘_id’
name.classify.constantize.find :all, :params =>
{foreign_key.to_sym => id }
end

Ma dernière proposition (que je commenterais éventuellement
plus tard, mais là je vais manger)

module Castafiore
def babar *args
options = args.last.is_a?(Hash) ? args.pop : {}
foreign_key = (options[:foreign_key] || name.foreign_key).to_sym

args.map(&:to_s).each do |klass_name|
  klass = klass_name.classify.constantize

  define_method(klass_name.underscore) do
    klass.find :all, :params => { foreign_key => id }
  end
end

end
end

– Jean-François.


Ruby ( http://www.rubyfrance.org ) on Rails ( http://www.railsfrance.org
)