Allowing users to edit content of pages with variables...

2 views
Skip to first unread message

Mark Locklear

unread,
Dec 13, 2013, 3:44:02 PM12/13/13
to ashevi...@googlegroups.com
Hey folks. I have a requirement in an app where users need to be able to edit the content on some pages. Additionally these pages contain variables that need to be appropriately displayed. I have created a Page model with a :name and :content, where :content is a text field. I have a view that is calling these pages like this...

<%= sanitize ERB.new(Page.find_by_name("New Registration").content).run %>

The content of the text in the DB look like...

<%= @registration = Registration.last %><%= @registration.orientation.class_time %> some plain content and text here

The issue I am having is when this displays I get a blank page. When I view source this is confirmed (there nothing there).

Honestly this feels pretty clunky, but its the best I could come up with. I have not found a "Rails Way" to do this. If anyone has suggestions please send them my way. Thanx!

--
J. Mark Locklear
-Philippians 4:13 gives you the muscle, but YOU have to flex it!

-He who works with his hands is a laborer.
-She who works with her hands and her head is a craftswomen.
-Those who work with their hands, their head, and their hearts are artists.

Levi Kennedy

unread,
Dec 13, 2013, 4:03:24 PM12/13/13
to ashevi...@googlegroups.com
Hey Mark,

Allowing a user to use ERB is very dangerous. You should use something like Mustache, or Liquid. ERB isn't sandboxed, so a user will have access to all kinds of things like File, FileUtils. A quick <%= File.read(Rails.root.join("config/database.yml")) %> would give the user access to your database. Or <%= Page.destroy_all %> would delete all of your page records.

Levi
--
You received this message because you are subscribed to the Google Groups "Asheville Ruby Users Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to asheville-rb...@googlegroups.com.
To post to this group, send email to ashevi...@googlegroups.com.
Visit this group at http://groups.google.com/group/asheville-rb.
For more options, visit https://groups.google.com/groups/opt_out.

Mark Locklear

unread,
Dec 13, 2013, 4:05:09 PM12/13/13
to ashevi...@googlegroups.com
Thanks Levi. I saw some references to those frameworks, but have not used them. Would I still use the same model configuration? With a Page model?

Levi Kennedy

unread,
Dec 13, 2013, 4:11:04 PM12/13/13
to ashevi...@googlegroups.com
Absolutely. What you are doing is great, I would just steer clear of ERB.

With Mustache, you would be able to give the user access to specific variables. So your example would then look something like this:

<%= sanatize Mustache.compile(Page.find_by_name("New Registration")).render(attrs) %>

where attrs is a hash. There are some other methods for rendering mustache templates as well, but I can't remember how that works.

Liquid I'm less familiar with off the top of my head. It's maintained by shopify and is always getting updated.

I really prefer mustache. Although it may or may not be still maintained.

Levi

Mark Locklear

unread,
Dec 16, 2013, 9:56:49 AM12/16/13
to ashevi...@googlegroups.com
Thanks Levi. So sanity check this for me. So now in my Page model data I have...

{{ @registration = Registration.last }} {{ @registration.orientation.class_time }} this is a test

...and in app/views/registrations/scheduling_text.html.erb I have...

<%= sanitize Mustache.render(Page.find_by_name("New Registration")) %>

which I am calling from the controller. If I use 'compile' like you suggested I get an undefined method error. Maybe its depricated? However, I can use render like...

<%= sanatize Mustache.render(Page.find_by_name("New Registration")).render(attrs) %>

..but now I get the error for 'attrs'. Ideas?

I'm amazed on how difficult this has been. I'm on my 2nd week off trying to implement this. You would think there would be more tutorials on the topic, but either its not a common use case, or I'm just missing it. *sigh*

Jeff Waltzer

unread,
Dec 16, 2013, 10:32:10 AM12/16/13
to ashevi...@googlegroups.com
Have you tried breakpointing the code at the call to sanitize and seeing what 'Mustache.render(Page.find_by_name("New Registration")).render(attrs) ' returns?  also check the class you are getting back.  Maybe its not a string?

Levi Kennedy

unread,
Dec 16, 2013, 10:39:35 AM12/16/13
to ashevi...@googlegroups.com
Hey Mark,

I pointed you in the wrong direction with my code examples.

So, first of all. Mustache is meant to be fairly logicless. So, there is no need to assign inside the view. You would actually want to pass in the registration object at render time like so.

<%= Mustache.render(Page.find_by_name("Foo").content, {:registration => Registration.last}) %>

Then you can access it in the template like so:

{{ registration.orientation.class_time }}

That may be wrong, you might want to check the Mustache docs. It may be better to nest them:

{{ #registration }}
{{ #orientation }}{{class_time}}{{ /orientation }}
{{ /registration }}

I know it seems a bit verbose. Liquid is more friendly with the "." syntax if i remember correctly. I would also not pass in the entire object as part of the attars. Maybe pass in the only things you need, like orientation_time.

Hope that makes sense.

Levi

Mark Locklear

unread,
Dec 16, 2013, 11:08:29 AM12/16/13
to ashevi...@googlegroups.com
Yes! That worked Levi, thanks so much. Stackoverflow flow was surprisingly not very helpful on this topic (nor were responses to my questions). Here is what I ended up with...

In the actual page model...http://pastie.org/8556099

#app/views/registrations/scheduling_text.html.erb
<%= Mustache.render(Page.find_by_name("New Registration").content, {:registration => @registration }).html_safe %>
<%= link_to 'Back', orientations_path %>

#app/controllers/registrations_controller.rb
def create
    @registration = Registration.new(params[:registration])

    respond_to do |format|
      if @registration.save
        if @registration.orientation != nil
          format.html { render "scheduling_text.html.erb" }
           ...

Thanks all for the responses.
Reply all
Reply to author
Forward
0 new messages