Skip to content

Commit a854d5f

Browse files
committed
added variable checking in logic
1 parent 302c18b commit a854d5f

File tree

9 files changed

+82
-37
lines changed

9 files changed

+82
-37
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ group :development, :test do
5151
gem 'faker'
5252
gem 'factory_girl_rails', '<2.0'
5353
gem 'timecop'
54+
gem 'single_test'
5455
end
5556

5657
group :production do

Gemfile.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ GEM
134134
ruby-debug-base19 (>= 0.11.19)
135135
ruby_core_source (0.1.5)
136136
archive-tar-minitar (>= 0.5.2)
137+
single_test (0.4.4)
137138
sqlite3 (1.3.4)
138139
sqlite3 (1.3.4-x86-mingw32)
139140
sqlite3-ruby (1.3.3)
@@ -177,6 +178,7 @@ DEPENDENCIES
177178
recaptcha
178179
ruby-debug19
179180
saferjs!
181+
single_test
180182
sqlite3-ruby
181183
therubyracer
182184
timecop

Rakefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@
66

77
require File.expand_path('../config/application', __FILE__)
88
require 'rake'
9+
require 'single_test'
10+
11+
SingleTest.load_tasks
912

1013
Quadbase::Application.load_tasks

app/models/logic.rb

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,28 @@
33
class Logic < ActiveRecord::Base
44
belongs_to :logicable, :polymorphic => true
55

6-
6+
validate :variable_parse_succeeds
77
validate :code_runs_safely
88

99
before_save :cache_code
1010

11+
serialize :variables_array
12+
1113
attr_reader :results
1214

13-
def run
14-
15-
16-
# TODO on save variables, split into array (serialized in class)
17-
# TODO cache this code
18-
19-
20-
# wrapped_code = ERB.new <<-CODE
21-
# var wrapper = {
22-
# runCode: function() {
23-
# <%= code %>
24-
# test = "hi";
25-
# results = {};
26-
# <% variables.each do |variable| %>
27-
# results['<%= variable %>'] = <%= variable %>
28-
# <% end %>
29-
# return results;
30-
# }
31-
# }
32-
# CODE
33-
#
34-
#
35-
#
36-
# ready_code = wrapped_code.result(binding)
37-
# # logger.debug(ready_code)
38-
#
39-
# debugger
40-
41-
c = SaferJS.compile(get_cached_code)
42-
43-
@results = c.call('wrapper.runCode') # TODO is here the place to pass in values from prior logic?
15+
JS_RESERVED_WORDS_REGEX = /^(do|if|in|for|let|new|try|var|case|else|enum|eval|
16+
false|null|this|true|void|with|break|catch|class|
17+
const|super|throw|while|yield|delete|export|
18+
import|public|return|static|switch|typeof|
19+
default|extends|finally|package|private|continue|
20+
debugger|function|arguments|interface|protected|
21+
implements|instanceof)$/
22+
23+
VARIABLE_REGEX = /^[_a-zA-Z]{1}\w*$/
24+
25+
def run(seed = rand(2e9))
26+
context = SaferJS.compile(get_cached_code)
27+
@results = context.call('wrapper.runCode') # TODO is here the place to pass in values from prior logic?
4428

4529
return @results
4630
end
@@ -60,7 +44,7 @@ def cache_code
6044
runCode: function() {
6145
<%= code %>
6246
results = {};
63-
<% variables.each do |variable| %>
47+
<% variables_array.each do |variable| %>
6448
results['<%= variable %>'] = <%= variable %>
6549
<% end %>
6650
return results;
@@ -70,4 +54,35 @@ def cache_code
7054

7155
self.cached_code = erb_code.result(binding)
7256
end
57+
58+
def variable_parse_succeeds
59+
60+
self.variables_array = variables.split(/[\s,]+/)
61+
62+
if !self.variables_array.all?{|v| VARIABLE_REGEX =~ v}
63+
errors.add(:variables, "can only contain letter, numbers and
64+
underscores. Additionally, the first character
65+
must be a letter or an underscore.")
66+
end
67+
68+
reserved_vars = self.variables_array.collect do |v|
69+
match = JS_RESERVED_WORDS_REGEX.match(v)
70+
match.nil? ? nil : match[0]
71+
end
72+
73+
reserved_vars.compact!
74+
75+
reserved_vars.each do |v|
76+
errors.add(:variables, "cannot contain the reserved word '#{v}'.")
77+
end
78+
79+
if !self.variables_array.all?{|v| JS_RESERVED_WORDS_REGEX =~ v}
80+
errors.add(:variables, "")
81+
end
82+
83+
self.variables = self.variables_array.join(", ")
84+
85+
errors.any?
86+
end
87+
7388
end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class AddVariablesArrayToLogic < ActiveRecord::Migration
2+
def self.up
3+
add_column :logics, :variables_array, :string
4+
end
5+
6+
def self.down
7+
remove_column :logics, :variables_array
8+
end
9+
end

db/schema.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended to check this file into your version control system.
1212

13-
ActiveRecord::Schema.define(:version => 20120313182705) do
13+
ActiveRecord::Schema.define(:version => 20120313200004) do
1414

1515
create_table "announcements", :force => true do |t|
1616
t.integer "user_id"
@@ -100,6 +100,7 @@
100100
t.datetime "updated_at"
101101
t.integer "predecessor_logic_id"
102102
t.text "cached_code"
103+
t.string "variables_array"
103104
end
104105

105106
create_table "messages", :force => true do |t|

notes.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ rake db:test:purge Empty the test database.
4040
rake db:test:load Recreate the test database from the current schema.rb
4141
rake db:test:prepare Check for pending migrations and load the test schema
4242
rake db:test:purge; rake db:test:load; rake db:test:prepare
43+
be rake db:test:purge db:test:load db:test:prepare
4344

4445
-------
4546
git rm --cached <file> removes that file from version control but leaves it in the working copy

test/factories.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,8 @@ def make_project(options = {})
266266
f.association :deputizer, :factory => :user
267267
f.association :deputy, :factory => :user
268268
end
269+
270+
Factory.define :logic do |f|
271+
f.code "x = 2"
272+
f.variables "x"
273+
end

test/unit/logic_test.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
require 'test_helper'
22

33
class LogicTest < ActiveSupport::TestCase
4-
# Replace this with your real tests.
5-
test "the truth" do
6-
assert true
4+
5+
test "basic" do
6+
assert_nothing_raised{Factory.create(:logic)}
7+
end
8+
9+
test "reserved words not allowed" do
10+
assert_raise(ActiveRecord::RecordInvalid) {Factory.create(:logic, :variables => 'x, y, continue')}
11+
end
12+
13+
test "start with letter or underscore" do
14+
assert_raise(ActiveRecord::RecordInvalid) {Factory.create(:logic, :variables => '9x')}
715
end
816
end

0 commit comments

Comments
 (0)