Hi,
I'm getting a class name as string via params[:class_name]. How can I
access the class?
E.g.
params[:class_name] => "Post"
and then something like
params[:class_name].to_class.find(:first)
Why I want to to this? I want to create a generic commenting component
with model controller and view (partials) that I can use to comment any
other instance.
For now each class that can be commented (here: Article besides many
others) needs rather the same action code:
class ArticleController < ApplicationController
def comment
@commentable = Article.find(params[:id]) # commentable
@comment = Comment.new
@comment.user = session['user']
@commentable.comments << @comment
if request.post?
@comment = Comment.new(params[:comment])
if @comment.save
render :partial => "comment/comment_list"
else
render :inline => "<%= user_message_helper 'comment' %>",
:status => 500
end
end
end
end
I would like to have this action only once in the CommentController,
somehow like this:
class CommentController < ApplicationController
def comment
class_name = params[:class_name]
@commentable = class_name.to_class.find(params[:id]) # commentable
@comment = Comment.new
@comment.user = session['user']
@commentable.comments << @comment
if request.post?
@comment = Comment.new(params[:comment])
if @comment.save
render :partial => "comment/comment_list"
else
render :inline => "<%= user_message_helper 'comment' %>",
:status => 500
end
end
end
end
I'm sure there is an elegant way to handle this...
on 2007-02-01 17:50
on 2007-02-01 18:19
starburger wrote: > Hi, > > I'm getting a class name as string via params[:class_name]. How can I > access the class? I think what you want is eval eval("Ball").find(:all) for example will find all balls with a model class Ball. Not that a class name is case sensitive!!!!!!
on 2007-02-01 18:20
Rob Nichols wrote:
> Not that a class name is case sensitive!!!!!!
Should be:
Note that a class name is case sensitive!!!!!!
on 2007-02-01 18:49
On 2/1/07, starburger <rails-mailing-list@andreas-s.net> wrote: > > and then something like > > params[:class_name].to_class.find(:first) Try String#constantize: params[:class_name].constantize.find(:first) Why I want to to this? I want to create a generic commenting component
on 2007-02-01 19:07
Michael Guterl wrote: > On 2/1/07, starburger <rails-mailing-list@andreas-s.net> wrote: >> >> and then something like >> >> params[:class_name].to_class.find(:first) > > > Try String#constantize: > > params[:class_name].constantize.find(:first) > > Why I want to to this? I want to create a generic commenting component how bout eval(params[:class_name].capitalize + ".find(:first)") ?
on 2007-02-01 20:29
On 1-Feb-07, at 2:13 PM, Jason Roelofs wrote: > Starburger > > Jason, Why stay away from eval? I'm currently using eval to dynamically build a restful url_helper reference. Is this also a bad case of using eval fro the same reason/? ala: eval("change_state_#{the_model.class.name.downcase}_url(# {the_model.id})") (sorry to hijack - hopefully this adds to the discussion!) Cheers, Jodi General Partner The nNovation Group inc. www.nnovation.ca/blog 
on 2007-02-01 21:48
On Thursday 01 February 2007 20:28, Jodi Showers wrote:
> Why stay away from eval?
class SomethingsController < ApplicationController
def tricky
...
eval(params[:my_param])
...
end
end
Then consider what a request like this might do to your server
http://example.com/trickies/tricky?my_param=system(%22rm%20-rf%20%2F%22)
Michael
--
Michael Schuerig
mailto:michael@schuerig.de
http://www.schuerig.de/michael/
on 2007-02-01 21:49
On Feb 1, 2007, at 11:28 AM, Jodi Showers wrote: >> > {the_model.id})") > Jodi- The reason to stay away from eval is because you want to avoid evaling anything user generated. The OP is trying to make a class from an item in the params object. DANGER!! look here: how bout eval(params[:class_name].capitalize + ".find(:first)") ? Now anyone can try to enter all kinds of things in the params [:class_name] form field. And it will get evaled without any checking on the server. Bad! If you can avoid eval please do so at all costs. class_Eval or instance_eval with blocks instead of strings are better. But in your example: eval("change_state_#{the_model.class.name.downcase}_url(# {the_model.id})") should be written like this: send("change_state_#{the_model.class.name.downcase}_url", "# {the_model.id}") Cheers- -- Ezra Zygmuntowicz -- Lead Rails Evangelist -- ez@engineyard.com -- Engine Yard, Serious Rails Hosting -- (866) 518-YARD (9273)
on 2007-02-01 23:57
On 1-Feb-07, at 3:48 PM, Ezra Zygmuntowicz wrote: >>> Jason >> I'm currently using eval to dynamically build a restful url_helper >> General Partner > evaling anything user generated. The OP is trying to make a class > instance_eval with blocks instead of strings are better. But in your > Cheers- > > -- Ezra Zygmuntowicz > -- Lead Rails Evangelist > -- ez@engineyard.com > -- Engine Yard, Serious Rails Hosting > -- (866) 518-YARD (9273) Thanx Ezra and Michael. I understood that Send limitted the scope(object calls) of damage that can be cause by eval - and a object.send("#{params[:command]) is dangerous enough. Whereby Eval's scope isn't limited. In my particular case the_model is instantiate by the controller action - so eval would likely be as 'safe' as send (?). My questions was questioning what additional protection that send provides - is there any protection provided above and beyond the localization of the class executing the arbritary code? I think my learning here is that regardless of means(send, eval, etc), that additionally checking should be done on the methods being called - limiting the scope of the methods that can be called (I've recently used acts_as_state_machine to limit sends based upon model state and other guards - this provides funnel that sends must qualify before running - and still give me the benefit of a measure of dynamism. ala: instance.send("#{params[:command]}") if Class.legitimate_commands.include?(params[:command]) thanks for teaching this ruby-nuby. Jodi
on 2007-02-02 17:50
> eval("change_state_#{the_model.class.name.downcase}_url(# > {the_model.id})") > > should be written like this: > > send("change_state_#{the_model.class.name.downcase}_url", "# > {the_model.id}") Hey Ezra - the send didn't succeed as : undefined method `change_state_project_url(:id => 85, :event => 'change_project_info')' for #<#<Class:0x345af20>:0x345aef8> note: this code is running inside application_helper - not sure what self is inside a helper, but it doesn't know about rest url helpers. Do you know what object 'owns' these methods? I gather they are Class methods. thanx. Jodi
on 2007-02-03 00:49
As everybody has said, avoid eval - use const_get to retrieve a
constant. If you want a class from a string, here's a simple
implementation:
class String
def to_class
Object.const_get(self)
end
end
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.