Error Messages partial not showing - ruby-on-rails

I have a model called Video, which takes in user_id, question, and video_cid.
The validates seem to have been set, as the form does not save if it doesn't meet requirements. However, the error messages partial shows no error messages :(.
Here's how the model looks like ->
# == Schema Information
#
# Table name: videos
#
# id :integer not null, primary key
# user_id :integer
# video_cid :string(255)
# question :string(255)
# created_at :datetime
# updated_at :datetime
#
class Video < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
validates :question, presence: true
validates :video_cid, presence: true
end
Here's how the videos/new view looks like ->
<% provide(:title, "Final step, Record a video of yourself") %>
<%= form_for #video do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :question %>
<%= select(:video, :question,
[
['Why would you be effective in a sales/business development role in China?',
'Why would you be a valuable addition to an international team in China? '],
['What is your most significant accomplishment or the best example of your leadership skills in China?',
'What is your most significant accomplishment or the best example of your leadership skills in China?'],
['How would you help solve the biggest challenges Chinese companies and investors face when doing business abroad?',
'How would you help solve the biggest challenges Chinese companies and investors face when doing business abroad? ']
]) %>
<%= render 'nimbb' %>
<%= f.hidden_field :video_cid, value: "" %>
<%= f.submit "Submit the Video", class: "button" %>
<% end %>
I use javascript to set the hidden value for :video_cid like so. The form should technically only pass if the user records a video of himself, and therefore updates the hidden value in the form ->
// Global variable to hold player's reference.
var _Nimbb;
// Global variable to hold the guid of the recorded video.
// Event: Nimbb Player has been initialized and is ready.
function Nimbb_initCompleted(idPlayer)
{
// Get a reference to the player since it was successfully created.
_Nimbb = document[idPlayer];
}
// Event: the video was saved.
function Nimbb_videoSaved(idPlayer)
{
document.getElementById('video_video_cid').value = _Nimbb.getGuid();
}
This is how the controller looks like -->
class VideosController < ApplicationController
before_action :signed_in_user
def new
if current_user.video.present?
redirect_to current_user
else
#video = current_user.build_video
end
end
def create
#video = current_user.build_video(video_params)
if #video.save
flash[:success] = "Video Created!"
redirect_to root_url
else
redirect_to new_video_path
end
end
private
def video_params
params.require(:video).permit(:video_cid,:question)
end
end
this is how the error messages partial looks like:
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
</ul>
</div>
<% end %>

Change your create method to:
def create
#video = current_user.build_video(video_params)
if #video.save
flash[:success] = "Video Created!"
redirect_to root_url
else
render :new
end
end
The form now will be displayed directly after your application rejects form data, without redirection, so it has Video object instantiated in create action, with its errors. In your original form, you were redirecting user to new video path after video saving failure, so the new action was being fired again, with new "clean" Video instance.

Use
<%= form_for(#video, :validate => true) do |f| %>
instead of
<%= form_for #video do |f| %>
And in your video controller, your create method should be like this
def create
#video = current_user.build_video(video_params)
respond_to do |format|
if #video.save
flash[:success] = "Video Created!"
format.html {redirect_to( :controller => "controller_name", :action => "action_name" )}
else
format.html {render :action => "action_name"}
end
end
end

Related

Ruby on rails - create Invitation on Project page without render new action

I try to create a project page with a form to send invitation to other users. The Owner (who have created the project) can invite other users to participate to the project.
Right now, Here is the code :
views/projects/show.html.erb
<div class="container">
<h3> <%= #project.title %> </h3>
<h6> Créé par <%= link_to #project.owner.username, user_path(#project.owner) %> </h6>
<hr>
<h3> Inviter des utilisateurs au projet </h3>
<!-- form for search users -->
<%= form_tag new_invite_path, method: :post, :class => 'form-inline' do %>
<div class="form-group">
<%= text_field_tag :search, params[:search], size: 30, class: 'form-control' %>
</div>
<%= submit_tag 'Ajouter au projet', class: 'btn btn-success' %>
<% end %>
<!-- end form for search users -->
<!-- display users results -->
<% #users.each do |user| %>
<p> <%= user.username %> | <%= user.email %> </p>
<% end %>
<!-- end display results -->
</div>
controllers/projects_controller.rb
class ProjectsController < ApplicationController
def show
#project = Project.find(params[:id])
#users = User.search(params[:search])
end
def new
#project = Project.new
end
def create
#project = Project.new(project_params)
#project.owner = current_user
#project.members = []
if #project.save
puts #project
redirect_to user_path(current_user)
else
puts 'something went wrong'
puts #project.errors.full_messages
render 'new'
end
end
private
def project_params
params.require(:project).permit(:title, :description, :client, :deadline, :owner, :members)
end
end
On the project page, I have an Ajax form to find all the users, with their username and email.
Now, when I submit this form, I want to create an invitation (a notification, but I haven't begin the notification system). So, I have created this model :
class Invite
include Mongoid::Document
field :email
belongs_to :project
belongs_to :sender_id, :class_name => 'User'
belongs_to :recipient_id, :class_name => 'User'
end
And a controller :
class InvitesController < ApplicationController
def new
#invite = Invite.new(email: params[:search], sender_id: current_user.id)
byebug
#invite.save
end
def create
#invite = Invite.new(params[:search])
if #invite.save
flash[:success] = 'the invitation is send'
redirect_to user_path(current_user)
else
render 'projects/show'
end
end
end
So as you can see, I want to save the invite in my db (MongoDB -> Mongoid), but when I submit the form (on the project/show page), I have this error :
No route matches [POST] "/invites/new"
It's normal, but I want to know :
how to insert data in my database without rendering a view ?
how to have access to user ID with the email adresse ? (which is in the DB)
Thank you !
NB: don't hesitate to ask if you need more code to answer
1) You can insert the data on the database without rendering anything with this line on the controller render :nothing => true, :status => 200
so your create method will be like this
def create
#invite = Invite.new(params[:search])
if #invite.save
flash[:success] = 'the invitation is send'
render :nothing => true, :status => 200
else
render 'projects/show'
end
end
and this is wrong No route matches [POST] "/invites/new" when you try to create something, you will need to go to create, not the new action, just change the url on the form, because you are pointing to the wrong action.
2) If you have an User model and want to load an user by email, you can do something like this
User.find_by_email("the email of the user")
this is your model is User and the column where the email is, is named "email"

Can't get a custom edit form to save

I want to have a form to just edit one field for my user's model that is separate from the scaffold generated _form.erb.
The form will show but it will not save. When I modify the def in the controller with a respond_to block, the form is bypassed and I just get the record shown.
employee_supervisor_edit.html.erb has <%= render 'employee_supervisor_form' %>
routes.rb contains match '/employee_supervisor_edit/:id' => 'users#employee_supervisor_edit' , via: [:get, :post ]
the form is _employee_supervisor_form.erb
users_controller.rb has
def employee_supervisor_edit
#users = User.all
#user = User.find(params[:id])
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
I also have have the following in my users controller.
def user_params
# params.require(:user).permit(:login,
params.permit(:login,
:group_strings,
:name,
:ou_strings,
:email,
:active_employee,
:last_name,
:first_name,
:is_supervisor,
:#supervisor_id)
end
end
If I comment out the whole respond_to block, the form appears but no data is saved. If I put the respond_to block in, then the form is bypassed and it goes right to the show method.
I'm not sure if the problem is related to getting the following error if I use params.require(:user).permit(:login, instead of params.permit(:login,
ActionController::ParameterMissing in UsersController#employee_supervisor_edit
param is missing or the value is empty: user
Rails.root: C:/Users/cmendla/RubymineProjects/employee_observations
Application Trace | Framework Trace | Full Trace
app/controllers/users_controller.rb:134:in `user_params'
app/controllers/users_controller.rb:16:in `block in employee_supervisor_edit'
app/controllers/users_controller.rb:15:in `employee_supervisor_edit'
========== added ==============
I have the following associations in my user.rb
Class User < ActiveRecord::Base
has_many :subordinates, class_name: "User", foreign_key: "supervisor_id"
belongs_to :supervisor, class_name: "User"
======== added : =====================
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
User Login: <%= #user.login %><br>
User Name: <%= #user.name %> <br>
<div class="field">
<%= f.label :active_employee %>
<%= f.check_box :active_employee %>
</div>
<div class="field">
<%= f.label :supervisor %>
<%= f.collection_select(:supervisor_id, User.order('name'), :id, :name, prompt: true)%>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The problem stemmed from my data. Since I am in the development process, I don't have all the error checking I need in place. Null fields or associations pointing to non existent records cause errors where it isn't always obvious (at least to me) that the problem is the data, not the code itself.
I went in with an sql editor and made sure that the contents causing the issues were not set to null and that the columns such as supervisor_id were pointing to actual existing records, not records that were deleted.
I changed params.permit(:login, back to params.require(:user).permit(:login, and now the form is saving as expected.
My next step will be to add validations for input and some error checking for the index and show methods. For the long term, I think that I need to become more proficient with testing as that might show areas that could cause these types of issues.

Incorrect param submitting

I have a form for casting your vote for your favourite image.
<%= form_for(#imagevote) do |f| %>
<% #miniature.collections(:photo).each do |collection| %>
<% if collection.photo.exists? %>
<td><div class="photo1">
<%= link_to image_tag(collection.photo.url(:thumb), :retina => true), collection.photo.url(:original), :retina => true, :class => "image-popup-no-margins" %>
<%= f.radio_button(:collection_id, collection.id) %>
<%= f.hidden_field :voter_id, :value => current_user.id %>
<%= f.hidden_field :voted_id, :value => collection.user_id %>
<%= f.hidden_field :miniature_id, :value => #miniature.id %>
<p>Painted by <%= link_to collection.user.name, collection.user %></p>
</div></td>
<% end %>
<% end %>
<%= f.submit "Vote" %>
<% end %>
Everything submits correctly except for the hidden_field :voted_id which for some reason duplicates the current_user.id.
UPDATE
I've tried logging in as another user and it seems that :voted_id is not duplicating current_user.id but rather that it is always "7" which was the :user_id I was using to test it before. Now logged in as user number 4 it is still entering the :voted_id as 7. I'm lost.
The link to the imagevotes view is as follows:
<%= link_to "See more and change your vote.", edit_imagevote_path(:miniature_id => #miniature, :voter_id => current_user.id) %>
Here is my image votes controller
class ImagevotesController < ApplicationController
respond_to :html, :js
def new
#imagevote = Imagevote.new
#miniature = Miniature.find(params[:miniature_id])
end
def edit
#imagevote = Imagevote.find_by_miniature_id_and_voter_id(params[:miniature_id],params[:voter_id])
#miniature = Miniature.find(params[:miniature_id])
end
def create
#imagevote = Imagevote.new(imagevote_params)
if #imagevote.save
flash[:success] = "Vote registered"
redirect_to :back
else
flash[:success] = "Vote not registered"
redirect_to :back
end
end
def update
#imagevote = Imagevote.find(params[:id])
if #imagevote.update_attributes(imagevote_params)
flash[:success] = "Vote changed."
redirect_to :back
else
redirect_to :back
end
end
private
def imagevote_params
params.require(:imagevote).permit(:collection_id, :voter_id, :voted_id, :miniature_id)
end
end
You only have one #imagevote object, but you are outputting the hidden fields inside your collection loop so you will have multiple fields in the form referencing the same attribute on the model: if you check the html that is generated, you should see multiple hidden fields with the same name attribute.
The way that browsers handle multiple inputs with the same name means that the param that comes through for :voted_id will always be the :user_id from the last collection.
It's difficult to say because you didn't provide your model and your loop code stripped.
I would guess that you loop over collection that belongs to the current_user. And in this case you will have current_user.id always be the same as collection.user_id. May be you wanted to see collection.photo_id?

Nested form fields_for text_area is not displaying

I have three-tier model:
User has_many Asks has_many Outcomes
On the home page, I would like the user to be able to add an Outcome to their Ask when they mark it complete. I'm trying to use a nested form to display the Outcome description in the Ask form which also updates the done flag and done date.
Like other users/questions here on SO, I cannot get a nested form to display on the screen. I've followed instructions from the other questions, but still the nested field is not displaying. Am wondering if someone can spot the issue in the code below?
Ask Model
class Ask < ActiveRecord::Base
attr_accessible :category, :description, :done, :followed_up,
:helper, :public, :date_done, :date_followed_up, :user_id, :outcomes_attributes
belongs_to :user, counter_cache: true
has_many :outcomes
accepts_nested_attributes_for :outcomes
end
Ask Controller
class AsksController < ApplicationController
def new
#ask = current_user.asks.build(params[:ask])
#ask.outcomes.build
end
def create
#ask = current_user.asks.build(params[:ask])
if #ask.save!
respond_to do |format|
format.html { redirect_to edit_ask_path(#ask) }
format.js
end
else
flash[:error] = "Something is wrong. The Ask was not saved..."
end
end
def edit
#ask = current_user.asks.find(params[:id])
end
def update
#ask = current_user.asks.find(params[:id])
#ask.outcomes.build
#ask.update_attributes(params[:ask])
respond_to do |format|
format.html { redirect_to edit_ask_path(#ask) }
format.js
end
end
end
Home Page Controller (this form is on the home page)
class StaticPagesController < ApplicationController
def home
if signed_in?
#ask = current_user.asks.build(params[:ask])
#ask.outcomes.build
end
end
Form Partial rendered on the home page
<% if current_user.asks.any? %>
<ul id="ask-list-items">
<% current_user.asks.where(done: false).each do |a| %>
<%= form_for(a) do |f| %>
<li><%= a.description %></li>
<%= f.hidden_field :date_done, value: Date.today %>
<%= f.hidden_field :done, :value=>true %>
<%= f.submit "Mark as done", class: "btn btn-small hidden done_btn", id: "a-#{a.id}-done" %>
<%= f.fields_for :outcomes do |builder| %> # << These fields are not showing up
<%= builder.text_area :description, placeholder: "Describe the outcome...", id: "ask-message" %>
<% end %>
<%= f.submit "Save outcome", class: "btn btn-primary" %>
<% end %>
<% end %>
</ul>
<% end %>
When using symbol in form_for and fields_for Rails tries to use an instance variable with he same name, e.g. #outcomes for :outcomes. So try (for existing outcomes):
<% #outcomes = a.outcomes %>
before the line with f.fields_for :outcomes....
And for new outcomes:
<% #outcomes = a.outcomes.build %>
(the last with contribution to the owner of the question)

Controller and routes issues in my rails app

I have an app where users can create courses, and each course has_one syllabus. How could I go about configuring my courses and syllabuses (I know it's Syllabi but apparently Rails doesn't) controller, and my routes, so on a course's page there is a link to create or show the course's syllabus, and a link back to the course from the show syllabus page?
In my routes I have:
resources :courses do
resources :syllabuses
member do
put :enroll #this is so users can enroll in the course
end
end
Currently , so the course_id will be saved in the syllabus table in my courses_controller, I have:
def create_syllabus
#course = Course.find(params[:id])
#syllabus = #course.build_syllabus(params[:syllabus])
if #syllabus.save
redirect_to #syllabus, notice: "Successfully created syllabus."
else
render :new
end
end
then in my courses show page I have:
<section>
<% if (current_user.courses.includes(#course) ||
current_user.coursegroups.find_by_course_id_and_role(#course.id, "admin")) %>
<%= render 'create_syllabus' %>
<% end %>
</section>
then in my create_syllabus form (in my courses views folder) I have tried starting it off with:
# I have #course = Course.find(params[:id]) defined in show in the
#courses_controller
<%= form_for #course.create_syllabus do |f| %>
<%= form_for #course.syllabus.create_syllabus do |f| %>
<%= form_for #course.syllabus.create do |f| %>
and I get an undefined method error for each of those.
If you want to create a new syllabus in your show action of a specific course, you can add this to your controllers and views:
courses_controller.rb
#course = Course.find(params[:id])
# Build a new #syllabus object, only if there is none for the current course
unless #course.syllabus
#syllabus = #course.build_syllabus
end
views/courses/show.html.erb
# Show the syllabus name if there is one, or show the form to create a new one
<% if #course.syllabus.name %>
<p>Syllabus: <%= #course.syllabus.name %></p>
<% else %>
<p>Create Syllabus:</p>
<%= form_for([#course, #syllabus]) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
syllabuses_controller.rb
def create
#course = Course.find(params[:course_id])
# Build new syllabus object based on form input
#syllabus = #course.build_syllabus(params[:syllabus])
if #syllabus.save
# redirect to /course/:id
redirect_to #course, notice: 'Syllabus was successfully created.' }
end
end
course.rb
class Course < ActiveRecord::Base
attr_accessible :name
has_one :syllabus
end
syllabus.rb
class Syllabus < ActiveRecord::Base
belongs_to :course
attr_accessible :name, :course_id
end
Some things that I left out but you should still include:
validations
rerendering form if something goes wrong
pulling things out into partials
fixing bad code like if #course.syllabus.name
pull out if/else logic into a helper
…

Resources