Ruby on Rails form helper - mysql

I am very new to Rails and have been having some trouble trying to find tutorials that actually work for me. I am attempting to create a database in MySQL and then allow users to submit information to this database through a form. I was able to create a form using the code below but it only triggers the new method in the Controller and not the create method. Does anyone know why this is happening and/or can guide me to a good tutorial for building forms. I have found some in google but for some reason the syntax never works for me when I try to enter it. Thank you very much in advance for any help you can give.
Controller -
class MessageController < ApplicationController
def new
#message = Message.new
end
def create
#message = Message.new
#message.message=params[:mess]
#message.user=params[:name]
if #message.save
redirect_to "http://itworks.com"
end
end
end
View -
<%= form_for :MessageController do |f| -%>
Message: <%= f.text_field :mess %><br />
UserName: <%= f.text_field :name %><br />
<%= f.submit%>
<% end -%>
Edit - When I change :MessageController to #message or :message I get a syntax error. (syntax error, unexpected keyword ensure, expecting $end. Surprisingly enough the form works with :MessageController but it only triggers the new method not the create method.

form_for expects either an instance of a model, or a symbol representing the name of a variable containing an instance of a model. You've given it the name of a controller.
Use this:
<%= form_for :message do |f| -%>
or thiS:
<%= form_for #message do |f| -%>

Since you're new, let me explain some things for you:
--
form_for
<%= form_for #message do |f| -%>
<%= f.label :mess %>
<%= f.text_field :mess %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
When you use form_for, you basically need to populate it with an ActiveRecord object. Currently, you're using the MessageController class, which is totally wrong. You've already set the #message object in your controller - you just need to populate your form_for method with it
--
Strong Params
Secondly, as I already mentioned in your other question, you need to ensure you're using the strong params functionality of Rails correctly:
#app/controllers/message_controller.rb
Class MessageController < ApplicationController
def create
#message = Message.new(message_params)
#message.save
end
private
def message_params
params.require(:message).permit(:mess, :user)
end
end

I'm still pretty new to Rails as well, but it looks like your syntax for the form_for method is off a bit. Here's the example from the rails guide for form helpers:
<%= form_for #article, url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
<%= f.text_field :title %>
<%= f.text_area :body, size: "60x12" %>
<%= f.submit "Create" %>
<% end %>
And here's the link to the form helper page: http://guides.rubyonrails.org/form_helpers.html
I've found the rubyonrails.org guides to be the best resource for trouble-shooting. The documentation is actually quite good(both extensive and clear).

I guess that maybe caused by the "Strong parameter",
to learn more you can see Strong Parameters by Example here.
In the Messages controller, we could add the strong parameter to it
class MessageController < ApplicationController
def new
#message = Message.new
end
def create
#message = Message.new(message_params)
#message.message=params[:mess]
#message.user=params[:name]
if #message.save
redirect_to "http://itworks.com"
end
end
private
def message_params
params.require(:message).permit(:mess, :name)
end
end
Because you define the #message , so..why not use it?
<%= form_for #message do |f| %>
Message: <%= f.text_field :mess %><br />
UserName: <%= f.text_field :name %><br />
<%= f.submit%>
<% end %>

Related

Multiple radio buttons getting selected in Rails app

I have an app where Question model has_many relationship with Option. I also have a button to add options while creating a question. Every question has only one correct answer. So when I create a question and click on Add Option button, new option is created but the new radio button associated with it has different name. In fact the name of radio button is of the form question[options_attributes][i][is_answer] where i is id. As far as I know radio buttons should have the same name to work as a collection or group. So how can I make it work as a group even if I create any number of options for a single question?
html.erb
<%= form_for #question do |form| %>
<div class="field">
<%= form.label :body %>
<%= form.text_area :body %>
</div>
<%= form.fields_for :options, question.options.each do |a| %>
<div class="field">
<%= a.label :options %>
<%= a.text_area :body %>
<%= a.radio_button :is_answer, "options" %>
<%= a.check_box :_destroy %>
<%= a.label :_destroy, 'delete' %>
</div>
<% end %>
<%= form.submit 'Add option', :name => "add_option" %>
<%= form.submit 'Delete options', :name => "remove_option" %>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
controller.rb
class QuestionsController < ApplicationController
def new
#question = Question.new
#question.options.build
end
def create
#question = Question.new(question_params)
#question.user = current_user
if params[:add_option]
#question.options.build
else
respond_to do |format|
if #question.save
format.html { redirect_to #question, notice: 'Question was successfully created.' and return }
format.json { render :show, status: :created, location: #question }
else
format.html { render :new }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
render :action => 'new'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_question
#question = Question.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def question_params
params.require(:question).permit(:body, options_attributes: [:id, :body, :question_id, :created_at, :updated_at, :is_answer])
end
end
There are two options:
Using JavaScript on the client-side to uncheck the radio buttons.
Using radio buttons with the same name. It this case you will have to change the way you pass the :is_answer parameter and manually assign the value in options_attributes.
Method 1 details:
See this question radio different names - only check one
Method 2 details:
Instead of passing :is_answer parameter for each option you can pass a single parameter for the question having chosen answer id as the value. Lets name it "answer_id". We want this parameter to be in the params[question]
hash in the controller, so the whole name will be "question[answer_id]". Although radio buttons are generated for each option, only the chosen one will be sent to the server as they all have the same name.
<%= form.fields_for :options, question.options.each do |a| %>
<div class="field">
<%= a.label :options %>
<%= a.text_area :body %>
<%= radio_button_tag "question[answer_id]", a.object.id, a.object.is_answer? %>
<%= a.check_box :_destroy %>
<%= a.label :_destroy, 'delete' %>
</div>
<% end %>
https://apidock.com/rails/v4.2.7/ActionView/Helpers/FormTagHelper/radio_button_tag
In the controller you will have to manually assign the option's is_answer parameter based on the answer_id value.
def question_params
result = params.require(:question).permit(:body, :answer_id, options_attributes: [:id, :body, :question_id])
answer_id = result.delete(:answer_id)
result[:options_attributes].values.each do |option_attrs|
option_attrs[:is_answer] = option_attrs[:question_id] == answer_id
end
result
end
If you need further details please let me know. I will update the answer to give more information.

Rails: Form_for: No route matches {:action=>"show", :controller=>"posts"} missing required keys: [:id]

I am completely new to RoR and was trying to build a simple blog, but already got stuck at the "Adding Post" function.
The following Error Message pops up when I load .../posts/new:
No route matches {:action=>"show", :controller=>"posts"} missing required keys: [:id]
Here is what my posts controller looks like this:
class PostsController < ApplicationController
def index
end
def new
end
def create
render plain: params[:post].inspect
end
end
Here is what my new.html.erb looks like this:
<h1>Add Post</h1>
<%= form_for :post, url: posts_path do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
I had set posts as resource in my routes. The surprising thing is, that on my friend's laptop, the code works.
I would be very happy about any advice, and apologize for the silly question.
The form_for helper is looking for a resource object to operate with, and you're giving it a symbol. I suspect it's assuming that's an action URL instead, and translating (or trying to) that symbol into a route.
Using form_for in a new action, the pattern is usually to create a new resource and feed that into the form_for helper:
def new
#post = Post.new
end
<%= form_for #post, url: posts_path do |f| %>
...
<% end %>
Check your routes with:
$rake routes
And you'll see that the posts_path with an id its used to update a "post" and not to create one, you'll also found the path you want to create a new "post".
You might say: but i don't have an update action. If on your routes file you used the resources keyword you do, even if the action itself is missing.
Update:
Remove the
url: post_path
From your form_for call
My recommendation, check out the rails guides on routing.

Getting a form get parameter

I am having trouble reading the business_id parameter from a form get request.
http://localhost:3000/clients?utf8=%E2%9C%93&client%5Bbusiness_id%5D=toyota&commit=Save+Client
With: params[:business_id]
Why doesn't that work?
Details:
html form:
<%= form_for :client, url:clients_path, method: :get do |f| %>
<%= f.label :business_id %><br>
<%= f.text_field :business_id %>
<%= f.submit%>
<% end %>
The form hits the create controller and redirects back to the original page:
def create
#clients = Client.all
redirect_to controller: 'clients'
end
On the original page reads the url string in the index controller with:
def index
#clients = Client.all
#filters = params[:business_id]
end
#filters comes back as blank unless I hard code a value.
You need to use params[:client][:business_id] as business_id is inside client hash.

passing params throught rails forms

I am using rails 4 and have a subject and comment models. Subject is a one to many relationship with comments. I want a simple page that can add comments to many subjects on the same page. So in my form I know how to submit a comment to create but I dont know how to find the right subject in my controller to add it to. Any advice?
class CommentsController < ApplicationController
def create
comment = Comment.create(comment_params)
if comment.save
# The line below is incorrect, I dont know what to do
Subject.find(params[:subject_id]).comments << comment
redirect_to(:controller => 'static_pages', action: 'home')
end
end
def new
end
private
def comment_params
params.require(:comment).permit(:text, :user_name)
end
end
StaticPages#home Find me in
app/views/static_pages/home.html.erb
<% #subjects.each do |subject| %>
<div class="subjects <%= cycle('odd', 'even') %>">
<h1><%= subject.name %></h1>
<h3><%= subject.description %></h3>
<% subject.comments.each do |comment|%>
<div class="comment">
<h4><%= comment.user_name%></h4>
<%= comment.text %>
</div>
<% end %>
<%= form_for(#comment) do |f| %>
<%= f.label :user_name %>
<%= f.text_field :user_name %>
<%= f.label :text %>
<%= f.text_field :text %>
<%= f.submit('Create comment', subject_id: subject.id) %>
<% end %>
</div>
<% end %>
The simplest way would be to populate the subject_id attribute of your #comment form, like this:
<%= form_for(#comment) do |f| %>
<%= f.label :user_name %>
<%= f.text_field :user_name %>
<%= f.label :text %>
<%= f.text_field :text %>
<%= f.hidden_field :subject_id, value: subject.id %>
<%= f.submit('Create comment', subject_id: subject.id) %>
<% end %>
This will populate the subject_id attribute of your new Comment object, which will essentially associate it through Rails' backend:
#app/controllers/your_controller.rb
Class YourController < ApplicationController
def create
#comment = Comment.new comment_params
#comment.save
end
private
def comment_params
params.require(:comment).permit(:subject_id, :text, :user_name)
end
end
--
foreign_keys
This works because of the Rails / relational database foreign_keys structure
Every time you associate two objects with Rails, or another relational database system, you basically have a database column which links the two. This is called a foreign_key, and in your case, every Comment will have the subject_id foreign_key column, associating it with the relevant subject
So you may have many different forms using the same #comment variable - the trick is to populate the foreign_key for each one

log in page fails at form tag definitions

I have the following code snippet
<%= form_tag :action => 'process_login'%>
Username: <%= text_field "user", "fullname" %>
Password: <%= password_field "user", "password" %>
<%= submit_tag %>
<%= end_form_tag %>
that is used as an index.rb page to log in my system.
The controller index function looks like this
def index
#user=MyEmployee.new
#user.fullname=params[:fullname]
#user.password=params[:password]
end
The error is
undefined local variable or method `end_form_tag' for #<#<Class:0x5cbe468>:0x5cbcb60>
what should I add or change to make it work ?
UPDATE
And here is my process_login function
def process_login
if user=MyEmployee.authenticate(params[:fullname])
session[:id]=user.id
redirect_to session[:return_to]
else
flash[:error]='Login fails, unauthenticated user'
redirect_to :action => 'login', :fullname=>params[:user][:fullname]
end
end
You're using a very, very old syntax there. end_form_tag was deprecated in Rails 2.
Use this syntax instead:
<%= form_tag :action => 'process_login' do%>
Username: <%= text_field "user", "fullname" %>
Password: <%= password_field "user", "password" %>
<%= submit_tag %>
<% end %>
Whatever guide has you using end_form_tag is really old and shouldn't be used any more. I would recommend following the Rails Tutorial.