error validations not showing in rails - ruby-on-rails

I have hit a wall in displaying error messages. The error validation messages don't show up.
On my users show template:
<%= form_for([current_user, #pub_message]) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.hidden_field :to_id, :value => #user.id %>
<div class="micropost_message_field">
<%= f.text_area :content, placeholder: "Any thoughts? Questions? Comments?", :id => 'public_message_text' %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
which goes to my pub_messages#create
def create
#pub_message = current_user.pub_messages.build
#pub_message.to_id = params[:pub_message][:to_id]
#pub_message.user_id = current_user.id
#pub_message.content = params[:pub_message][:content]
if #pub_message.save
flash[:success ] = "Your post has been sent"
unless params[:pub_message][:slug].nil?
redirect_to lesson_path(params[:pub_message][:slug])
else
redirect_to user_path(params[:pub_message][:to_id])
end
else
#redirect_to :controller => :users, :action => :show, :id => params[:pub_message][:to_id]
#redirect_to user_path(params[:pub_message][:to_id])
render 'users/show'
end
end
however it wont' display the error messages. ive read from a number of other stackoverflow posts that error_messages will not survive a redirect_to so instead i have a render. however, since the render only displays the view, i'm missing all the variables. i tried just copying and pasting everything from my user#show action earlier but it seems like a bad practice. if i did that, i also ran into the issue that all my templates are missing. it seemed like i have to move all my templates to a shared folder in order for this to work but it seems wrong since some things are specific to just the user.
my error messages are being displayed correctly elsewhere but i just cant figure out what is wrong with my pub_messages.
i have something very similar called microposts, and it works.
def create
#user = current_user
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to root_path
else
#feed_items = current_user.feed.paginate(page: params[:page], per_page: 20)
render 'static_pages/home'
end
end
The only difference I think is that it does a render but also has all the templates it needs in a shared folder. Is that the only way for this to work?

Related

No template found for UsersController#create, rendering head :no_content

OK, previously I had a problem with a no template error from users#create, now it complete 200 OK however does not redirect at all. Below is my edited users_controller.rb
I have a Signup, Login, Logout rails application with users as a resource. I am trying to save the first user in the database so I can then login but this error is server output when I try to "users#new" and "users#create" the full error is below, then my users_controller.rb and views/users -> new.html.erb
No template found for UsersController#create, rendering head :no_content
Completed 204 No Content in 35ms (ActiveRecord: 0.5ms)
users_controller.rb
def new
#user = User.new
end
def create
#user = User.new(user_params)
if (#user = User.find_by_email(params[:email]))
flash[:success] = "User already exists."
if #user.save
session[:user_id] = user.id
flash[:success] = "New User created."
redirect_to '/layouts/application'
else
render 'new'
end
end
end
new.html.erb
<h1>Sign Up</h1>
<%= form_with(model: #user) do |f| %>
<p> Username:</br> <%= f.text_field :username %> </p>
<p> Email:</br> <%= f.text_field :email %> </p>
<p> Password:</br> <%= f.password_field :password%></p>
<%= f.submit "Signup" %>
<% end %>
<% if #user.errors.any? %>
<ul class="Signup_Errors">
<% for message_error in #user.errors.full_messages %>
<li>* <%= message_error %></li>
<% end %>
</ul>
<% end %>
</div>
Do I have to have another html.erb file? And how can I tell what that has to be? Sorry for the obvious question, newb here.
As per your code if the User is not present it will not enter in the if block. Rails end up trying to find create.html as the current action is create.
To avoid this you must redirect it somewhere or render a template which you have done in the next if and else but it's not executing.
The condition is not letting it redirect to anywhere. Try moving the if block out like this.
def create
#user = User.new(user_params)
if User.exists?(email: params[:email]) # I think this should be `user_params[:email]` instead of `params[:email]`
flash[:error] = "User already exists."
redirect_to 'whereever/you/want/to/redirect' and return
end
if #user.save
session[:user_id] = user.id
flash[:success] = "New User created."
redirect_to '/layouts/application'
else
render 'new'
end
end

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?

Rails Controller code isn't executing

I must be missing something... my views are being rendered, but it appears like code in the controller isn't being executed. I can't find what's wrong.
When I click the login button in login.html.erb, the login_process method of the PublicController should be called to authenticate the user. That doesn't seem to happen as the view login_process.html.erb just displays, which shouldn't be possible.
I've even tried putting a flash[:notice] = "heyhey" on the login_screen action so it appears on the login form, but that doesn't happen either.
What have I done wrong?
Is it something in the routes.rb?
routes.rb
root :to => "public#index"
get "login",
:to => "public#login",
:as => "login_screen"
post "login_process",
:to => "public#login_process",
:as => "login_process"
get "logout",
:to => "public#logout",
:as => "logout"
public_controller.rb
class PublicController < ApplicationController
def login_screen
flash[:notice] = "heyhey"
end
def login_process
authenticated_user = User.authenticate params[:email], params[:password]
if authenticated_user
session[:user_id] = authenticated_user.id
session.countdown_start(1.minute)
redirect_to :public => :index
else
flash[:notice] = 'Email/Password incorrect. Receive a new password.'
flash[:color] = "invalid"
end
render :login_screen
end
def logout
session.countdown_abort
flash[:notice] = "You are now logged out"
redirect_to :login_screen
end
def count
render :text => session.countdown_count.to_i
end
end
views/public/login.html.erb
<h1>Login</h1>
<p id="notice"><%= notice %></p>
<%= form_tag :login_process do %>
<div class="field">
<%= label_tag :email %><br>
<%= text_field_tag :email %>
</div>
<div class="field">
<%= label_tag :password %><br>
<%= password_field_tag :password %>
</div>
<div class="actions">
<%= submit_tag "Login" %>
</div>
<% end %>
<h1>Login</h1>
<p id="notice"><%= notice %></p>
<%= form_tag :login_process do %>
<div class="field">
<%= label_tag :email %><br>
<%= text_field_tag :email %>
</div>
<div class="field">
<%= label_tag :password %><br>
<%= password_field_tag :password %>
</div>
<div class="actions">
<%= submit_tag "Login" %>
</div>
<% end %>
login_process.html.erb
I never expect to see this page as the user should be directed elsewhere
<p>login_process.html.erb</p>
<p id="notice"><%= notice %></p>
Update 1:
I've modified the authenticate action in the User model to be:
def authenticate(:email, :password)
#x = new User
#x.id = 123
return false #x
end
and login_process on PublicController to be:
def login_process
if true
flash[:notice] = 'boom'
else
flash[:notice] = 'Email/Password incorrect. Receive a new password.'
flash[:color] = "invalid"
end
redirect_to :login_screen
end
Unfortunately though... same issue. The login_process.html.erb is
displayed with no flash notices either.
Versions:
Ruby 2.0.0p247
Rails 4.0.0
The code in your controller is probably executing just fine.
I think the authenticate class method on User is not giving you the correct result. That's why it doesn't go through the if authenticated_user and just renders the login_process view. You don't have to call this render command though, it's done for you if you do nothing.
There's a problem with the login_process method though. You can't have a render call and a redirect_to be called together, now it can happen in your case, if the user is authenticated. Put the render :login_screen in the else case, otherwise you get the AbstractController::DoubleRenderError error saying: Render and/or redirect were called multiple times in this action. [etc.]
This is what you would get as an error if the user was authenticated.
Edit: Running this locally (stubbing User.authenticate) on a new Rails project it works. Flash notices appear and everything.
Also: render :login_screen is probably render :login, no? in login_process?
If nothing works still, what's your: Ruby version, Rails version, put authenticated_user = false # or true in login_process to see if it behaves differently.
redirect_to :public => :index
It seems like you are redirecting from login_process to /login_process?public=index, which I don't think is your intention.
If you are meaning to redirect to public#index, try
redirect_to root_path
(But I can't see that action in your public controller.)
I believe the problem is that you call two renders in one action. You can only render one page per action.
def login_process
authenticated_user = User.authenticate params[:email], params[:password]
if authenticated_user
session[:user_id] = authenticated_user.id
session.countdown_start(1.minute)
redirect_to :public => :index
else
flash[:notice] = 'Email/Password incorrect. Receive a new password.'
flash[:color] = "invalid"
end
render :login_screen
end
The user is authenticated and the redirect_to should bring you to the public/index, however, you call render :login_screen after the if statement, so it will execute that portion of the code no matter what and bring you back to the login.

Implementing ancestry on a nested resource throwing an error

I am implementing ancestry on a nested resource.
resources :loads do
resources :messages
end
Here is my index action
def index
load = Load.find(params[:load_id])
#messages = load.messages.scoped
#message = load.messages.new
end
My index.html.erb is throwing the following error.
Missing partial messages/message with {:locale=>[:en],
:formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in:
* "C:/Sites/final/cloud/app/views"
My index.html.erb is as follow
<% title "Messages" %>
<%= nested_messages #messages.arrange(:order => :created_at) %>
<%= render "form" %>
Here is my nested_message definition
module MessagesHelper
def nested_messages(messages)
messages.map do |message, sub_messages|
render(message) + content_tag(:div, nested_messages(sub_messages), :class => "nested_messages")
end.join.html_safe
end
end
Here is my _message.html.erb
<div class="message">
<div class="created_at"><%= message.created_at.strftime("%B %d, %Y") %></div>
<div class="content">
<%= link_to message.content, message %>
</div>
<div class="actions">
<%= link_to "Reply", new_load_message_url(:parent_id => message) %> |
<%= link_to "Destroy", [message.load, message], :confirm => "Are you sure?", :method => :delete %>
</div>
</div>
Any help appreciated.
This error states that your application has tried to search for a partial _messages.html.erb, as a result of this the partial must not be in your /app/views/messages which results in the message you are being shown. Check your messages directory and check if you have this partial. Going by your nested resources I am guessing your association between Load and Message is:
class Load < ActiveRecord::Base
has_many :messages
end
class Message < ActiveRecord::Base
belongs_to :load
end
Further more I noticed that you have the following line in your index action: #message = load.messages.new surely this does not seem right. Because what your telling your application to do is when the controller recieves a response to render the index action it should also create message by doing #message = load.messages.new which is why it is trying to render the partial.
To clarify things a bit more for you. If in your application you had a link_to to create a new user. Upon clicking the new user it will do something like:
def new
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
And will render `app/views/users/new.html.erb which inside this will most probably have a
<%= form_for #user do |f| %>
<%= render :partial => 'form', :locals => { :f => f } %>
<% end %>
This will call your partial which in normal cases would be _form.html.erb. The create action of a particular controller will come into play when you attempt to save the partial. Usually a create block for a controller will look like this:
def create
#title = "Create a user"
#user = User.new(params[:user])
if #user.save
redirect_to usermanagement_path
flash[:success] = "Created successfully."
else
#title = "Create a user"
render 'new'
end
end
Here inside the create action when your _form.html.erb or _message.html.erb is submitted it will try to create a new user by passing in the user through the params. I do thoroughly believe that your issue may potentially well be:
1) Your missing your _message.html.erb
2) Also you are calling a .new inside your index action.
Hope this clears this up for you.

Update database using 'update_attributes' through 'has_many'

I'm having a problem getting my first app (I'm a total newbie) to save a new associated record. I have two models (users and pictures) with a has_many/belongs_to association. I have set up the userController so that it can create a new picture as below:
def new_picture
#user = User.find(current_user.id)
#picture = #user.pictures.build
end
def create_picture
#user = User.find(params[:id])
#picture = #user.pictures.build(params[:picture])
if #picture.save
flash[:notice] = "Your picture was successfully added."
redirect_to :action => 'show', :id => #user.id
else
render :template => "new_picture"
end
end
and I use
<%= link_to("add picture", :action => 'new_picture', :id => #user.id) if current_user %>
to add a new one. But I'd also like to be able to edit. So I updated the usercontroller with some new code:
def edit_picture
#user = User.find(current_user.id)
#picture = #user.pictures.find(params[:id])
end
# When the user clicks the save button update record
def update_picture
#user = User.find(current_user.id)
#picture = #user.pictures.find(params[:picture])
respond_to do |format|
if #picture.update_attributes(params[:picture])
flash[:notice] = "Your picture was successfully updated."
redirect_to :action => 'show', :id => #user.id
else
render :template => "new_picture"
end
end
end
and added the edit link to show.erb:
<%= link_to("edit picture", :action => 'edit_picture', :id => picture.id) if current_user %>
It loads the edit form fine, with the data all in the right place, but on save all it's doing is giving me the error 'ArgumentError in UsersController#update_picture' with a bunch of Unknown key(s) from my pictures table.
Could somebody explain why? I feel like there is one piece of the jigsaw I haven't quite understood here....
Thanks in advance!
UPDATE: View code is as follows:
<h1>New picture for <%= #user.name %></h1>
<% form_for :picture, #picture, :html => { :multipart => true }, :url => {:action => 'update_picture', :id => #user.id} do |f| %>
Can't seem to see your problem in the view code, however you can do the same thing more elegantly (RESTful) as a nested route. That way you might be able to see the problem more clearly.
config/routes.rb:
resources :users do
member do
resources :pictures
end
end
app/controllers/pictures_controller.rb:
class PicturesController < ApplicationController
before_filter :find_picture, :only => [:edit, :update]
def edit
end
def update
if #picture.update_attributes params[:picture]
flash[:notice] = "Your picture was successfully updated."
redirect_to user_path(current_user)
else
render :edit
end
end
protected
def find_picture
#picture = current_user.pictures.find params[:id]
end
end
app/views/pictures/edit.html.erb:
<%= form_for [current_user, #picture] do |f| %>
<!-- some stuff -->
<% end %>
and to link to your edit form:
<%= link_to_if current_user, 'edit picture',
edit_user_picture_path(:user => current_user, :id => picture) %>
I suggest adding 'accepts_nested_attributes_for :pictures to the user model, and then do
<%= form_for #user do |form| %>
.. user fields
<%= form.fields_for :pictures do |picture_form| %>
.. picture fields
<% end %>
<%= form.submit %>
<% end %>
in the view.
Another option is to create a new controller for the pictures. That may be simpler.

Resources