Jae
Jae

Reputation: 1157

I have a bug in my HTML ERB file for Rails

I want to create a text field that accepts input and when you press the button next to it, it will save these changes to the database. It will be a PUT request, updating the value in the database for this specific user (not the logged in user, this is a page for admins to update values for users).

This is what the structure should be, (code to follow below):

1) Create text field and button for this in show.html.erb

2) Create a function called set_wistia_project_ID for this in users_controller.rb, set button equal to this :action

3) Create a helper function called set_project_id in user.rb that is called by set_wistia_project_ID, which actually updates the database. I decided to split it up into two functions because I noticed a lot of Rails projects tend to separate and break up functionality into the controller and model.

4) Edit my routes.rb to include some strange code, which I'll be honest, have no idea what it actually does. But without it, the entire app crashes on Heroku. So I leave it there. Found from a StackOverflow post.

My show.html.erb:

<% provide(:title, @user.name) %>
<div class="row">
  <aside class="col-md-4">
    <section class="user_info">
      <h1>
        <%= gravatar_for @user %>
        <%= @user.name %>
        <br>
        <%= @user.email %>
        <br>
        <div class="row">
          <div class="col-md-6 col-md-offset-3">
            <%= form_for(@user) do |f| %>
              <%= render 'shared/error_messages' %>

              <%= f.label :wistia_project_id %>
              <%= f.text_field :wistia_project_id, class: 'form-control' %>

              <%= button_to "Save", :action => "set_wistia_project_ID", :method => :put, :form_class => "form-control" %>   
          </div>
        </div>
      </h1>
    </section>
  </aside>
</div>

My users_controller.rb:

  # Sets wistia_project_ID.
  def set_wistia_project_ID
    @user = User.find(params[:id])
    @user.set_project_id
  end

My user.rb:

  # Sets the wistia_project_ID.
  def set_project_id
    self.wistia_project_ID # HOW TO SET EQUAL TO INPUT?
  end

My routes.rb:

Rails.application.routes.draw do
  root 'static_pages#home'
  get 'password_resets/new'
  get 'password_resets/edit'
  get 'sessions/new'
  get  '/help',    to: 'static_pages#help'
  get  '/about',   to: 'static_pages#about'
  get  '/contact', to: 'static_pages#contact'
  get  '/signup',  to: 'users#new'
  post '/signup',  to: 'users#create'
  get    '/login',   to: 'sessions#new'
  post   '/login',   to: 'sessions#create'
  delete '/logout',  to: 'sessions#destroy'
  resources :users do
    member do
      put 'set_wistia_project_ID'
    end
  end
  resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]
end

But the problem I am having is that when I try to go to show.html.erb, my Heroku app crashes :(

The reason:

F, [2019-06-25T19:53:20.706881 #8] FATAL -- : [b2ed08bb-de52-417f-9ba8-8ec85629dce8] 
app/views/users/show.html.erb:30: 
syntax error, unexpected end-of-input, expecting end

But it looks fine to me?

Upvotes: 0

Views: 415

Answers (1)

max pleaner
max pleaner

Reputation: 26768

The syntax error is that you are missing <% end %> for the <%= form_for(@user) do |f| %> block.

To answer your question about how to access the param in the model's method - you should pass it as an argument:

@user.set_project_id(params[:wistia_project_ID])

And change the method to accept an argument. Note, I am assuming you want to actually persist this to the database, so I'm adding a save call. You could alternatively call update which assigns the new value and saves in one go.

def set_project_id(val)
  self.wistia_project_ID = val # self is necessary here
  save # or self.save, but the self is unnecessary here
end

However, calling save does always succesfully save the record, there is still the possibility of an error if a model-level validation failed. You can handle this using flash: https://guides.rubyonrails.org/action_controller_overview.html#flash-now

or, if you don't need to redirect, can just use an instance variable to store the errors:

@user = User.find(params[:id])
@user.set_project_id(params[:wistia_project_ID])
unless @user.valid?
  @errors = @user.errors.full_messages
  render :show
end

and in the show view:

<% if @errors  %>
  <p>THE FORM COULD NOT BE SAVED </p>
  <ul id='errors'>
  <% @errors.each do |error| %>
    <li><%= error %></li>
  <% end %>
  </ul>
<% end %>

Also note, I would probably rename your set_project_id method to set_project_id! (added a bang), to signify that it mutates the input (changes its internal state).

Upvotes: 1

Related Questions