Howto: find model from controller


#1

Hallo allerseits,

folgende Frage auf die ich auch nach Stunden der Suche keine Antwort
finde: wie finde ich das Model, auf welches sich der aufrufende
Controller bzw. dessen Aktion bezieht?

Hintergrund ist, das ich die Tags, die per acts_as_tagable_on_steroids
zur Verfügung gestellt werden, kontextsensitiv machen möchte: bei
Controller A sollen nur die Tags A* gezogen werden, bei Controller B nur
die Tags B*

Ich fand etwas wie:
Tagging.find_all_by_taggable_type(ActiveRecord::Base.send
(:class_name_of_active_record_descendant, self).to_s)

Aber
a) - es funktioniert nicht, wegen: undefined method `base_class’
b) - da fehlt mir dann doch das Wissen(, um es selbst zu beheben)

Danke im voraus für Hinweise
Torsten


#2

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

geht nicht einfach:

<% tags = @A.tag_counts %>
<%= _(‘Tags:’) %>

<% tag_cloud tags, %w(tag_cloud1 tag_cloud2 tag_cloud3 tag_cloud4)
do |tag, css_class| %>
<%= link_to(tag.name, { :action => :index, :id => tag.name, :tags
=> true }, :class => css_class) %>
<% end %>

Am 07.10.2008 um 22:37 schrieb Torsten F.:

die Tags B*
Torsten


rubyonrails-ug mailing list
removed_email_address@domain.invalid
http://mailman.headflash.com/mailman/listinfo/rubyonrails-ug

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (Darwin)

iD8DBQFI68yEs/WwCK0ZZEARAuhIAKC3YuEJavftoWtU+hUOm83xANjXhACeKVin
MXb+G85Zy4H27vT4UmWPNg4=
=QpBh
-----END PGP SIGNATURE-----


#3

On Tuesday 07 October 2008, Torsten F. wrote:

Hallo allerseits,

folgende Frage auf die ich auch nach Stunden der Suche keine Antwort
finde: wie finde ich das Model, auf welches sich der aufrufende
Controller bzw. dessen Aktion bezieht?

An welcher Stelle denn? Im Controller selbst weisst du doch ganz genau,
mit welcher Model-Klasse du zu tun hast.

Hintergrund ist, das ich die Tags, die per
acts_as_tagable_on_steroids zur Verfügung gestellt werden,
kontextsensitiv machen möchte: bei Controller A sollen nur die Tags
A* gezogen werden, bei Controller B nur die Tags B*

Ich fand etwas wie:
Tagging.find_all_by_taggable_type(ActiveRecord::Base.send
 (:class_name_of_active_record_descendant, self).to_s)

Warum nicht einfach so

class A < ActiveRecord::Base

def self.taggings
Tagging.find_all_by_taggable_type(self.name)
end

bzw.

def self.tags
Tagging.find_all_by_taggable_type(self.name,
:include => :tag).map(&:tag)
end
end

Michael


#4

On Tue, 7 Oct 2008 23:20:12 +0200, “Michael S.”
removed_email_address@domain.invalid said:

On Tuesday 07 October 2008, Torsten F. wrote:

Hallo allerseits,

folgende Frage auf die ich auch nach Stunden der Suche keine Antwort
finde: wie finde ich das Model, auf welches sich der aufrufende
Controller bzw. dessen Aktion bezieht?

An welcher Stelle denn? Im Controller selbst weisst du doch ganz genau,
mit welcher Model-Klasse du zu tun hast.

die Tags werden via before_filter im Application-Controller gezogen.
Von daher könnte ich der Methode, die die Liste der Tags zusammenbaut,
den Namen des Controllers via controller.controller_name als Parameter
mit auf den Weg geben.

Derzeit macht dieser Filter nichts anderes wie:
@tags = Tag.find(:all)

  :include => :tag).map(&:tag)

end
end

Das ist verständlich(er), aber wie löse ich vom String (also
dem Controllernamen als Parameter) zum Model auf?
Das ist mir nicht klar und das scheint auch nicht trivial zu sein,
denn prinzipiell kann man im Controller ja jedes beliebige Model laden.

Gruß, Torsten


#5

On Wednesday 08 October 2008, Torsten F. wrote:

wie löse ich vom String (also
dem Controllernamen als Parameter) zum Model auf?
Das ist mir nicht klar und das scheint auch nicht trivial zu sein,
denn prinzipiell kann man im Controller ja jedes beliebige Model
laden.

Im allgemeinen Fall geht das nicht. Wenn in deinem konkreten Fall
Controller und Model immer miteinander korrespondieren, dann kannst du
aus dem Namen des Controllers den des Models ableiten.

Wenn du schon ein Model-Objekt hast, könntest du auf dessen Klasse
natürlich die gezeigte Methode #tags aufrufen: model.class.tags.

Michael


Michael S.
mailto:removed_email_address@domain.invalid
http://www.schuerig.de/michael/


#6

On Wed, 8 Oct 2008 09:05:53 +0200, “Michael S.”
removed_email_address@domain.invalid said:

On Wednesday 08 October 2008, Torsten F. wrote:

wie löse ich vom String (also
dem Controllernamen als Parameter) zum Model auf?
Das ist mir nicht klar und das scheint auch nicht trivial zu sein,
denn prinzipiell kann man im Controller ja jedes beliebige Model
laden.

Im allgemeinen Fall geht das nicht. Wenn in deinem konkreten Fall
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
das hatte ich befürchtet :wink:

Controller und Model immer miteinander korrespondieren, dann kannst du
aus dem Namen des Controllers den des Models ableiten.

Du meinst etwas in der Art, das man den Plural des Wortes ‘Posts’
mittels einer geeigneten Methode (etwa substring) in seinen Singular
umwandelt => ‘Post’. Im Moment würde das (noch) gehen.

Dabei fällt mir ein: schön wäre es, wenn sich das Framework selbst
beschreiben könnte, es wüßte also über seine Struktur selbst bescheid.

Wenn du schon ein Model-Objekt hast, könntest du auf dessen Klasse
natürlich die gezeigte Methode #tags aufrufen: model.class.tags.

In dem Falle habe ich noch keines.

Danke fürs Mitdenken
Guß, Torsten


#7

Dabei fällt mir ein: schön wäre es, wenn sich das Framework selbst
beschreiben könnte, es wüßte also über seine Struktur selbst bescheid.
Ich glaube nicht, dass Mode und Controller fest verdrahtet sind.
Eine automatische Auflösung wird also nur funktionieren,
wenn Model und Controller entsprechend der Rails-Konvention benannt
sind.

dann liefert …
controller_class_name() #… den vollständigen Klassennamen z.b.
“PostsController”
controller_name() #… den Namen ohne Erweiterung und
kleingeschrieben, also hier “posts”

und das Modell heißt dann
@model_name = controller_name.singularize #… also hier “post”

Wenn das nicht universell genug ist, schau mal in den Quellcode vom
ScaffoldGenerator.

Hope it helps
Oliver


#8

On Wed, 08 Oct 2008 13:45:45 +0200, “Oliver Haag” removed_email_address@domain.invalid said:

controller_name() #.. den Namen ohne Erweiterung und 

kleingeschrieben, also hier “posts”

und das Modell heißt dann
@model_name = controller_name.singularize #… also hier “post”

just vor 60 Sekunden hab ich auch die singularize-Methode gefunden.
Und da meine Model und Controller der RAILS-Konvention folgen, werde
ich das so machen (müssen)

Wenn das nicht universell genug ist, schau mal in den Quellcode vom
ScaffoldGenerator.

Hope it helps

i think so…

Oliver

Danke an alle
Torsten


#9

Torsten F. schrieb:

Hallo allerseits,

folgende Frage auf die ich auch nach Stunden der Suche keine Antwort
finde: wie finde ich das Model, auf welches sich der aufrufende
Controller bzw. dessen Aktion bezieht?

Hintergrund ist, das ich die Tags, die per acts_as_tagable_on_steroids
zur Verfügung gestellt werden, kontextsensitiv machen möchte: bei
Controller A sollen nur die Tags A* gezogen werden, bei Controller B nur
die Tags B*

Dank Eurer Hilfe hab ich das mal geschwind mal so gelöst:

before_filter :get_tags
def get_tags
model = params[:controller].singularize.capitalize
@tags = Tag.find_by_sql(“select distinct t.id, t.name from tags t,
taggings tg where t.id = tg.tag_id and tg.taggable_type = ‘#{model}’”)
end

Ãœber die Instanzvariable bereite ich dann im Application-Helper das
Linkmenü zu oder zeige halt keines an, wenn keine Tags gefunden wurden
(die Startseite mit Tags zu versehen wäre vermessen). Ich hab hier auf
die Fehlerbehandlung verzichtet…

funktioniert bestens, nochmals Danke an alle Helfenden
Torsten


#10

Am 08.10.2008 um 22:14 schrieb Torsten F.:

before_filter :get_tags
def get_tags
model = params[:controller].singularize.capitalize
@tags = Tag.find_by_sql(“select distinct t.id, t.name from tags t,
taggings tg where t.id = tg.tag_id and tg.taggable_type =
‘#{model}’”)
end

Ich glaub ich bin letztens schon mal über solche Verwendung des
before_filters
hergezogen aber wiederhol mich gerne :slight_smile:

Lös das Ding über einen Helper, den kannst ja im Controller genauso
verwenden.
Der Grund dafür ist dass du dir später, wenn das ganze mal unter
action oder
fragement_caching komment, viel Arbeit ersparen wirst bzw der Caching
Bonus
am Anfang kleiner ausfällt als du hoffst.

Daten sollte man erst dann aus der Datenbank holen wenn man sie
wirklich verwendet.

ciao, tom


Thomas R. “TomK32” Koll || http://tomk32.de || http://ananasblau.com
just a geek trying to change the world
Skype: TomK32 || Mail: removed_email_address@domain.invalid
http://beta.lomography.com/homes/TomK32


#11

On Thu, 9 Oct 2008 11:12:12 +0200, “Thomas R. Koll” removed_email_address@domain.invalid
said:

Ich glaub ich bin letztens schon mal über solche Verwendung des
before_filters hergezogen aber wiederhol mich gerne :slight_smile:

ich glaube, sowas gelesen zu haben…

Lös das Ding über einen Helper, den kannst ja im Controller genauso
verwenden.
Der Grund dafür ist dass du dir später, wenn das ganze mal unter
action oder
fragement_caching komment, viel Arbeit ersparen wirst bzw der Caching
Bonus
am Anfang kleiner ausfällt als du hoffst.

Daten sollte man erst dann aus der Datenbank holen wenn man sie
wirklich verwendet.

ich brauch sie doch aber gleich…
das find_by_sql werde ich aber wohl in den application_helper auslagern.

ciao, tom

torsten


#12

Moinmoin Thorsten,

Moin Tom

die find_by_SQL kommt doch eher ins Model, oder? Die Helper sind im

da hat er wohl recht, aber gibt es ein application-model?
Da das ganze über einen before_filter im application-controller
gemacht wird, denke ich, das ich im application_helper am besten
aufgehoben bin… ich lass mich gerne eines besseren belehren :slight_smile:

gut’s nächtle
torsten


#13

On Oct 9, 2008, at 11:57 AM, Torsten F. wrote:

ich brauch sie doch aber gleich…
das find_by_sql werde ich aber wohl in den application_helper
auslagern.

Moinmoin Thorsten,

die find_by_SQL kommt doch eher ins Model, oder? Die Helper sind im
Grunde genommen
nur Auslagerungsmoeglichkeiten fuer die Views und dementsprechend
sollten nur
ausgabebezogene Dinge enthalten.

Besten Gruß,
Tom_______________________________________________
rubyonrails-ug mailing list
removed_email_address@domain.invalid
http://mailman.headflash.com/mailman/listinfo/rubyonrails-ug


#14

Hallo zusammen, ich misch mich mal ein…

Was gemeint ist:

class ModelName
def self.load_stuff_with_sql
self.find_by_sql(…)
end
end

Und in den ApplicationController (before-filter wurde ja schon richtig
gesagt) kommt dann der Aufruf rein:

class ApplicationController
before_filter :load_stuff

def load_stuff
@variable = ModelName.load_stuff_with_sql
end
end

Lässt sich deutlich besser testen und entspricht dem MVC-Pattern.

Viele Grüße
Nicolai


#15

On Thu, 9 Oct 2008 23:08:02 +0200, “Codeblogger” removed_email_address@domain.invalid
said:

Und in den ApplicationController (before-filter wurde ja schon richtig
gesagt) kommt dann der Aufruf rein:

class ApplicationController
before_filter :load_stuff

def load_stuff
@variable = ModelName.load_stuff_with_sql
end
end

ahh, so wars gemeint. In der Tat viel besser!
Danke, Torsten