sign up and create new object at the same time - ruby-on-rails

i'm new in Ruby on Rails.
I was trying to register a new user with devise and at the same time, create a new Company object. The association between them : User belongs to Company. Company has many users. I tried to make it based on this link : http://railscasts.com/episodes/196-nested-model-form-part-1?view=asciicast, but it didnt work. it said : "undefined method for Company", which is Company doesnt have email attribute.
and in sign up form, i only put email attribute for user
<div class="title"><%= t('.signup') %></div>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="control-group"><%= f.label :email, t('.email') %>
<%= f.email_field :email %></div>
<div class="control-group"><%= f.label :password, t('.password') %>
<%= f.password_field :password %></div>
<div class="control-group"><%= f.label :password_confirmation, t('.password_confirmation') %>
<%= f.password_field :password_confirmation %></div>
<%= f.fields_for :company_attributes do |f_company| %>
<div class="control-group"><%= f_company.label :name, t('.company_name') %>
<%= f_company.text_field :name %></div>
<% end %>
<div class="buttons"><%= f.submit t('.signup'), class:"btn btn-primary" %><br>
<%= render "links" %></div>
<% end %>
updated
Company controller :
class CompaniesController < Devise::RegistrationsController
def new
#company = Company.new
#user = #company.users.build
end
def create
#company = Company.new(params[:company])
#user = User.create(params[:user].merge(company_id:company.id))
if #company.save
redirect_to "/"
else
render 'users/sign_up'
end
end
end
User Controller :
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to users_path
else
render 'users/new'
end
end
I would really appreciate any idea and any help. Thanks in advance

In your case, since you are only interested in receiving the company_name I'd simplify it and submit the company_name via a text_field_tag.
In other words, I would replace:
<%= f.fields_for :company_attributes do |f_company| %>
<div class="control-group"><%= f_company.label :name, t('.company_name') %>
<%= f_company.text_field :name %></div>
<% end %>
With this
<%= text_field_tag 'company_name', {placeholder:"Enter here the name of your company",class:"form-control"} %>
This would submit the name to the UsersController, and you could access it with params[:company_name] so the controller would look like this:
Users controller:
def new
#user = User.new
end
def create
#user = User.create(params[:user])
#Create a company via 'user<->company' association using 'company_name'
#company= #user.company.create(name: params[:company_name])
if #user.save
redirect_to users_path
else
render 'users/new'
end
end

Related

Keep getting "Param is missing or the value is empty"

I keep getting the error mentioned above, even though my form object matches my controller object (most people who had this problem had mixed their objects up in similar questions). What exactly am I doing wrong here?
My code is below:
<!-- The form is here -->
<%= form_for(#user), url: {action: "/users/signup"}, html: {class: "signup_form"} do |f| %>
<%= label_tag(:firstname, "Firstname: ") %>
<%= f.text_field :firstname %>
<%= label_tag(:lastname, "Lastname: ") %>
<%= f.text_field :lastname %>
<%= label_tag(:username, "Username: ") %>
<%= f.text_field :username %>
<%= label_tag(:email, "Email: ") %>
<%= f.text_field :email %>
<%= label_tag(:password, "Password") %>
<%= f.password_field :password %>
<%= f.submit "Create Account" %>
<% end %>
And here's the controller:
class UsersController < ApplicationController
def create
#user = User.new(user_params)
#user.save
redirect_to #user
end
private
def user_params
params.require(:user).permit(:firstname, :lastname, :username,
:email, :password)
end
end
Would really appreciate some help and sorry if I missed something silly here, thanks in advance.
users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, success: 'Thanks for signing up!' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
end
users/_form.html.erb
<%= form_for(#user) do |f| %>
<div class="field">
<%= f.label :first_name, "First name" %><br>
<%= f.text_field :first_name %>
</div>
<div class="field">
<%= f.label :last_name, "Last name" %><br>
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :email, "Email" %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password, "Password" %><br>
<%= f.password_field :password %>
</div>
<div class="actions">
<%= f.submit "Sign Up" %>
</div>
<% end %>
Why do you have url: {action: "/users/signup"} in the form? It is much simpler if you do the following:
routes.rb
Rails.application.routes.draw do
resources :user
end
views/users/_form.html.erb
<%= form_for(#user), html: {class: "signup_form"} do |f| %>
controllers/users_controller.rb (add the following)
class UsersController < ApplicationController
def new
#user = User.new
end
end
If you do it like this, form_for will automatically detect whether or not the #user object has been saved in the database, and will route the form to the create or update method respectively.
I general I don't reccommend altering the standard RESTful routes unless absolutley necessary. A user is not likely going to look at yoursite.com/users/new in the URL and be upset or confused.

Ruby on Rails: Populate dropdown with two fields of database record

In my database I have a Users table that looks something like:
User_ID Firstname Surname Company
1 Steve Jobs Apple
2 Bill Gates Microsoft
What I am trying to do is make a drop down menu in a form that would allow a user to choose from selecting their name or their company, e.g. when Steve Jobs is logged in he can either select "Steve" or "Apple" in the drop down menu.
What I have tried so far is the following:
<%= f.select :from_name, [session[:user_id],session[:user_id]] %>
Which obviously didn't work because it only returns the user id of the logged in user.
<%= f.select :from_name, [#user.firstname,#user.company] %>
Which gave me the error undefined methodfirstname for nil:NilClass`
My Users controller is as follows:
class UsersController < ApplicationController
before_filter :check_authorization, :except => [:show, :new, :create, :search ]
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def edit
#user = User.find(params[:id])
end
def create
#user = User.new(user_params)
#user.role = "customer"
if #user.save
session[:user_id] = #user.id
# Save a copy of the email address entered by the user into the Accounts table
#account = Account.create(email: params[:user][:primaryemailaddress], user_id: session[:user_id])
redirect_to root_path
else
render 'new'
end
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to #user
else
render 'edit'
end
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to users_path
end
private
def user_params
params.require(:user).permit(:title, :firstname, :surname, :housenumber, :street, :city, :postcode, :company, :primaryemailaddress, :password)
end
end
And my _form.html.erb is:
<%= form_for(#email) do |f| %>
<% if #email.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#email.errors.count, "error") %> prohibited this email from being saved:</h2>
<ul>
<% #email.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :from_name %><br>
<%= f.select :from_name, [current_user.firstname, current_user.company] %>
</p>
<p>
<%= f.label :From_Email_Address %><br>
<%= f.collection_select :account_id, Account.where(user_id: session[:user_id]),
:id,:email %>
</p>
<p>
<%= f.label :to %><br>
<%= f.text_field :to %>
</p>
<p>
<%= f.label :cc %><br>
<%= f.text_field :cc %>
</p>
<p>
<%= f.label :bcc %><br>
<%= f.text_field :bcc %>
</p>
<p>
<%= f.label :subject %><br>
<%= f.text_field :subject %>
</p>
<p>
<%= f.label :message %><br>
<%= f.text_field :message %>
</p>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I'm not too sure how to solve this issue, can someone please help.
#BenSmith I guess you are accessing EmailsController. And on that controller's new or edit method there is no #user variable.
In your edit and new method add
#user = User.find(session[:user_id])
undefined method firstname for nil:NilClass
Seems like some how #user is nil
create a helper and check for presence of #user
<%= f.select :from_name, dropdown_values %>
application_helper.rb
def dropdown_values
if #user.present?
[#user.firstname, #user.company]
else
['default', 'values']
end
end
<p>
<%= f.label :from_name %><br>
<%= f.select :from_name, [current_user.firstname, current_user.company] if #user.present?%>
</p>
because User.new time create blank object doesn't find username.i hope its will be help you.

Ruby / ActionMailer / Saving mail

I am creating a customer support app where clients can create, view, edit and comment support tickets.
I have this portion of the app working fine, but I want to have the data they submit into the ticket form emailed to me.
I have a separate "contact us" form that emails the data to me perfectly, but I want to combine the two forms into one.
It should work like this: client creates ticket, ticket is saved into the database, a copy of the ticket is emailed to me.
I can't figure out how to make all of these actions happen from one form.
Here is my tickets controller:
class TicketsController < ApplicationController
def new
#ticket = Ticket.new
end
def create
#ticket = Ticket.new(ticket_params)
#ticket.save
redirect_to #ticket
end
def show
#ticket = Ticket.find(params[:id])
end
def index
#tickets = Ticket.all
end
def edit
#ticket = Ticket.find(params[:id])
end
def update
#ticket = Ticket.find(params[:id])
if #ticket.update(ticket_params)
redirect_to #ticket
else
render 'edit'
end
end
def destroy
#ticket = Ticket.find(params[:id])
#ticket.destroy
redirect_to tickets_path
end
private
def ticket_params
params.require(:ticket).permit(:name, :email, :phone, :help)
end
end
Here is my new ticket view:
<%= link_to "View an Existing Ticket", tickets_path, :class =>'btn btn-danger btn-sm'%>
<h1>New Ticket</h1>
<%= form_for :ticket, url: tickets_path do |f| %>
<p>
<%= f.label "Name:" %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label "Email:" %>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :"Phone #:" %>
<%= f.text_field :phone %>
</p>
<p>
<%= f.label :"How can we help?" %>
<p><%= f.text_area :help, :cols=> 38, :rows => 8 %></p>
</p>
<p>
<button type="submit" class="btn btn-danger btn-sm">Submit Ticket</button>
</p>
<% end %>
<p><%= button_to "Back", root_path, :class => "btn btn-danger btn-sm", :method => :get %></p>
Here is my email controller:
class ContactController < ApplicationController
def new
#message = Message.new
end
def create
#message = Message.new(params[:message])
if #message.valid?
NotificationsMailer.new_message(#message).deliver
redirect_to(root_path, :notice => "Message was successfully sent.")
else
flash.now.alert = "Please fill all fields."
render :new
end
end
end
Here is my email view:
<%= form_for #message, :url => contactcreate_path do |form| %>
<fieldset class="fields">
<div class="field">
<%= form.label :name %>
<%= form.text_field :name %>
</div>
<div class="field">
<%= form.label :email %>
<%= form.text_field :email %>
</div>
<div class="field">
<%= form.label :subject %>
<%= form.text_field :subject %>
</div>
<div class="field">
<%= form.label :body %>
<%= form.text_area :body %>
</div>
</fieldset>
<fieldset class="actions">
<%= form.submit "Send" %>
</fieldset>
<% end %>
Ticket Model:
class Ticket < ActiveRecord::Base
after_create :send_new_ticket_to_email
private
def send_new_ticket_to_email
NotificationsMailer.send_new_ticket(self).deliver
end
end
Notifications Mailer:
class NotificationsMailer < ActionMailer::Base
def send_new_ticket(ticket)
#ticket = ticket
mail(:subject => "HelpDesk: #{message.subject}")
default :from => "HelpDeskApp#ascendstudioslive.com"
default :to => "Support#ascendstudioslive.com"
end
Let me know if there is anything else you would like to see. Basically, I want to have one form that saves a ticket to the database and then emails a copy of it out.
Thank you!
You can create an after_create callback in your Ticket model to e-mail the saved ticket to yourself.
class Ticket < ActiveRecord::Base
after_create :send_new_ticket_to_email
private
def send_new_ticket_to_email
UserMailer.send_new_ticket(self).deliver
end
end
and in your ActionMailer class:
class UserMailer < ActionMailer::Base
def send_new_ticket(ticket)
#ticket = ticket
/* here you configure the variables for your email */
mail(to: your#email.com, subject: 'New ticket...')
end
end
then you will be able to use the #ticket object in your mailer views whatever way you please.
Have you tried this? I don't know if it is going to work, but all the same:
#new_message = NotificationsMailer.new_message(#message)
save_to_db(#new_message) # custom method to write it into your db somehow
#new_message.deliver
Not really sure what a contact is versus a ticket, but, broadly, the way to do what you want is, in your create action:
def create
#message = Message.create(params[:message])) # create will save and validate the message
if #message.valid?
NotificationsMailer.new_message(#message).deliver # #message gets set to
# else...
end

Couldn't find User with id=update_password with Devise

I'm using devise on a Rails application and for various reasons I needed to add a custom password change, using solution 3 from here: https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-edit-their-password
I've looked through various other questions and tried augmenting my routes in a number of ways but the url always comes up /users/update_password (without a parameter passed), or /users/update_password.254 (with a parameter passed). I need it to be /users/254/update_password.
Here is the Users Controller I'm working with (relevant methods are update_password and user_params).
class UsersController < ApplicationController
inherit_resources
load_and_authorize_resource
before_filter :authenticate_user!
def destroy
name = #user.to_s
destroy!(notice: "User #{#user.to_s} was deleted.")
end
def edit
#user = current_user
end
def update_password
#user = User.find(current_user.id)
if #user.update_with_password(user_params)
sign_in #user, :bypass => true
redirect_to root_path
else
render "edit"
end
end
private
def build_resource_params
[params.fetch(:user, {}).permit(:name, :email, :phone_number, :password, :password_confirmation).tap do |p|
p[:institution_pid] = build_institution_pid if params[:user][:institution_pid]
p[:role_ids] = build_role_ids if params[:user][:role_ids]
end]
end
def build_institution_pid
institution = Institution.find(params[:user][:institution_pid])
authorize!(:add_user, institution)
institution.id
end
def build_role_ids
[].tap do |role_ids|
roles = Role.find(params[:user][:role_ids].reject &:blank?)
roles.each do |role|
authorize!(:add_user, role)
role_ids << role.id
end
end
end
def user_params
params.required(:user).permit(:password, :password_confirmation, :current_password)
end
end
This is the relevant portion of routes.rb
devise_for :users
resources :users do
collection do
get 'password'
put 'update_password'
end
end
This is the view I created to go with it:
<div class="page-header">
<h1>Change Password</h1>
</div>
<%= form_for(#user, :url => { :action => "update_password" } ) do |f| %>
<div class="field">
<%= f.label :password, "Password" %><br />
<%= f.password_field :password, :autocomplete => "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %>
</div>
<div class="action_container">
<%= f.submit %>
</div>
And this is the link: (currently with a parameter but I've tried without as well)
<li><%= link_to "Change Password", update_password_users_path(current_user) %></li>
When I click that link I get routed to a page that says ActiveRecord::RecordNotFound in UsersController#show, Couldn't find User with id=update_password.
I tried to follow the instructions pretty closely and I've tried to fiddle with the routes a couple times to get it to work and I'm pretty lost at this point. Has anyone seen this before and can help? Thanks!
To achieve what you need, you will have the following routes:
resources :users do
patch 'update_password', on: :collection
get 'edit_password', on: :member
end
Then you'll add a link that would lead user to update password form. The link should look like as follows:
<li><%= link_to "Change Password", edit_password_user_path(current_user) %></li>
The link would lead to users/edit_password.html.erb:
<div class="page-header">
<h1>Change Password</h1>
</div>
<%= form_for(#user, :url => { :action => "update_password" } ) do |f| %>
<div class="field">
<%= f.label :password, "Password" %><br />
<%= f.password_field :password, :autocomplete => "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %>
</div>
<div class="action_container">
<%= f.submit %>
</div>
<% end %>
When form is submitted, that would trigger update_password in UsersController. Here is the code for controller:
class UsersController < ApplicationController
def edit_password
#user = current_user
end
def update_password
#user = User.find(current_user.id)
if #user.update_with_password(user_params)
sign_in #user, :bypass => true
redirect_to root_url
else
render "edit_password"
end
end
private
def user_params
params.required(:user).permit(:password, :password_confirmation, :current_password)
end
end

rails: "Sign In" and "Password Authentication" of Users

Im trying to set up a log-in and password page for my site. This will be on the index page. I have a Model Class: "User" and a controller class "users_controller".
The behavior that Im trying to implement is this:
Users type in the url of the site and it opens the index page as shown below. Then the users signs in and is brought to a different page where they have access to the content of the site.
Now the question is what do I need to put in the "def index" function so that it accepts the form's paramters and passes these to another function called "self.authenticate(parameters)" to check and return a status
Here is the code for the users_controller
class UsersController < ApplicationController
def index
#user = User.new
respond_to do |format|
format.html
#index.html.erb
end
end
def show
#user = User.find(params[:id])
#title = #user.name
end
def edit
#user = User.find(params[:id])
#title = #user.name
end
def destroy
#user = User.find(params[:id])
end
def new
#user = User.new
#title = "Sign Up"
end
def create
end
end
Here is the form:
<html>
<h1>Returning Users- Sign In</h1>
<%= form_for(#user) do |f| %>
<div class="field">
<%=f.label :email %><br/>
<%= f.text_field :email %>
</div>
<div class = "field">
<%= f.label :password %><br/>
<%= f.password_field :password %>
</div>
<div class = "actions">
<%= f.submit "Sign In" %>
</div>
<% end %>
<h1>New Users- Sign Up</h1>
<%= form_for(#user) do |f| %>
<div class="field">
<%=f.label :name %><br/>
<%= f.text_field :name %>
</div>
<div class="field">
<%=f.label :email %><br/>
<%= f.text_field :email %>
</div>
<div class = "field">
<%= f.label :password %><br/>
<%= f.password_field :password %>
</div>
<div class = "field">
<%= f.label :password_confirmation, "Confirm Password" %><br/>
<%= f.password_field :password_confirmation %>
</div>
<div class = "actions">
<%= f.submit "Sign Up" %>
</div>
<%end%>
<br/>
<%= debug(params) if Rails.env.development? %>
<br/>
</body>
Any help would be great. Thanks
Have a look at the recent RailsCast Authentication from Scratch from Ryan Bates. You can also use a common authentication plugin like AuthLogic or Devise.
I'm going to explain to you what you want to do.
You can get the params by using the hash params:
params[]
Then, you can get the value of a field by passing it's identification, like:
params[:id]
or
params[:name]
Now pass it to the self.authenticate(parameters) in the way you can(I don't know how this method is implemented).

Resources