0

I am trying to use a form input from a rails controller in a Python script. I have a form on my rails (version 4.2.1) app that take in a url, then I want to use that url in a Python script. I'm new to rails and have no idea how to do this. My app has gotten as far as taking in the form inputs and rendering them on a page as well as being able to call a Python script and run it, but I need to link them together.

Here is the controller code so far:

class ContestsController < ApplicationController
  def index
    value = %x(python /Users/my/Desktop/rails_test.py 2>&1)
    render :text => value
    @contests = Contest.all
  end

  def new
    @contest = Contest.new
  end

  def create
    @contest = Contest.new(contest_params)

    if @contest.save
      redirect_to contests_url
    else
      render 'new'
    end
  end

  private

  def contest_params
    params.require(:contest).permit(:site, :contest_url)
  end
end

My Python rails_test.py script is:

#!/bin/bash

print "Python script works!"
#url = last :contest_url param from rails app
#print url

Try #1:

I modified the rails code to:

value = %x(python /Users/jdesilvio/Desktop/rails_test.py #{Shellwords.escape(params[:contest_url])} 2>&1)

I modified the Python script to:

#!/Users/me/anaconda/bin/python2.7 python

import sys

print "Python script works!"
print "Url: ", sys.argv[1]

The output is:

Python script works! Url:

My form is:

<%= form_for @contest do |f| %>
  <div>
    <%= f.label :site %>
    <%= f.text_field :site %>
  </div>
  <div>
    <%= f.label :contest_url %>
    <%= f.text_field :contest_url %>
  </div>
  <%= f.submit %>
<% end %>
jdesilvio
  • 1,794
  • 4
  • 22
  • 38

1 Answers1

2

well you could just pass them as command line arguments to your script. %x does string interpolation, but you need to be careful and verify the input since someone could pass params[:contest_url] = " && rm -rf / " or something similar into your script and cause you problems(never trust user input) So the Shellwords (http://ruby-doc.org/stdlib-2.0/libdoc/shellwords/rdoc/Shellwords.html) class can help. Perhaps something like.

value = %x(/Users/my/Desktop/rails_test.py #{Shellwords.escape(params[:site])} #{Shellwords.escape(params[:contest_url])} 2>&1)

Then just make your python script read the values via STDIN

#!/usr/bin/env python
import sys

print "Site: ", sys.argv[1]
print "Url: ", sys.argv[2]

I made your python scripts shebang call /usr/bin/env python, but if python isn't in the path of the user that your rails app is running as you might need the full path. Also you don't need a /bin/bash at the top of your python script if you are calling it as an argument to the python executable.

Doon
  • 19,719
  • 3
  • 40
  • 44
  • I made the changes you suggested (see above), but it didn't print the `argv`. Is that how you meant for me to enter the Python path? In my test editor, the curly brackets around #{Shellwords...} won't close, not sure if something is not right in my editor or if there's an issue in the code.. – jdesilvio May 02 '15 at 01:45
  • It looks like the parameter is not being passed. When I do: `#{Shellwords.escape("test")` the output prints `'test'`. But when I do `#{Shellwords.escape(params[:contest_url])}` the out put is `''`. – jdesilvio May 02 '15 at 02:44
  • try `contest_params[:site]` – Doon May 02 '15 at 02:49
  • that's what I thought too, but when I use `contest_params[:site]` I get the error: `param is missing or the value is empty: contest` – jdesilvio May 02 '15 at 02:55
  • What does your form look like? Also look in your logs and see what the params hash is getting passed in as. You will need to match that. Did you use a form for? Or a form tag? – Doon May 02 '15 at 03:57
  • I'm using `form_for` (see above), here is what the console said the last submission was `Contest Load (0.2ms) SELECT "contests".* FROM "contests" ORDER BY "contests"."id" DESC LIMIT 1 => #` – jdesilvio May 02 '15 at 04:08
  • As you are calling the python script inside index, there actually won't be any params passed , which is why you can't use them? What is the script supposed to run on? 1 Instance of contest, all instances of the contest, when adding a new contest, when showing a contest? – Doon May 02 '15 at 10:43
  • When a new contest is entered, only the new params should be passed to the Python script. Any old params are largely irrelevant. Similar to a search field. So I think you mean the params should be passed inside 'new'? – jdesilvio May 02 '15 at 13:54
  • if only when contest is entered (created) it should go in the create action. – Doon May 02 '15 at 18:31