Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Submitting a form to Rails with ReactJS

I'm trying to submit a simple form to my Rails app. I lost myself in confusion and nothing's working. This is what I have tried to do:

var newUserForm = React.createClass({
  propTypes: {
    user: React.PropTypes.array
  },
  getInitialState: function() {
    return {name: '', age: '', country: '' };
  },
  handleNameChange: function(e) {
    this.setState({ name: e.target.value });
  },
  handleAgeChange: function(e) {
    this.setState({ age: e.target.value });
  },
  handleCountryChange: function(e) {
    this.setState({ country: e.target.value });
  },
  handleSubmit: function(e) {
    e.preventDefault();
    var name = this.state.name.trim();
    var age = this.state.age.trim();
    var country = this.state.country.trim();
    if (!name || !age || !country) {
      return;
    }
    this.setState({ name: '', age: '', country: '' });

    var user = {user: this.state.user}
    this.setState({data: user});
    $.ajax({
      url: '/users/new',
      dataType: 'json',
      type: 'POST',
      data: {user: user},
      success: function(data) {
        this.setState({data: user});
      }.bind(this),
      error: function(xhr, status, err) {
        this.setState({data: user});
       console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },


  render: function() {
    return (
      <form onSubmit={ this.handleSubmit }>
        <input type="text" placeholder="User's name" value={ this.state.name } onChange={ this.handleNameChange } />
        <input type="text" placeholder="His age" value={ this.state.age } onChange={ this.handleAgeChange } />
        <input type="text" placeholder="Country of origin" value={ this.state.country } onChange={ this.handleCountryChange } />

        <input type="submit" value="Post"/>
      </form>
    )
  }
});

And my console: enter image description here

I need some help.

toy_controller.rb

class ToyController < ApplicationController
  def index
    @users = User.all
    render component: 'usersList', props: { users: @users }
  end

  def new
    @user = User.new
    render component: 'newUserForm'
  end

  def create
    @user = User.new(user_params)

    if @user.save
      render component: 'showUser', props: {user: @user }
    else
      render text: "Something went wrong."
    end
  end

  private

  def user_params
    params.require(:user).permit(:name, :age, :country)
  end
end

routes.rb

Rails.application.routes.draw do
  get '/users', to: 'toy#index'
  get '/users/new', to: 'toy#new'
  post '/users/new', to: 'toy#create'
end
like image 546
emi Avatar asked Jul 16 '16 13:07

emi


1 Answers

TL;DR: you most likely just need to restructure the JSON you are sending to include the 'user' key


lengthier response:

you are using what are called 'strong params', so when you call user_params in #create and have require(:user), if the params hash does not have the word user as a key, the error you see above is raised.

one route would be to restructure the data you are sending to include the word 'user'

for instance:

{user: {name: 'test', age: 1}}

so maybe (could modify however you'd like to achieve the above structure)

$.ajax({
  url: '/users/new',
  dataType: 'json',
  type: 'POST',
  data: user,
  success: function(data) {
    this.setState({data: user});
  }.bind(this),
  error: function(xhr, status, err) {
    //this.setState({data: user});
    // console.error(this.props.url, status, err.toString());
  }.bind(this)
});

to

$.ajax({
  url: '/users/new',
  dataType: 'json',
  type: 'POST',
  data: {user: user},
  success: function(data) {
    this.setState({data: user});
  }.bind(this),
  error: function(xhr, status, err) {
    //this.setState({data: user});
    // console.error(this.props.url, status, err.toString());
  }.bind(this)
});
like image 128
Drew Avatar answered Oct 27 '22 17:10

Drew