I'm making a single page application based on Futureme.org for practice. The user goes to the home page, sees a form to put their email address, subject, and the body of their message and sends it.
The problem I am having is I get an error "First argument in form cannot contain nil or be empty". Here is my code;
Model;
class Letter < ActiveRecord::Base
VALID_EMAIL_REGEX = /\A[\w+\-,]+#[a-z\d\-.]+\.[a-z]+\z/i
validates_presence_of :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates_length_of :subject, presence: true, length: { maximum: 50 }
validates_presence_of :message
end
Controller;
class LettersController < ApplicationController
def new
#letter = Letter.new
end
def create
#letter = Letter.new(params[:letter])
if #letter.save
redirect_to letters_path, :notice => "Your letter was sent!"
else
render "new"
end
end
end
View form;
<%= form_for #letter, :html => {:class => 'form-horizontal'} do |f| %>
<% if #letter.errors.any? %>
<div class="error_messages">
<h2><%= pluralize(#letter.errors.count, "error")%>stopped this message from being saved</h2>
<ul>
<% #letter.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :subject %><br />
<%= f.text_field :subject %><br />
</div>
<div class="field">
<%= f.label :message, "Message" %><br />
<%= f.text_area :message, size: "60x10" %>
</div>
<div class="actions"><%= f.submit "Submit", class: "btn btn-small btn-primary" %></div>
<% end %>
The form is on the home page which is in the "Welcome Controller".
Any help would be great.
It looks like you build letter in action new when form is drawn on other view :)
You should move #letter = Letter.new to appropriate action
One of the variant is:
#WelcomeController
def home
#letter = Letter.new
end
#LettersController
def create
#letter = Letter.new(params[:letter])
if #letter.save
redirect_to letters_path, :notice => "Your letter was sent!"
else
render "welcome/home"
end
end
be careful if you prepare some data in action home you should care about initializing them for action create when validation failed because you render "welcome/home" view
Related
When I submit the form it is passing {"utf8"=>"✓", "authenticity_token"=>"blah", "client"=>{"first_name"=>"jack", "last_name"=>"kool","complaints"=>{"symptom"=>"burnt"} in the params and I am getting Unpermitted Parameters: complaints Since complaints is nested in Client, it should be passing complaints_attributes, like I have it set up in the strong params, and I can't figure out why it isn't.
class ClientsController < ApplicationController
def new
#client = Client.new
end
def edit
#client = Client.find(params[:id])
end
def create
#client = Client.new(client_params)
if #client.save
redirect_to #client
else
render 'new'
end
end
def update
#client = Client.find(params[:id])
if #client.update(client_params)
redirect_to #client
else
render 'edit'
end
end
private
def client_params
params.require(:client).permit(:first_name, :last_name, complaints_attributes: [ :symptom, :id ])
end
end
Client model:
class Client < ActiveRecord::Base
has_many :complaints
has_one :personal_disease_history
has_one :family_disease_history
has_many :surgeries
has_many :hospitalizations
has_many :medications
has_many :allergies
validates :first_name, :last_name, presence: true
accepts_nested_attributes_for :complaints
end
Complaint model:
class Complaint < ActiveRecord::Base
belongs_to :client
end
Form:
<%= form_for :client, url: clients_path, html: { class: "form-inline" } do |f| %>
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">Health History Form</h3>
</div>
<div class="panel-body">
<div class="form-blocks"><legend>Name</legend>
<div class="form-group">
<%= f.label :first_name, class: "sr-only" %>
<%= f.text_field :first_name, class: "form-control", placeholder: "First Name" %>
</div>
<div class="form-group">
<%= f.label :last_name, class: "sr-only" %>
<%= f.text_field :last_name, class: "form-control", placeholder: "Last Name" %>
</div>
</div>
<div class="form-blocks"><legend>Complaints</legend>
<div class="form-group">
<%= f.fields_for :complaints do |builder| %>
<%= builder.label :symptom, class: "sr-only" %>
<%= builder.text_field :symptom, class: "form-control", placeholder: "Symptom" %>
<% end %>
</div>
</div>
<div>
<%= f.submit "Submit Form", class: "btn btn-primary btn-lg"%>
</div>
<% end %>
inside client controller create action, try saying this inside the if #client.save:
Complaint.create(symptom: params[
"client"]["complaints"]["symptom"], client_id: #client.id)
the unpermitted parameter is related to the nested attribute problem but this should get the actual record saving. If that doesn't do it, please post the stack trace surrounding the commit.
have couple other ideas: but (1) you have complaint_attributes in the permitted params but you could change that to complaint bc that's what's coming through in the params.
My user model contains values for things like:
name, email, phone, approved, etc..
The scope of the project I am working on includes custom user settings and for this reason I am using hstore (I dont want to create a user_settings table).
On the user edit view I want to create a checkbox called 'colors' and whether or not the checkbox is checked determines if that setting is set for the user or not.
I have already setup hstore as follows:
class AddHstore < ActiveRecord::Migration
def up
enable_extension :hstore
end
def down
disable_extension :hstore
end
end
And updated the User model as follows:
class AddSettingsToUser < ActiveRecord::Migration
def up
add_column :users, :settings, :hstore
end
def down
remove_column :users, :settings
end
end
This is essentially my user edit view:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, :class => "form-horizontal user" }) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name, autofocus: true %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email %>
</div>
<div class="field">
<%= f.label :phone_number %><br />
<%= f.text_field :phone_number %>
</div>
<div class="actions">
<%= f.submit 'Update', :class => 'btn btn-primary' %>
</div>
<% end %>
At this point I am unsure as to how to actually implement this functionality. The user edit page allows the user to change their name, phone and other values but how would I include a new value for the hstore settings?
Inside the form_for from where you are creating users, add your hstore fileds like below :
<%= form_for resource, ...do |f| %>
#...
<%= f.fields_for :settings do |settings| %>
<%= settings.text_field :field1 %>
<%= settings.text_field :field2 %>
<% end %>
#....
<% end %>
Then update your controller strong parameter method like below to permit these new fields.:
def user_params
params.require(:user)
.permit(
:name,
:email,
settings: [ :field1, :field2 ]
)
end
Now, you are done. Open your rails console and try some sample data like
User.create(
settings: { field1: 'data1', field2: 'data2' }
)
Users can make a reservation, and each reservation can have multiple occurrences. After they've entered their data, they get a preview page to confirm the information before it's saved to the database. The occurrence information is being passed to the preview page. I can see it in the parameter dump at the bottom of the page. I can't seem to access it to display it to the user.
Here's my code:
reservations_controller.rb
def new
#reservation = Reservation.new
#occurrence = #reservation.occurrence.build
end
def preview
if params[:reservation]
#reservation = Reservation.new(reservation_params)
#occurrence = #reservation.occurrence.build(params[:occurrence])
end
end
private
def reservation_params
params.require(:reservation).permit(:title, :description, :is_public, :is_internal, :internal_organization, :contact_name,
:contact_phone, :contact_email, :contact_present, :contact_present_name,
:contact_present_phone, :contact_present_email, :notes)
end
reservations/new.html.erb (I've put some blank lines around the nested form to make it easier to find):
<div id="addReservationForm_container" class="addReservationFormContainer formContainer">
<%= form_for #reservation, :url => preview_path, :html => { :method => :get } do |f| %>
<% if #reservation.errors.any? %>
<div class="error">
Please address the <%= "#{'error'.pluralize(#reservation.errors.count)}" %> below to submit this reservation.
</div>
<% end %>
<%= field_set_tag 'Reservation Information' do %>
<div class="formField paragraph <%= 'error' if #reservation.errors.include?(:title) %>">
<%= f.label :title, 'Title:' %>
<%= f.text_field :title, size: "40", class: (#reservation.errors.include?(:title) ? 'error' : '') %>
</div>
<div class="formField">
<%= f.label :description, 'Enter a short description of the event:' %>
<%= f.text_area :description, size: "60x6" %>
</div>
<div class="formField">
<%= f.label :is_public do %>
Should this event be listed on public calendars?
<%= f.select :is_public, options_for_select([['Yes', true], ['No', false]]) %>
<% end %>
</div>
<hr />
<div class="formField">
<%= f.label :is_internal do %>
Is this reservation for a related event?
<%= f.select :is_internal, options_for_select([['Yes', true], ['No', false]]) %>
<% end %>
</div>
<div class="internalDetails formField <%= 'error' if #reservation.errors.include?(:internal_organization) %>">
<%= f.label :internal_organization, 'Please enter the name of the department, organization, or club hosting the event:' %>
<%= f.text_field :internal_organization, size: '40', class: (#reservation.errors.include?(:internal_organization) ? 'error' : '') %>
</div>
<% end %>
<%= field_set_tag 'Date and Time' do %>
<div class="paragraph">
Select the date(s) and time(s) you want to reserve:
<div class="formField paragraph">
<%= f.fields_for :occurrences do |o| %>
<%= o.text_field :start_date, class: 'datepicker' %>
<%= o.select :end_date, options_for_select(create_hours(:start_time => 7.5.hours, :end_time => 21.hours, :increment => 15.minutes)) %>
<% end %>
</div>
</div>
<% end %>
<%= field_set_tag 'Contact Information' do %>
<div class="paragraph">
Please enter the contact information of the person responsible for the reservation:
</div>
<div class="formField paragraph <%= 'error' if #reservation.errors.include?(:contact_name) %>">
<%= f.label :contact_name, 'Name:' %>
<%= f.text_field :contact_name, size: "40", class: (#reservation.errors.include?(:contact_name) ? 'error' : '') %>
</div>
<div class="formField paragraph <%= 'error' if #reservation.errors.include?(:contact_phone) %>">
<%= f.label :contact_phone, 'Phone:' %>
<%= f.text_field :contact_phone, size: "40", class: (#reservation.errors.include?(:contact_phone) ? 'error' : '') %>
</div>
<div class="formField paragraph <%= 'error' if #reservation.errors.include?(:contact_email) %>">
<%= f.label :contact_email, 'E-mail:' %>
<%= f.text_field :contact_email, size: "40", class: (#reservation.errors.include?(:contact_email) ? 'error' : '') %>
</div>
</div>
<% end %>
<%= field_set_tag 'Additional Information' do %>
<div class="internalDetails formField">
<%= f.label :notes, 'Please enter any additional information or instructions:' %>
<%= f.text_area :notes, size: "60x6" %>
</div>
<% end %>
<%= f.submit 'Continue' %>
<% end %>
</div>
The code below is where I can't seem to display the information from the occurrences nested form.
reservations/preview.html.erb
<div class="paragraph">
Please look over the information you entered for your reservation, and then click either
the "Submit Reservation" button to submit your request, or the "Make Changes" button to
return to the previous form and edit the request.
</div>
<div style="margin-left: 3em;">
<div class="paragraph">
<div> <%= #reservation.title %></div>
<div> <%= #occurrence.start_date %></div>
<div> <%= #reservation.contact_name %> (<%= #reservation.contact_email %>)</div>
<div> <%=#reservation.contact_phone %></div>
</div>
</div>
reservation.rb
has_many :occurrence
accepts_nested_attributes_for :occurrence, :reject_if => :all_blank
I'm new to Rails, so it wouldn't surprise me to find I have multiple things wrong here.
I still novice with RoR. My mission is to add examplaries according to the number of exemplary inserted in the form of book, knowing that i have a book table and an examplary table and the relationship in between is a book has_many exemplaries and an exemplary belong_to a book.
This is my attempt:
in books_controller.rb
method create:
def create
#book= Book.new(book_params)
if #book.save
#book.nbr_exemplaires.times do |i|
#exemplaire= Exemplaire.create(book_id: #book.id, state: 0 )
end
flash[:notice]='goood'
redirect_to admin_manage_path
else
flash[:alert]='ouups'
redirect_to root_url
end
end
private
def book_params
params.require(:book).permit(:title, :pages, :resume,:nbr_exemplaires, :has_exemplaires, :author_ids =>[], :subject_ids =>[])
end
book/new.html.erb:
<h1>Add new book</h1>
<%= form_for(#book) do |form| %>
<div> <%= form.label :title %><br>
<%= form.text_field :title %>
</div>
<div>
<%= form.label :pages %><br>
<%= form.number_field :pages %>
</div>
<div>
<%= form.label :resume %><br>
<%= form.text_area :resume %>
</div>
<div>
<p>select author from existing list</p><br>
<%= form.collection_select :author_ids, #authors, :id, :l_name, {:selected => 1}, {:name => 'book[author_ids][]'} %>
</div>
<div>
<p> Select subject from existing list</p><br>
<%= form.collection_select :subject_ids, #subjects, :id, :name, {:selected =>1}, {:name => 'book[subject_ids][]'} %>
</div>
<div>
<%= form.label :has_exemplaires? %>
<%= form.check_box :has_exemplaires,{}, 'Yes', 'No'%>
<div id="expl_details" style="display:none;">
<%= form.label :nbr_exemplaires %> <%= form.number_field :nbr_exemplaires %>
</div>
</div>
<%= form.submit "Submit" %>
<% end %>
<script type="text/javascript">
var checkbox = document.getElementById('book_has_exemplaires');
var details_div = document.getElementById('expl_details');
checkbox.onchange = function() {
if(this.checked) {
details_div.style['display'] = 'block';
} else {
details_div.style['display'] = 'none';
}
};
</script>
Then I would suggest something like this:
class Book < ActiveRecord::Base
has_many :exemplaires
attr_accessor :nbr_exemplaires
after_save :create_exemplaires
private
def create_exemplaires
nbr_exemplaires.times do
self.exemplaires.create()
end
end
If you actually have a column name 'nbr_exemplaires' in your table, you don't need the attr_accessor line. That is only if you won't be saving that as separate value in the DB.
I would use nested attributes, that way rails will create them automatically for you through the same form:
class Book < ActiveRecord::Base
has_many :exemplaires
accepts_nested_attributes_for :exemplaires, allow_destroy: true
This would allow to use the nested form builder in your view:
<%= form_for(#book) do |form| %>
<div><%= form.label :title %><br>
<%= form.text_field :title %>
</div>
<%= form.fields_for :exemplaires do |f| %>
<%= f.text_field :name %>
... more fields
<% end %>
You could then add some javascript to create a multiple nested forms:
<%= link_to_add_fields "Add Exemplarie", f, :answers %>
With this kind of setup, rails will automatically create all the associated objects in the same action with no additional code on the controller/model side. Here is a great railscasts on it:
http://railscasts.com/episodes/196-nested-model-form-revised
If you haven't subscribed, I suggest you do. It's the most useful rails resource I ever used when starting out and it costs only a few $ a month. Good luck!
Controller code
class AuthenticationController < ApplicationController
def sign_in
#user=User.new
end
def login
username_or_email=params[:user][:username]
password=params[:user][:password]
#check for the username or email
if username_or_email.rindex('#')
email=username_or_email
else
email=username_or_email
end
if User.authenticate(email,password)
flash[:notice] = 'Welcome.'
redirect_to :root
else
flash.now[:error] = 'Unknown user. Please check your username and password.'
render "sign_in"
end
Sign-in view Code
<p>Sign In</p>
<%= form_for #user, :as => :user, :url => sign_in_path(#user) do |f| %>
<p>
<%= f.label 'username or email:' %><br />
<%= f.text_field :username %>
</p>
<p>
<%= f.label 'password:' %><br />
<%= f.password_field :password %>
</p>
<p>
<%= f.submit 'Sign In' %>
<%= f.submit 'Clear Form', :type => 'reset' %>
</p>
<% end %>
Error:-
First argument in form cannot contain nil or be empty when I am rendering Sign_In form after the user is not authorised.