Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute view code stored in string in run time with eval in rails 3.2 erb?

What we are trying to do is to store a chunk of erb code in a string and then execute the code in run time. Here is a test we did :

  1. take out a chunk of the code from a working erb file and,
  2. rewrite the erb file with eval.

Here is the chunk of erb code taken out:

<tr>
      <th>#</th>
      <th><%= t('Date') %></th>
      <th><%= t('Project Name') %></th>
      <th><%= t('Task Name') %></th>
      <th><%= t('Log') %></th>
      <th><%= t('Entered By') %></th>
  
    </tr>

    <% @logs.each do |r| %>
        <tr>
          <td><%= r.id %></td>
          <td><%= (r.created_at + 8.hours).strftime("%Y/%m/%d")%></td>
          <td><%= prt(r, 'task.project.name') %></td>
          <td><%= prt(r, 'task.task_template.task_definition.name') %></td>
          <td><%= prt(r, :log) %></td>
          <td><%= prt(r, 'last_updated_by.name') %></td>
          
        </tr>
    <% end %>

t() is the translation method for internationalization.

Here is the erb file after rewriting:

  <table class="table table-striped">
    <% code = find_config_const('task_log_view', 'projectx')%>
    <%= eval(code)%>

  </table>

Before rewriting, the chunk of code goes between <table>. Now variable code returns a string of the chunk of code and eval execute the chunk of code. But here is the error:

(eval):1: syntax error, unexpected '<'
(eval):4: syntax error, unexpected tIDENTIFIER, expecting $end
      <th><%= t('Project Name') %></th>
               ^

Extracted source (around line #6):

4:   <table class="table table-striped">
5:      <% code = find_config_const('task_log_view', 'projectx')%>
6:     <%= eval(code)%>
7: 
8:   </table>
9: 

What's wrong with the code above?

like image 209
user938363 Avatar asked Dec 26 '22 22:12

user938363


1 Answers

eval works by evaluating ruby code.

irb(main):001:0> eval('puts "Hello World"')
Hello World
=> nil

while Converting erb template should be done with ERB class

irb(main):002:0> require 'erb'
irb(main):003:0> ERB.new('<%= "Hello World" %>').result
=> "Hello World"

My guess is that the code is actually a string that contain ERB template rather than ruby code.

Nonetheless I don't think that this is a good approach. task.project.name are probably from database that possibly came from user input. doing eval on that seems not like a good idea.

Probably you could solve your problem with normal partials

like image 106
ahmy Avatar answered May 07 '23 03:05

ahmy