My rails form skips validation and doesn't save. Any ideas on why this is happening?
What ends up happening is that the form submits and it goes to the create action, but it skips the validation completely set up in contact.rb and this line in the contact controller's #contact.save doesn't save and it goes to the else.
This is what gets printed in the terminal server window after the contact form gets submitted with dummy data:
logged in #<Contact:0xb60b3978>
Started POST "/contacts" for 127.0.0.1 at 2013-08-11 17:04:46 -0400
Processing by ContactsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"zbEGKGXz1t2Os6VjVOMzcfeHru9sBfoBaF6tgr16qPo=", "contact"=>{"name"=>"", "email"=>"", "subject"=>"", "body"=>""}, "category"=>"bug", "commit"=>"Contact Us"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 3]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 3]]
(0.1ms) begin transaction
(0.1ms) rollback transaction
Redirected to http://localhost:3000/contact
Completed 302 Found in 9ms (ActiveRecord: 0.3ms)
Started GET "/contact" for 127.0.0.1 at 2013-08-11 17:04:46 -0400
Processing by ContactsController#new as HTML
Rendered common/_form_errors.html.erb (0.0ms)
Rendered contacts/_contact_form.html.erb (2.3ms)
Rendered contacts/new.html.erb within layouts/application (2.9ms)
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 3]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 3]]
Rendered common/_search_form.html.erb (0.5ms)
Rendered layouts/_navbar.html.erb (4.2ms)
Rendered layouts/_flashmessages.html.erb (0.1ms)
Rendered layouts/_footer.html.erb (0.0ms)
Completed 200 OK in 72ms (Views: 71.2ms | ActiveRecord: 0.2ms)
Contact.rb:
class Contact < ActiveRecord::Base
belongs_to :user
attr_accessible :body, :category, :email, :name, :subject
validates :body, presence: true, length: { in: 10..255 }
validates :category, presence: true
validates :name, presence: true
validates :email, presence: true
validates :subject, presence: true
end
_contact_form.html.erb:
<%= form_for(#contact) do |f| %>
<%= render 'common/form_errors', object: #contact %>
<div class="span4">
<div class="well">
<%= f.label :name, "What's your name?" %>
<%= f.text_field :name, :class => "field span4" %>
</div>
<div class="well">
<%= f.label :email, "Your Email so we can hit you back." %>
<%= f.text_field :email, :class => "field span4" %>
</div>
<div class="well">
<%= f.label :category, "Pick one:" %>
<%= select_tag(:category,
options_for_select(
[['I found a bug.', 'bug'], ['I have a suggestion.', 'suggestion'], ['other', 'other']]
)) %>
</div>
<div class="well">
<%= f.submit "Contact Us", :class=> "marginTopBottom" %>
</div>
</div>
<div class="span4">
<div class="well">
<%= f.label :subject, "Subject:" %>
<%= f.text_field :subject, :class => "field span4" %>
</div>
<div class="well">
<%= f.label :body, "What's Up?" %>
<%= f.text_area(:body, :rows => 7, :class => "field span4") %>
</div>
</div>
<% end %>
contacts/new.html.erb:
<%= provide(:navActive, 'Contact Us') %>
<h1>Contact Us</h1>
<div class="row">
<%= render 'contact_form' %>
</div>
contacts_controller.rb:
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
if logged_in?
#contact = current_user.contacts.build(params[:contact])
puts "logged in #{#contact}" # prints out when logged in
else
#contact = Contact.new(params[:contact])
#contact.user_id = 999999
puts "not logged in #{#contact}" # prints out when not logged in
end
if #contact.save
flash[:success] = "Your message was sent and we'll get back to you as soon as possible!"
# send an email to offering poster about the new request
UserMailer.contact(#contact, sent_at = Time.now).deliver
redirect_to contact_path
else
flash[:success] = "Your message was not sent. Something went wrong. Please contact pavankat#gmail.com."
redirect_to contact_path
end
end
end
routes.rb
resources :contacts, only: [:new, :create]
schema.rb:
create_table "contacts", :force => true do |t|
t.string "name"
t.string "email"
t.string "category"
t.string "subject"
t.string "body"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "user_id"
end
add_index "contacts", ["user_id"], :name => "index_contacts_on_user_id"
I don't think it's skipping the validation, I think there's no way for your page to show the error.
You need to add <%= flash[:success] %> somewhere on the page.
You can also output errors for the contact object, which might help!
(You may refute this by posting the content of common/form_errors -
It should be:
<%= f.select(:category,
options_for_select(
[['I found a bug.', 'bug'], ['I have a suggestion.', 'suggestion'], ['other', 'other']]
)) %>
Related
This is my views/devise/registrations/edit.html.erb:
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: "edit-user-form m-t" }) do |f| %>
<%= f.error_notification %>
<div class="form-group">
<%= f.input_field :email, required: true, autofocus: true %>
</div>
<div class="form-group">
<%= f.input_field :current_password, hint: "we need your current password to confirm your changes", placeholder: "current password", required: true %>
</div>
<div class="form-group">
<%= f.input_field :password, autocomplete: "off", hint: "leave it blank if you don't want to change it", placeholder: "new password", required: false %>
</div>
<div class="form-group">
<%= f.input_field :password_confirmation, placeholder: "confirm new password", required: false %>
</div>
<div class="form-group">
<%= f.association :school, collection: School.where(school_type: [:college, :university]), prompt: "Choose a school", class: 'col-lg-4 form-control', label: false %>
</div>
</div>
<div class="form-group">
<div class="col-lg-12 text-center">
<%= f.button :submit, "Update", class: "btn btn-lg edit-account-update-button" %>
</div>
</div>
<% end %>
And this is my ApplicationController:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
check_authorization :unless => :devise_controller?
rescue_from CanCan::AccessDenied do |exception|
respond_to do |format|
format.json { head :forbidden }
format.html { redirect_back(fallback_location: root_path, flash: { danger: exception.message }) }
end
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:account_update, keys: [:avatar, :avatar_cache, :remove_avatar, :school_id])
end
end
The issue though is that it isn't updating the record, here is the log from that operation:
Started PUT "/users" for ::1 at 2016-11-02 19:22:59 -0500
Processing by DeviseInvitable::RegistrationsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Xo445XVpElgDmfcjywZKEbsXIqZR/2Wgw==", "user"=>{"remove_avatar"=>"0", "avatar_cache"=>"", "email"=>"coach#test.com", "current_password"=>"[FILTERED]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "school_id"=>"3"}, "commit"=>"Update"}
User Load (4.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 7], ["LIMIT", 1]]
User Load (9.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 7], ["LIMIT", 1]]
(0.7ms) BEGIN
SQL (4.2ms) UPDATE "users" SET "updated_at" = $1, "avatar" = $2 WHERE "users"."id" = $3 [["updated_at", 2016-11-03 00:22:59 UTC], ["avatar", "a1.jpg"], ["id", 7]]
(0.8ms) COMMIT
Redirected to http://localhost:3000/
Completed 302 Found in 139ms (ActiveRecord: 19.1ms)
Note that the school_id is set in the params, so we know it properly accepts the input from the form. But the SQL UPDATE statement, doesn't include school_id, so it doesn't actually save that info to the DB.
Also note that there are no unpermitted params messages in the log.
What could be causing this?
Edit 1
This is the School.rb model:
class School < ApplicationRecord
has_many :users
enum school_type: { high_school: 0, college: 1, university: 2 }
end
This is the User.rb model:
class User < ActiveRecord::Base
belongs_to :school
end
The problem was that your devise model User was inheriting ActiveRecord::Base instead of ApplicationRecord which is an abstract class in Rails 5. With the inheritance of latter, most of the gems which deal with models can and do modify the code of ActiveRecord::Base in their own context without affecting other models, which isn't possible if you inherit the former.
Source: Why Rails 5 uses ApplicationRecord instead of ActiveRecord::Base?
I am trying to nest a user to an account and allow the user to be created when the account is created. I am having an issue when creating both the account and user from the same form, and my server output is not very helpful in trying to isolate the problem.
here is the output when I try to save the Account and User.
Started POST "/accounts" for ::1 at 2016-10-10 20:55:23 -0600
Processing by AccountsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"UK7h4edNzRomi7JGomoZD1ayYmlNxI/h2ZH+NEaJxWQzcFsYAJujr5EDDS2HeprAX41IuS5/crRxmXYz80YpYw==", "account"=>{"subdomain"=>"mydomain", "owner_attributes"=>{"email"=>"swilson#ta#####td.com", "f_name"=>"S####", "l_name"=>"W####", "date_of_birth"=>"19##-##-##", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}, "commit"=>"Create Account"}
(0.3ms) BEGIN
User Exists (0.3ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 LIMIT $2 [["email", "swilson#ta#####td.com"], ["LIMIT", 1]]
Account Exists (0.3ms) SELECT 1 AS one FROM "accounts" WHERE "accounts"."subdomain" IS NULL LIMIT $1 [["LIMIT", 1]]
(0.2ms) ROLLBACK
Rendering accounts/new.html.erb within layouts/application
Rendered accounts/_form.html.erb (3.8ms)
Rendered accounts/new.html.erb within layouts/application (5.1ms)
Rendered shared/_signed_out_nav.html.erb (1.3ms)
Completed 200 OK in 183ms (Views: 44.2ms | ActiveRecord: 1.1ms)
I believe the issue may have something to do with the account generation and the subdomain. but I Can not pin it down for the life of me!
also I commented out my personal info with the ####...
here is my account controller
class AccountsController < ApplicationController
def new
#account = Account.new
#account.build_owner
end
def create
#account = Account.new(account_params)
respond_to do |format|
if #account.save
format.html {redirect_to root_path, notice: 'Account successfully created.'}
else
format.html {render :new, alert: 'There was a problem, please try again.'}
end
end
end
private
def account_params
params.require(:account).permit(:subdomain, owner_attributes: [:email, :password, :password_confirmation, :f_name, :l_name, :date_of_birth])
end
def set_account
#account = Account.find(params[:id])
end
end
here is my account form:
<%= bootstrap_form_for(#account) do |f| %>
<div class="row">
<div class="col-xs-12">
<%= f.text_field :subdomain, hide_label: true, placeholder: 'Company Name', append: ".patrolvault.net" %>
</div>
</div>
<%= f.fields_for :owner do |o| %>
<div class="row">
<div class="col-xs-12">
<%= o.email_field :email, label: 'Email Address' %>
</div>
<div class="col-xs-12">
<%= o.text_field :f_name, label: 'First Name' %>
</div>
<div class="col-xs-12">
<%= o.text_field :l_name, label: 'Last Name' %>
</div>
<div class="col-xs-12">
<%= o.date_field :date_of_birth, label: 'Date Of Birth' %>
</div>
<div class="col-xs-6">
<%= o.password_field :password, label: 'Password' %>
</div>
<div class="col-xs-6">
<%= o.password_field :password_confirmation, label: 'Confirm Password' %>
</div>
</div>
<% end %>
<%= f.submit :class => 'btn btn-primary' %>
<% end %>
and here is my account model:
class Account < ApplicationRecord
# Before Actions
before_validation :downcase_subdomain
# Relationships
belongs_to :owner, class_name: 'User', optional: true
accepts_nested_attributes_for :owner
# Validations
validates :owner, presence: true
RESTRICTED_SUBDOMAINS = %w(www, patrolvault, test)
validates :subdomain, presence: true,
uniqueness: { case_sensitive: false },
format: { with: /\A[\w\-]+\Z/i, message: 'Contains invalid characters.' },
exclusion: { in: RESTRICTED_SUBDOMAINS, message: 'Restricted domain name'}
# Custom Methods
private
def downcase_subdomain
self.subdomain = subdomain.try(:subdomain)
end
end
Please let me know if you require further info or if I have missed something! Thanks!
so the problem was in my before_validation :downcase_subdomain. once I removed that and the matching method everything began to work fine. I will rework this.
Thanks.
The attachment resume seems to works fine, but i do not have any insert into database (null, null, null , null) and i do not have file uploaded to any folder in my app...
class AddAttachmentCvToUsers < ActiveRecord::Migration
def change
change_table :users do |t|
t.attachment :cv
end
end
end
User model :
attr_accessor :cv
validates_attachment :cv
has_attached_file :cv, :path=>":rails_root/storage/#{Rails.env}#{ENV['RAILS_TEST_NUMBER']}/."
I have also installed carrierwave but still no effects..
Edit:
User Controller (I do not have another controller for attachments) :
class UsersController < ApplicationController
def new
#users = User.new
end
def create
#user = User.new(user_params)
if #user.save
session[:user_id] = #user.id
current_user = #user.id
redirect_to '/status'
else
redirect_to '/signup'
end
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :PESEL, :phone, :password,:cv)
end
end
View for new user with attachement:
<div class="login">
<div class="container">
<div class="form">
<h1>SIGN UP</h1>
<%= form_for #users,:html=> {:multipart=>true} do |f| %>
<%= f.text_field :first_name, :placeholder => "First name" %>
<%= f.text_field :last_name, :placeholder => "Last name" %>
<%= f.email_field :email, :placeholder => "Email" %>
<%= f.text_field :PESEL, :placeholder => "PESEL number" %>
<%= f.phone_field :phone, :placeholder => "Phone Number" %>
<%= f.password_field :password, :placeholder => "Password" %>
<p>CV</p>
<%= f.file_field :cv, name: "CV", class: 'form-control' %>
<%= f.submit "Sign up", class: "btn-submit" %>
<% end %>
</div>
</div>
</div>
Some logs from console:
Started POST "/users" for 127.0.0.1 at 2016-05-18 03:55:17 +0200
Processing by UsersController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Fw6easThY51CDppDDVfqO0ProQITaltqP3DaIL3An67ey4vGXh2yEerhhhxoo3bTp/mKbkIaAmktzBviBIjg8g==", "user"=>{"first_name"=>"Test", "last_name"=>"Test", "email"=>"test#t.pl", "PESEL"=>"91020300441", "phone"=>"609123123", "password"=>"[FILTERED]"}, "CV"=>#<ActionDispatch::Http::UploadedFile:0x007f25790c1b60 #tempfile=#<Tempfile:/tmp/RackMultipart20160518-26849-rqaabr.pdf>, #original_filename="pdf-test.pdf", #content_type="application/pdf", #headers="Content-Disposition: form-data; name=\"CV\"; filename=\"pdf-test.pdf\"\r\nContent-Type: application/pdf\r\n">, "commit"=>"Sign up"}
(0.1ms) BEGIN
User Exists (1.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = BINARY 'test#t.pl' LIMIT 1
User Exists (0.1ms) SELECT 1 AS one FROM `users` WHERE `users`.`PESEL` = BINARY '91020300441' LIMIT 1
SQL (0.1ms) INSERT INTO `users` (`first_name`, `last_name`, `email`, `PESEL`, `phone`, `password_digest`, `created_at`, `updated_at`) VALUES ('Test', 'Test', 'test#t.pl', '91020300441', '609123123', '$2a$10$HmHAiJkHv1Tada/OpzKXKOISiwumoFKTy48tFpNBYuATq/A5GaC9G', '2016-05-18 01:55:17', '2016-05-18 01:55:17')
SQL (1.0ms) INSERT INTO `job_apps` (`user_id`, `created_at`, `updated_at`) VALUES (35, '2016-05-18 01:55:17', '2016-05-18 01:55:17')
(3.0ms) COMMIT
Redirected to http://localhost:3000/status
Completed 302 Found in 135ms (ActiveRecord: 8.2ms)
Started GET "/status" for 127.0.0.1 at 2016-05-18 03:55:17 +0200
Processing by JobAppsController#index as HTML
You have overridden the name attribute of the file_field, which has broken Rails naming conventions. If you remove the name attribute, Rails will be able to pass the file details uploaded in the :cv field to the database.
Change the file_field to this:
<%= f.file_field :cv, class: 'form-control' %>
If you have Javascript attached to the form, and need to refer to the file_field element, you can use this, instead:
<%= f.file_field :cv, id: "cv", class: "form-control" %>
I have a Rails app that builds both a User and an Organization when the first User signs up (User belongs_to Organization). This works fine, and if you fail to put in e.g. the email address (or use an incorrect one) then the form renders the relevant rails error messages just fine. I have additional logic that ensures the first User to sign up an Organization becomes the Admin User of that Organization, and they are permitted to add other users to the site too. If you try and sign up with an existing Organization name it's not permitted.
My tests are all fine, and I'm using the skeleton logic for authentication and authorization provided by the Hartl tutorial (not the new draft one). What I recently noticed was that when an Admin User inputs a blank form for a new user, the app returns to the Organization page and displays a success message. No User object is built (so some part of the app is still working) - I just don't want this to happen (I want the error messages displayed). I can't quite work out what is happening here - why wouldn't the "validates" statements return the errors in this case? Anyway - here's my code:
User.rb:
class User < ActiveRecord::Base
belongs_to :organization
has_many :sales_opportunities
before_save { self.email = email.downcase }
before_destroy :allocate_sales_opportunities_to_admin
before_create :create_remember_token
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(?:\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
validates :organization, presence: true
Organization.rb:
class Organization < ActiveRecord::Base
validates :organization_name, presence: true, length: { maximum: 50 }, uniqueness: true
has_many :users, :inverse_of => :organization, dependent: :destroy
has_many :companies, :inverse_of => :organization, dependent: :destroy
has_many :products, :inverse_of => :organization, dependent: :destroy
has_many :competitors, :inverse_of => :organization, dependent: :destroy
accepts_nested_attributes_for :users
after_create :set_admin
def users_for_form
collection = users.where(organization_id: id)
collection.any? ? collection : users.build
end
private
def set_admin
if self.users.count == 1
self.users.first.update_attribute(:admin, true)
else
return true
end
end
end
Users controller:
class UsersController < ApplicationController
before_action :signed_in_user, only: [:index, :edit, :update]
before_action :correct_user, only: [:edit, :update, :show]
before_action :admin_user, only: :destroy
def update
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
def create
if signed_in?
#organization = Organization.find(params[:organization_id])
#organization.users.create(user_params)
flash[:success] = "You added a new user to your organization. Send them their login details today!"
redirect_to #organization
else
#user = User.new(user_params)
if #user.save
sign_in #user
flash[:success] = "Thanks for signing up with My App! This is your profile page, be sure to take a look at the support link in the footer"
redirect_to #user
else
render 'new'
end
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation, organization_attributes: [:organization_name, :organization_id])
end
#before filters
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in." unless signed_in?
end
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
def correct_user
#user = User.find(params[:id])
#organization = #user.organization
redirect_to root_url, notice: "You are not permitted to visit that page. Please create an account or sign in" unless current_user?(#user) || #user.organization == current_user.organization
end
end
Organization's controller:
class OrganizationsController < ApplicationController
before_action :signed_in_user, only: [:edit, :update, :show]
before_action :correct_org, only: [:edit, :update, :show]
def new
#organization = Organization.new
#organization.users.build
end
def create
#organization = Organization.new(organization_params)
if #organization.save
#user = #organization.users.first
sign_in #user
flash[:success] = "Thanks for signing up with My App! This is your profile page, be sure to take a look at the support link in the footer"
redirect_to #user
else
render 'new'
end
end
I'm sure I've got some ugly code in here (the Organizations and Users features were the first new functionality I built when learning RoR and deviating from the Hartl course), and I can't quite work out why the validations are working (no User object is created) when the error message handling is not. For completeness here's the add user form:
<% provide(:title, 'Add more users to your organization') %>
<div class-"container-fluid">
<h1>Sign up colleagues using the form below:</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="well">
<%= form_for([:organization, #user], :html => {:class => "form-horizontal"}) do |f| %>
<%= render 'shared/error_messages' %>
<div class="form-group">
<%= f.label :name, :class => "col-md-4 control-label" %>
<div class ="col-md-8">
<%= f.text_field :name, :placeholder => "What's their name?" %>
</div>
</div>
<div class="form-group">
<%= f.label :email, :class => "col-md-4 control-label" %>
<div class ="col-md-8">
<%= f.text_field :email, :placeholder => "Enter their email address" %>
</div>
</div>
<div class="form-group">
<%= f.label :password, :class => "col-md-4 control-label" %>
<div class ="col-md-8">
<%= f.password_field :password, :placeholder => "Provide a password" %>
</div>
</div>
<div class="form-group">
<%= f.label :password_confirmation, "Repeat Password", :class => "col-md-4 control-label" %>
<div class ="col-md-8">
<%= f.password_field :password_confirmation, :placeholder => "Repeat password" %>
</div>
</div>
<%= f.submit "Add new user account", class: "btn btn-large btn-success" %>
<% end %>
</div>
</div>
</div>
</div>
Here's the working form for a new Organization/User combo:
<% provide(:title, 'Sign up') %>
<div class="container-fluid">
<h1>Sign up!</h1>
<div class="row">
<div class="col-md-8 col-md-offset-2">
</div>
</div>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="well">
<%= form_for(#organization, :html => {:class => "form-horizontal"}) do |f| %>
<%= render 'shared/org_error_messages' %>
<div class="form-group">
<%= f.label :organization_name, :class => "col-md-4 control-label" %>
<div class ="col-md-8">
<%= f.text_field :organization_name, :placeholder => "Who do you work for?" %>
</div>
</div>
<%= f.fields_for :users, #organization.users_for_form do |user| %>
<div class="form-group">
<%= user.label :name, :class => "col-md-4 control-label" %>
<div class ="col-md-8">
<%= user.text_field :name, :placeholder => "What's your name?" %>
</div>
</div>
<div class="form-group">
<%= user.label :email, :class => "col-md-4 control-label" %>
<div class ="col-md-8">
<%= user.text_field :email, :placeholder => "Email" %>
</div>
</div>
<div class="form-group">
<%= user.label :password, :class => "col-md-4 control-label" %>
<div class ="col-md-8">
<%= user.password_field :password, :placeholder => "Enter password - minimum 6 characters" %>
</div>
</div>
<div class="form-group">
<%= user.label :password_confirmation, "Repeat Password", :class => "col-md-4 control-label" %>
<div class ="col-md-8">
<%= user.password_field :password_confirmation, :placeholder => "Repeat password" %>
</div>
</div>
<%= user.hidden_field :organization_id, input_html: {value: #organization.id} %>
<% end %>
<%= f.submit "Create my account", class: "btn btn-large btn-success" %>
<% end %>
</div>
</div>
</div>
<div>
Where am I going wrong?
EDIT - here is the log from my console when the above happens:
Processing by UsersController#new as HTML
Parameters: {"organization_id"=>"1"}
Rendered shared/_error_messages.html.erb (0.1ms)
Rendered users/new.html.erb within layouts/application (3.4ms)
Rendered layouts/_shim.html.erb (0.0ms)
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'b8cabbe1e1514f14be24f95d48248ad716e11342' LIMIT 1
Organization Load (0.3ms) SELECT "organizations".* FROM "organizations" WHERE "organizations"."id" = $1 LIMIT 1 [["id", 1]]
Rendered layouts/_header.html.erb (3.9ms)
Rendered layouts/_footer.html.erb (0.2ms)
Completed 200 OK in 28ms (Views: 26.0ms | ActiveRecord: 0.9ms)
Started POST "/organizations/1/users" for 127.0.0.1 at 2014-10-05 22:22:15 +0630
Processing by UsersController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"fKx7bdWtC7bmBKMRF3ivwBlmJXzrcWJ16dYYOfNLBC0=", "user"=>{"name"=>"", "email"=>"", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Add new user account", "organization_id"=>"1"}
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'b8cabbe1e1514f14be24f95d48248ad716e11342' LIMIT 1
Organization Load (0.4ms) SELECT "organizations".* FROM "organizations" WHERE "organizations"."id" = $1 LIMIT 1 [["id", 1]]
(0.3ms) BEGIN
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('') LIMIT 1
(0.8ms) COMMIT
Redirected to http://0.0.0.0:3000/organizations/1
Completed 302 Found in 14ms (ActiveRecord: 2.7ms)
Started GET "/organizations/1" for 127.0.0.1 at 2014-10-05 22:22:15 +0630
Processing by OrganizationsController#show as HTML
Parameters: {"id"=>"1"}
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'b8cabbe1e1514f14be24f95d48248ad716e11342' LIMIT 1
Organization Load (0.4ms) SELECT "organizations".* FROM "organizations" WHERE "organizations"."id" = $1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT "organizations".* FROM "organizations" WHERE "organizations"."id" = $1 LIMIT 1 [["id", "1"]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."organization_id" = $1 [["organization_id", 1]]
Rendered organizations/_users_index.html.erb (1.0ms)
Organization Load (0.4ms) SELECT "organizations".* FROM "organizations" WHERE "organizations"."id" = $1 LIMIT 1 [["id", 1]]
Company Load (0.6ms) SELECT "companies".* FROM "companies" WHERE "companies"."organization_id" = $1 [["organization_id", 1]]
Competitor Load (0.4ms) SELECT "competitors".* FROM "competitors" WHERE "competitors"."organization_id" = $1 [["organization_id", 1]]
Product Load (0.4ms) SELECT "products".* FROM "products" WHERE "products"."organization_id" = $1 [["organization_id", 1]]
Rendered organizations/show.html.erb within layouts/application (13.3ms)
Rendered layouts/_shim.html.erb (0.0ms)
Rendered layouts/_header.html.erb (0.6ms)
Rendered layouts/_footer.html.erb (0.2ms)
Completed 200 OK in 37ms (Views: 30.6ms | ActiveRecord: 3.1ms)
I think it's something to do with the way I'm handling creating a new user, after further testing. The following code is almost certainly where the error lies:
def create
if signed_in?
#organization = Organization.find(params[:organization_id])
#organization.users.create(user_params)
flash[:success] = "You added a new user to your organization. Send them their login details today!"
redirect_to #organization
else
#user = User.new(user_params)
if #user.save
sign_in #user
flash[:success] = "Thanks for signing up with My App! This is your profile page, be sure to take a look at the support link in the footer"
redirect_to #user
else
render 'new'
end
end
end
Where I'm testing if the User is signed in, the choice either leads to adding a new user to the current organization or creating both from scratch. What I need is a way to test whether #organization.users.create was successful (or maybe I need #organization.users.new) and if it fails the validations then I need to render "users/new" rather than heading back to the #organization path and displaying the (obviously incorrect) flash that a new user has been created.
Anyone got any ideas how I test for this? I tried a quick if/else test (along the lines of "if #organization.users.create ... else: render the users/new page"), but then I got a bunch of form errors because I wasn't defining the object that the page was creating.
I solved this with the change to the create function in the Users controller - I was creating a new #organization.user regardless of the error messages in the form. Instead I needed to use #user = #organization.users.new, and then use the same if #user.save ... test that works for a new user. See the below code for how it was fixed:
def create
if signed_in?
#organization = Organization.find(params[:organization_id])
#user = #organization.users.new(user_params)
if #user.save
flash[:success] = "You added a new user to your organization. Send them their login details today!"
redirect_to #organization
else
render 'new'
end
else
#user = User.new(user_params)
if #user.save
sign_in #user
flash[:success] = "Thanks for signing up with My App! This is your profile page, be sure to take a look at the support link in the footer"
redirect_to #user
else
render 'new'
end
end
end
Pretty standard update in my opinion, but upon submitting the put request, the attribute is not updated. Here is my relevant model:
class Vendor < ActiveRecord::Base
geocoded_by :address
after_validation :geocode,
:if => lambda{ |obj| obj.address_changed? }
end
My controller methods:
def edit
#vendor = Vendor.find(params[:id])
end
def update
#vendor = Vendor.find(params[:id])
if #vendor.update_attributes(vendor_params)
redirect_to vendors_mgmt_path
else
render 'edit'
end
end
def vendor_params
params.permit(:id, :name, :address, :image, :latitude, :longituded )
end
I see this in the server log after trying to update:
Started PUT "/vendors/1" for 127.0.0.1 at 2013-10-20 20:44:54 -0700
Processing by VendorsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"fTbZVEfckQz4xQzY5xSMQCArrGZqymNsVeyic/PXKcE=", "vendor"=>{"name"=>"Store", "address"=>"1221 E. Main St."}, "commit"=>"Save changes", "id"=>"1"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Vendor Load (0.2ms) SELECT "vendors".* FROM "vendors" WHERE "vendors"."id" = ? LIMIT 1 [["id", "1"]]
Unpermitted parameters: utf8, _method, authenticity_token, vendor, commit
(0.1ms) begin transaction
(0.1ms) commit transaction
Redirected to http://localhost:3000/vendors/mgmt
Completed 302 Found in 10ms (ActiveRecord: 0.6ms)
This confuses me, because the Vendor form looks like so, and has no authenticity token etc.
<h1>Update <%= "#{#vendor.name}" %></h1>
<%= form_for(#vendor) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :address %>
<%= f.text_field :address %>
<%= f.label :Logo %>
<%= f.file_field :image %>
<%= f.submit "Save changes", class: "btn btn-success" %>
<% end %>
Anyone see any glaring errors? Any help is much appreciated. Thanks in advance!
Rails by default includes certain hidden fields in all forms, such as the authenticity_token, which is present to stop CSRF. (More info here) I would recommend changing the line:
params.permit(:id, :name, :address, :image, :latitude, :longituded )
to:
params.require(:vendor).permit(:id, :name, :address, :image, :latitude, :longituded)
Changing this line in your controller should permit the other parameters that are submitted by the form, not just the ones in the vendor param.
Also, you misspelled "longitude", I'm not sure if that's causing any additional trouble or if it's just a typo in your question instead.