Forum: Rails Germany howto: find model from controller

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
A46ca7c2903460c19ffeee0476b9542d?d=identicon&s=25 Torsten Flammiger (Guest)
on 2008-10-07 22:37
(Received via mailing list)
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
0719268936a0d71e8dcf7c21810510bf?d=identicon&s=25 Manuel Wiedenmann (Guest)
on 2008-10-07 22:55
(Received via mailing list)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

geht nicht einfach:

  <% tags = @A.tag_counts %>
  <%= _('Tags:') %><br />
  <% 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 Flammiger:

> die Tags B*
> Torsten
> _______________________________________________
> rubyonrails-ug mailing list
> rubyonrails-ug@headflash.com
> 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-----
Bce1d1b7c3ec7b577dcb42e254899e6b?d=identicon&s=25 Michael Schuerig (Guest)
on 2008-10-07 23:21
(Received via mailing list)
On Tuesday 07 October 2008, Torsten Flammiger 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
A46ca7c2903460c19ffeee0476b9542d?d=identicon&s=25 Torsten Flammiger (Guest)
on 2008-10-08 08:41
(Received via mailing list)
On Tue, 7 Oct 2008 23:20:12 +0200, "Michael Schuerig"
<michael@schuerig.de> said:
> On Tuesday 07 October 2008, Torsten Flammiger 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
Bce1d1b7c3ec7b577dcb42e254899e6b?d=identicon&s=25 Michael Schuerig (Guest)
on 2008-10-08 09:06
(Received via mailing list)
On Wednesday 08 October 2008, Torsten Flammiger 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 Schuerig
mailto:michael@schuerig.de
http://www.schuerig.de/michael/
A46ca7c2903460c19ffeee0476b9542d?d=identicon&s=25 Torsten Flammiger (Guest)
on 2008-10-08 09:36
(Received via mailing list)
On Wed, 8 Oct 2008 09:05:53 +0200, "Michael Schuerig"
<michael@schuerig.de> said:
> On Wednesday 08 October 2008, Torsten Flammiger 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 ;)

> 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
Cb37c4d3ed0c1eef295be9607347d2aa?d=identicon&s=25 Oliver Haag (Guest)
on 2008-10-08 13:46
(Received via mailing list)
>
> 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
A46ca7c2903460c19ffeee0476b9542d?d=identicon&s=25 Torsten Flammiger (Guest)
on 2008-10-08 14:34
(Received via mailing list)
On Wed, 08 Oct 2008 13:45:45 +0200, "Oliver Haag" <ohaag@ohcon.de> 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
A46ca7c2903460c19ffeee0476b9542d?d=identicon&s=25 Torsten Flammiger (Guest)
on 2008-10-08 22:15
(Received via mailing list)
Torsten Flammiger 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
978ed7ca309d5495078702096f9add03?d=identicon&s=25 Thomas R. Koll (Guest)
on 2008-10-09 11:13
(Received via mailing list)
Am 08.10.2008 um 22:14 schrieb Torsten Flammiger:

> 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 :)

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: tomk32@gmx.de
http://beta.lomography.com/homes/TomK32
A46ca7c2903460c19ffeee0476b9542d?d=identicon&s=25 Torsten Flammiger (Guest)
on 2008-10-09 11:58
(Received via mailing list)
On Thu, 9 Oct 2008 11:12:12 +0200, "Thomas R. Koll" <tomk32@gmx.de>
said:
>
> Ich glaub ich bin letztens schon mal über solche Verwendung des
> before_filters hergezogen aber wiederhol mich gerne :)

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
0928885251288471f82ea5be3f26f5de?d=identicon&s=25 Thomas Winkler|Formrausch (Guest)
on 2008-10-09 13:57
(Received via mailing list)
On Oct 9, 2008, at 11:57 AM, Torsten Flammiger 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
rubyonrails-ug@headflash.com
http://mailman.headflash.com/mailman/listinfo/rubyonrails-ug
A46ca7c2903460c19ffeee0476b9542d?d=identicon&s=25 Torsten Flammiger (Guest)
on 2008-10-09 21:26
(Received via mailing list)
> 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 :-)

gut's nächtle
torsten
59528506e6297141161afcde91d677c9?d=identicon&s=25 Nicolai Reuschling (codeblogger)
on 2008-10-09 23:08
(Received via mailing list)
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
A46ca7c2903460c19ffeee0476b9542d?d=identicon&s=25 Torsten Flammiger (Guest)
on 2008-10-10 08:04
(Received via mailing list)
On Thu, 9 Oct 2008 23:08:02 +0200, "Codeblogger" <codeblogger@gmail.com>
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
This topic is locked and can not be replied to.