I am getting an error in my rails application. param is missing or the value is empty: contact
Home Controller
def contact
#contact = Contact.new(contact_params)
if #contact.save
redirect_to root_path
firstname = params[:contact][:firstname]
lastname = params[:contact][:lastname]
email = params[:contact][:email]
message = params[:contact][:message]
ContactMailer.contact_email(firstname, lastname, email, message).deliver
flash[:success] = "Thanks for your message, we will be in touch soon."
else
redirect_to home_contact_path
flash[:danger] = "Opps, there was a problem! Please fill out all the fields."
end
end
private
def contact_params
params.require(:contact).permit(:firstname, :lastname, :email, :message)
end
Mailer/Form
<div class="contact-form">
<%= simple_form_for #contact do |f| %>
<%= f.input :firstname, required: true %>
<%= f.input :lastname, required: true %>
<%= f.input :email, required: true %>
<%= f.input :message, required: true %>
<%= f.submit "Get in touch!", class: "btn btn-info" %>
<% end %>
</div>
Contact Page
<!DOCTYPE html>
<div class="jumbotron">
<h1 class="center-aligned">Contact Me</h1>
</div>
<div class="main-content">
<p class="center-aligned">You can contact me via the social media links at the bottom of the site or via the contact form below.</p>
<%= render 'home/mailer' %>
</div>
Contact.rb
class Contact < ActiveRecord::Base
validates_presence_of :firstname, :lastname, :email, :message
end
Server Log
Started GET "/home/contact" for 127.0.0.1 at 2016-05-17 14:13:13 -0500
Processing by HomeController#contact as HTML
Completed 500 in 6ms (ActiveRecord: 0.0ms)
ActionController::ParameterMissing (param is missing or the value is empty: contact):
app/controllers/home_controller.rb:28:in `contact_params'
app/controllers/home_controller.rb:9:in `contact'
Rendered /home/andy/.rvm/gems/ruby-2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_source.erb (21.9ms)
Rendered /home/andy/.rvm/gems/ruby-2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (9.8ms)
Rendered /home/andy/.rvm/gems/ruby-2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (3.5ms)
Rendered /home/andy/.rvm/gems/ruby-2.3.0/gems/actionpack-4.2.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (80.8ms)
Rendered /home/andy/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/_markup.html.erb (1.9ms)
Rendered /home/andy/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string (1.3ms)
Rendered /home/andy/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string (1.8ms)
Rendered /home/andy/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/style.css.erb within layouts/inlined_string (1.9ms)
Rendered /home/andy/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/console.js.erb within layouts/javascript (72.9ms)
Rendered /home/andy/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/main.js.erb within layouts/javascript (1.3ms)
Rendered /home/andy/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/error_page.js.erb within layouts/javascript (2.0ms)
Rendered /home/andy/.rvm/gems/ruby-2.3.0/gems/web-console-2.3.0/lib/web_console/templates/index.html.erb (135.5ms)
Please let me know if you need anything else. I am still learning Ruby on Rails.
You're not defining #contact when you render the form.
The action that renders the form need a code similar like #contact = Contact.new
On the other hand, you need to define a POST method for submit the form. Contact should be your post method where the form is submited and you need another action GET with the code that I give you before.
def contact
#contact = Contact.new(contact_params)
end
def create
if #contact.save
redirect_to root_path
firstname = params[:contact][:firstname]
lastname = params[:contact][:lastname]
email = params[:contact][:email]
message = params[:contact][:message]
ContactMailer.contact_email(firstname, lastname, email, message).deliver
flash[:success] = "Thanks for your message, we will be in touch soon."
else
redirect_to home_contact_path
flash[:danger] = "Opps, there was a problem! Please fill out all the fields."
end
end
routes.rb
resources :contacts
Simply your form parameter is empty, reason of getting the error from there. Also, you have to define your routes.
Form
<%= simple_form_for Contact.new, url: :contact_emailer do |f| %>
routes
post 'contact_emailer' => "contacts#contact", as: :contact_emailer
You get this error because you try to assign params here:
#contact = Contact.new(contact_params)
and since nothing has been submitted yet, and you specified that params.require(:contact) you get the error.
Here's what you do: as a good rails citizen create separate method for showing the form (usually new) and another one for submitting it (usually create)
It would look little bit like this:
def new
#contact = Contact.new # this is empty model, no data yet
end
def create
#contact = Contact.new(contact_params)
# ... and all the other fancy stuff you have there
end
don't forget to update your view filename to new.html.erb or call render in the controller.
It is possible to use one method to both show new form and handle request on submit but the separation to new/create is more clear.
Related
I'm very new to RoR. I'm trying to learn.
This is my user_controller update/edit part.
def edit
binding.break
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
#binding.break
if #user.update(params.require(:user).keep_if{|key| #user.attributes[key] != params[:user][key]}.permit(:username, :email, :password))
# Call to debugger
flash[:notice] = "Article was updated successfully."
redirect_to #user
else
#binding.break
flash[:notice] = "Article was not updated successfully."
render 'edit'
end
end
This is my edit.html.erb file
<h1>Edit an existing User</h1>
<% if #user.errors.any? %>
<h2>The following errors prevented the user from being saved</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<%= puts msg%>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<%= form_with(model: #user, local: true) do |f| %>
<p>
<%= f.label :username %><br/>
<%= f.text_field :username %>
</p>
<p>
<%= f.label :email %><br/>
<%= f.text_field :email %>
</p>
<p>
<p>
<%= f.label :password %><br/>
<%= f.password_field :password %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
The success case is working fine.
For the negative case where the update fails, I wanted to print the error messages for which the update failed and render it. But currently it just renders the edit page again. Also the #user in the else part of the controller is having the values which is invalid and those are getting filled in the edit page upon rendering. I want to reset to original values and show the errors for which it got failed.
The errors can be anything like, email format not correct or something.
Server logs says
↳ app/controllers/users_controller.rb:19:in `update'
TRANSACTION (0.2ms) rollback transaction
↳ app/controllers/users_controller.rb:19:in `update'
Rendering layout layouts/application.html.erb
Rendering users/edit.html.erb within layouts/application
Username has already been taken
Rendered users/edit.html.erb within layouts/application (Duration: 23.0ms | Allocations: 2337)
Rendered layout layouts/application.html.erb (Duration: 59.2ms | Allocations: 4962)
Completed 200 OK in 152ms (Views: 87.9ms | ActiveRecord: 5.0ms | Allocations: 11120)
Can someone shed some light on this?
render 'edit' with render edit without controller, you need to call #user = User.find(params[:id]) before render to get original value.
If you want to show errors message, grant it to other const and render it in views
def edit
binding.break
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
#binding.break
if #user.update(params.require(:user).keep_if{|key| #user.attributes[key] != params[:user][key]}.permit(:username, :email, :password))
# Call to debugger
flash[:notice] = "Article was updated successfully."
redirect_to #user
else
#binding.break
#errors = #user.errors
#user = User.find(params[:id])
flash[:notice] = "Article was not updated successfully."
render 'edit'
end
end
in view, using #errors.full_messages
I'm stuck trying to get my form with a collection_select to save. I have 3 models (Events, Users, Items), plus a joining model to link Items to Events (Event_Items).
My goal is for each users to be able to join events, and each user can specify a list of items they will bring to the event from an inventory that is unique to each user.
My form partial with collection select looks like this:
<%= form_for [#event, #event_items], remote: true do |f| %>
<%= f.hidden_field :user_id, value: current_user.id %>
<div class="form-group">
<%= f.collection_select(:item_id, current_user.items.all, :id, :title, { :prompt => "Select an Item", :selected => #item_id}, { class: "form-control"}) %>
</div>
<%= f.submit "Submit", class: "btn btn-primary", id: "event-item-button" %>
My event_items_controller looks like:
class EventItemsController < ApplicationController
before_action :authenticate_user!
def new
#event_item = EventItem.new
end
def create
#event_item = EventItem.new
#event = Event.find(params[:id])
if #event_item.save
flash[:success] = "Item Added to List"
redirect_to #event
else
flash.now[:danger] = "Please try again"
redirect_to #event
end
end
def destroy
#event_item = EventItem.find(params[:id])
end
private
def event_item_params
params.require(:event_item).permit(:event_id, :user_id, :item_id)
end
end
In the Event show page, I have this section where I iterate over each attendee and render the Event_Item partials:
<% #event.attendees.each do |user| %>
<div class="col-md-4">
#should render each existing item on the list.
#Doesn't work yet
<%= render 'event_items/event_item' %>
</div>
<% if user == current_user %>
#renders dropdown with only current user's inventory
#currently shows items correctly, just doesn't save to
#database
<%= render 'event_items/form' %>
<% end %>
<% end %>
Whenever I hit the Submit button after selecting an Item in the dropdown, nothing is saved to the database, although the server console shows:
Started POST "/Events/27/event_items" for 127.0.0.1 at 2018-09-26 19:54:32 -0500
Processing by EventItemsController#create as JS
Parameters: {"utf8"=>"✓", "event_item"=>{"user_id"=>"5", "item_id"=>"2"}, "commit"=>"Submit", "event_id"=>"27"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 5], ["LIMIT", 1]]
Completed 404 Not Found in 2ms (ActiveRecord: 0.3ms)
ActiveRecord::RecordNotFound (Couldn't find Event without an ID):
app/controllers/event_items_controller.rb:11:in `create'
In your create action, you do:
#event = Event.find(params[:id])
But, params doesn't have :id, it has :event_id. So, it should probably be:
#event = Event.find(params[:event_id])
And, your create action should probably look more like:
def create
#event = Event.find(params[:event_id])
#event_item = #event.event_items.new(event_item_params)
if #event_item.save
flash[:success] = "Item Added to List"
redirect_to #event
else
flash.now[:danger] = "Please try again"
redirect_to #event
end
end
By doing:
#event_item = #event.event_items.new(event_item_params)
event_id will be set on the new event_item. (This assumes, naturally, that Event has_many :event_items and EventItem belongs_to :event.)
I am fairly new to Ruby. I am trying to follow along with a tutorial for creating a simple posting app.
My create action will not work. I tried this and it seems to do something in the terminal, but it doesn't add it to my Posts object.
Here is my posts controller:
class PostsController < ApplicationController
def index
#posts = Post.all
end
def show
#post = Post.find(params[:id])
end
def new
#post = Post.new
end
def create
#post = Post.new(:title => params[:title], :content => params[:content])
#post.save
end
def edit
end
def update
end
def destroy
end
end
Here is my new view:
<h1>Add a New Post</h1>
<%= form_for #post do |f| %>
<p>
<%= f.label :title %>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :content %>
<%= f.text_area :content %>
</p>
<p>
<%= f.submit "Add a New Post" %>
</p>
<% end %>
This is what comes up in the terminal when I try to submit:
Started POST "/posts" for ::1 at 2016-08-31 17:54:39 -0700
ActiveRecord::SchemaMigration Load (16.4ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"tGpevHtpEoP5jHYqCn1G7tUKX9YWnx+PWkqlPzKadTCiIEX1UGs96mSCrDf UIShKjp+ObwNA6G1nh3KE5gAIgw==", "post"=>{"title"=>"Jack's Post", "content"=>"Please use this post"}, "commit"=>"Add a New Post"}
(0.1ms) begin transaction
SQL (16.0ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES (?, ?) [["created_at", 2016-09-01 00:54:40 UTC], ["updated_at", 2016-09-01 00:54:40 UTC]]
(14.7ms) commit transaction
No template found for PostsController#create, rendering head :no_content
Completed 204 No Content in 114ms (ActiveRecord: 31.3ms)
I feel like I've read about a million stack overflow posts about this and no one seems to have the answer. Any help would be very appreciated!
You've successfully inserted a record into the database. What do you want to happen next? How about:
redirect_to action: 'index'
You should use strong params to get the parameters you need from the form.
class PostsController < ApplicationController
def create
#post = Post.new(post_params)
#post.save
end
private
def post_params
params.require(:post).permit(:title, :content)
# params.require(:post).permit! # Allow all
end
end
If you want your exisiting solution to work, you would need to prefix the params like this:
#post = Post.new(:title => params[:post][:title], :content => params[:post][:content])
If you examine the logs, you'll see the form input is nested inside of post
"post"=>{"title"=>"Jack's Post", "content"=>"Please use this post"}
When you look in the logs it clearly says that I have rendered no view.
No template found for PostsController#create, rendering head :no_content
So in PostsController#create action we need to redirect to any action, mostly we redirect to show action. So you need add following line in create action.
# redirects user to show page of newly created post.
if #post.save
redirect_to #post
else
render 'new'
end
Go kill waves :)
I'm working through this Epicodus lesson and I just refactored my form partial for the new and edit views, but the new & edit actions are not working. When submitting the update, I'm getting the "name can't be blank" error.
Here's my new, create, edit & update actions in my contacts_controller:
def new
#contact = Contact.new
end
def create
#contact = Contact.new name: params[:name],
email: params[:email],
phone: params[:phone]
if #contact.save
flash[:notice] = "#{#contact.name} added."
redirect_to contacts_path
else
render 'new'
end
end
def edit
#contact = Contact.find(params[:id])
end
def update
#contact = Contact.find(params[:id])
if #contact.update name: params[:name],
email: params[:email],
phone: params[:phone]
flash[:notice] = 'Contact updated.'
redirect_to contact_path(#contact)
else
render 'edit'
end
end
My edit view:
<% content_for(:title, "Edit #{#contact.name} | Wikipages") %>
<h1>Edit <%= #contact.name %></h1>
<%= render 'errors'%>
<%= render 'form'%>
<p><%= link_to 'Return to contacts', '/contacts' %></p>
My new view:
<% content_for(:title, "New contact | Wikipages") %>
<h1>New contact</h1>
<%= render 'errors'%>
<%= render 'form'%>
<p><%= link_to 'Return to contacts', '/contacts', class: 'btn btn-default' %></p>
My form partial:
<%= form_for(#contact) do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="form-group">
<%= f.label :phone %>
<%= f.text_field :phone %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<%= f.submit(class: "btn btn-primary")%>
<% end %>
And my routes:
Rails.application.routes.draw do
root 'contacts#index'
resources :contacts do
resources :phones
end
end
Here's the output from my log for the new:
Started POST "/contacts" for 127.0.0.1 at 2014-09-23 07:00:34 -0400
Processing by ContactsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"q59xzpBWXEs58qStmPcnpEqm89finUQKiUvYsjRYm8Q=", "contact"=>{"name"=>"Lance", "phone"=>"", "email"=>""}, "commit"=>"Create Contact"}
(2.1ms) BEGIN
(0.2ms) ROLLBACK
Rendered contacts/_errors.html.erb (0.6ms)
Rendered contacts/_form.html.erb (3.2ms)
Rendered contacts/new.html.erb within layouts/application (6.0ms)
Completed 200 OK in 214ms (Views: 207.5ms | ActiveRecord: 2.3ms)
Here's the output from my log for the edit:
Started PATCH "/contacts/12" for 127.0.0.1 at 2014-09-23 06:48:02 -0400
Processing by ContactsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"q59xzpBWXEs58qStmPcnpEqm89finUQKiUvYsjRYm8Q=", "contact"=>{"name"=>"Chuck Wight", "phone"=>"435345345e", "email"=>"desfwrf#er.com"}, "commit"=>"Update Contact", "id"=>"12"}
Contact Load (0.3ms) SELECT "contacts".* FROM "contacts" WHERE "contacts"."id" = $1 LIMIT 1 [["id", 12]]
(0.1ms) BEGIN
(0.4ms) ROLLBACK
Rendered contacts/_errors.html.erb (0.5ms)
Rendered contacts/_form.html.erb (4.4ms)
Rendered contacts/edit.html.erb within layouts/application (7.2ms)
Completed 200 OK in 208ms (Views: 201.0ms | ActiveRecord: 0.8ms)
Any thoughts?
Your params nested under contact and you are passing params to your create and update action directly. So try paarams[:contact][:email] instead of params[:email]
Like this :
def create
#contact = Contact.new name: params[:contact][:name],
email: params[:contact][:email],
phone: params[:contact][:phone]
if #contact.save
flash[:notice] = "#{#contact.name} added."
redirect_to contacts_path
else
render 'new'
end
end
def update
#contact = Contact.find(params[:id])
if #contact.update name: params[:contact][:name],
email: params[:contact][:email],
phone: params[:contact][:phone]
flash[:notice] = 'Contact updated.'
redirect_to contact_path(#contact)
else
render 'edit'
end
end
Clearly in your update action your are getting #contact as nil. So try make changes I suggested in your controller action. Hope this help you.
2nd Update
This is the code in my model
after_initialize :start_two_weeks
def start_two_weeks
#subscription = TrialSubscription.all
#subscription.manual_expiry_date =
#subscription.save
end
How do you set the time dynamically from Time.now to Time.now - 2 weeks?
Its a datetime field what is the value for a datetime field?
More Update
this means I didn't log out
Filter chain halted as :require_no_authentication rendered or redirected
I logged out and the user did get created but its through the registration controller.....
Updated
I just realized that the form is posting to /users. The registrations controller is inheritting from devise::registration
Started POST "/users" for 127.0.0.1 at 2014-03-23 19:58:08 -0400
Processing by RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"8xhRi7TBEA+zXfmuzuJLqLjjo5JMkyEjUmgmRT6DsOQ=", "user"=>{"email"=>"helloworld#gmail.com", "password"=>"[FILTERED]"}, "commit"=>"Create User"}
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Redirected to http://localhost:3000/
Filter chain halted as :require_no_authentication rendered or redirected
Completed 302 Found in 4.1ms (ActiveRecord: 0.7ms)
The form isn't posting to here
new_trial_subscription GET /trial_subscriptions/new(.:format) trial_subscriptions#new
POST /trial_subscriptions(.:format) trial_subscriptions#create
Ok I am trying to reproduce the stuff that I did in rails console to put them into the controllers.
I have two models
class TrialSubscription < ManualSubscription
accepts_nested_attributes_for :user
attr_accessible :user_attributes
end
ManualSubscription inherits from Subscription and in Subscription model
belongs_to :user
I am building the user model through subscription because of some other reason.
in my rails console I did these
#subscription = TrialSubscription.new
#user = #subscription.build_user(email: "helloworld#gmail.com", password: "thisiseightcharacters")
#subscription.save
I am able to create a user and its associated trial subscription at the same time. I am trying to reproduce this in the controller and the content will be user inputted.
This is my form in
app/views/trial_subscriptions/new.html.erb
<%= simple_form_for #subscription.user do |f| %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.button :submit %>
<% end %>
I added
resources :trial_subscriptions
so the url is trial_subscriptions/new
this is my controller
class TrialSubscriptionsController < ApplicationController
def index
end
def new
#subscription = TrialSubscription.new
#subscription.build_user
end
def create
#subscription = TrialSubscription.new(params[:subscription])
#subscription.email = :email
#subscription.password = :password
if #subscription.save
flash[:notice] = "Trial Subscription has started"
else
flash[:error] = "There was an error creating this subscription, please try again"
end
end
end
1) What is happening between new and create?
2) in my create method the params[:subscription] is pointing to the #subscription object in my form is this correct?
3) The :email is actually user attribute, is it getting passed correctly at #subscription.email = :email?
Your new action looks correct, your create action needs some update. Let's first start from your association then move on to the form and then to your create action.
In the form view code, you are building a form for #subscription.user. The simple_form_for method would translate this to create action in UsersController. But you do not have this and your intention is to create user through TrialSubscriptionsController.
So in order to make this happen, you need to change the form so that when it renders and/or submits it creates the form for trial_subscription along with the defined user_attributes within trial_subscription. So, update your view to:
<%= simple_form_for #subscription do |f| %>
<%= f.simple_fields_for :user do |u| %>
<%= u.input :email %>
<%= u.input :password %>
<% end %>
<%= f.button :submit %>
<% end %>
The changes are simple_form_for #subscription.user to simple_form_for #subscription, and wrapping email and password fields with f.simple_fields_for :user. With these changes, when your form submits, it will execute the create action of the TrialSubscriptionsController.
The next change is on the TrialSubscriptionsController#create action.
def create
#subscription = TrialSubscription.new(params[:trial_subscription])
if #subscription.save
flash[:notice] = "Trial Subscription has started"
else
flash[:error] = "There was an error creating this subscription, please try again"
end
end
The changes here are #subscription = TrialSubscription.new(params[:subscription]) to #subscripition = TrialSubscription.new(params[:trial_subscription]), this is because your object is of type TrialSubscription not Subscription.
The second change is removal of the following lines:
#subscription.email = :email
#subscription.password = :password
This is because, as you say, email and password are members of user not trial_subscription.
Hopefully this helps.