Rails 4 & Devise 4: Keep user on current page after updating profile - ruby-on-rails

I have a User model, and I am hoping to have different pages to edit their info so that I don't have everything on edit.html.erb
So far I have created views for page_content.html.erb and donation_options.html.erb which have my forms on them. Both work as intended and successfully update my User, but after submitting the form I am redirected the User root, which is show.html.erb. I would like to set it up so that the user stays on the current page after updating their profile. I am not sure if I need to edit my UsersController, or create a new controller, or take a different approach.
Here's an example of my form:
<%= form_for #user do |f| %>
<!--Some inputs-->
<div class="actions">
<%= f.submit 'Update', :class => "btn btn-primary" %>
<!--After submitting, I'm taken to /users/:id/. I'd like to stay on /users/:id/current_view-->
</div>
<% end %>

If you already have a UsersController you should set something up comparable to this:
Class UsersController < ApplicationController
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to your_path_here
end
end
end
I am not sure exactly what your UsersController looks like, but that should give you an idea. After a user is updated, use redirect_to with your path you would like the User sent to. You may also use redirect_to :back if you are looking to redirect back to the current page you are on.
Please see this existing SO post.

Related

Displaying a messaging right away to the user when page is loaded

I am not sure if this is possible but I want to display a flash message to the user when they come onto on of the pages automatically. I kind of played around with it but no luck. Does anyone know how to do that if so any help would be greatly appreciated!
CODE FOR CONTROLLER
class BookinController < ApplicationController
def flash
flash.now[:notice] = "Test"
render :action => :new
end
def bookin
#alert = "Successfully saved!"
end
def bookout
#customer_list = Customer.all
#customer_name = params[:customer_name_in]
#r = Customer.find_by_last(#customer_name)
end
end
CODE FOR VIEW
<h2>The Maintenance Functions are restricted to authorized users.
Please login below</h2>
<%= form_tag(bookin_bookout_path, :method => "post") do %>
<div class="field">
Name
<%= text_field_tag :customer_name_in %>
</div>
<br>
Password
<%= text_field_tag :customer_name_in %>
</div>
<br>
<div class="actions">
<br>
<%= submit_tag "Submit Customer Name" %>
</div>
<% end %>
<h2> Main Menu</td> </h2>
You could try the bootbox-rails gem.
In a nutshell:
Add it to your Gemfile,
Add it to your app/assets/javascripts/applications.js
Put something like this in your view:
<script>
<%= raw #alerts %>
</script>
Put something like this in your controller:
#alerts = "bootbox.alert('Some kind of alert!');"
Flash
You'll want to set the flash message in the action, so it's there when the user hits the page
The flash is basically a session variable which will only persist per one action, meaning if you set it on your action, the next one will not have the same message
You can set the flash, as you've already done, like this:
def action
flash[:notice] = "Welcome to our website"
end
Code
As RSB has queried, you've not provided us with the most specific code. So instead, I'll show you a simple example and look out for some comments to come back with updates:
#app/controllers/bookin_controller.rb
class BookinController < ApplicationController
def index
flash[:notice] = "Welcome To Our Page!"
end
end
#app/views/bookin/index.html.erb
<%= flash[:notice] %>
This will display your message for the rendered action. You don't need any specific methods - just set the flash var value in the action you're rendering

Having problems with putting database to use

So I have this books database and a burrows database. In burrows, there is a field for book_id and also a field for user_id, so that I can see who burrowed which book.
Now, I am trying to create a controller and view for it but it is not going well really. Right now the view is looking like this:
<% provide(:title, "Burrow") %>
<b align="center">Choose the name of the book you want t burrow'</b>
<%= form_for(#book) do |f| %>
<div class="forms">
<%= f.name %>
<%= f.check_box(:book_id) %>
<%= f.submit 'Submit!' %>
</div>
<% end %>
But this puts me to the problem where it creates an error because I want to put all books into #books in burrows controller. But I dont really see any other way? \
The final idea would be so that I have all the books displayed and after them a checkbox, so I can select which books I want to burrow. And after that I also want a dropdown menu where all users are listed, I can choose to burrow the book for another user, but the default value would be the logged in user but theres time till that. Right now I am struggline to understand, why my solution for listing books does not work?
Listing my controller here also:
class BurrowsController < ApplicationController
before_action :signed_in_user, only: [:index,:edit,:update, :destroy]
before_action :admin_user, only: :destroy
def index
#burrows = Burrow.all
end
def show
#burrow = Burrow.find(params[:id])
end
def new
#burrow = Burrow.new
end
def create
#burrow = Burrow.new(burrow_params)
if #burrow.save
flash[:success] = "Burrowing a book was successful!"
redirect_to #burrow
else
render 'new'
end
end
def listing
#book_list = Book.all
end
# Private section, makes the page unable to be seen for non logged in users
private
def burrow_params
params.require(:burrow).permit(:user_id, :book_id)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
# Redirecting not logged in user etc.
def signed_in_user
unless signed_in?
store_location
redirect_to '/sessions/new', notice: "Please sign in!"
end
end
end
Right now I am struggline to understand, why my solution for listing books does not work?
I'm not sure what listing you mean. The view you pasted apparently corresponds to the controller action Burrows#new?
So I'm going to tell you what's wrong with your view:
<%= form_for(#book) do |f| %>
This prints a form for a Book, not a Burrow. You could create a new book with this form, but that's certainly not what you're trying to do here.
You'll want to have all these variables in your controller:
def new
#users = User.all
#books = Book.all
#burrow = Burrow.new
end
so you can use collection_select with #users, have a #burrow object to use with form_for, and do a each loop on #books, for instance, like this:
<%= form_for(#burrow) do |f| %>
<% #books.each do |book| %>
<%= f.check_box :book_ids, multiple: true, book.id, nil %>
<% end %>
<%= f.collection_select :user_id, #users, :id, :name, {}, selected: current_user.id %>
<%= f.submit %>
<% end %>
Click the links for documentation on these commands: collection_select, check_box
This is not ideal code, but it's as close to your example as I can get.
I understand if you don't get this right away. Your code is a bit of a mess right now and there's too much wrong with it to be explained in one post and fixed by just one line. You might want to start over, and make a single controller action work before you try to make everything at once.
Sometimes it's better to sit back and really think about what you're trying to achieve, and first lay out how to achieve it inside your head; and only then start programming!
It seems to me that you're using the RailsTutorial by Michael Hartl, so all I can recommend to you right now is, read what you've read again more thoroughly and try to stick to his examples first until you feel confident, before really starting to make your very own application.

Possible to add a form into another models view in rails

I have a very small application I ma building in rails. It is a simple weight tracker app. I have created a User model which has a sign up page. Once the user logs in they are redirected to the user#show view. Here is the user controller so far:
class UsersController < ApplicationController
before_filter :authenticate_user!
def show
#user = current_user
end
end
I have 2 other models one is a Weight model and the other a Goal model, I would like it so what when a user signs up they are presented with a screen asking them to type in the current weight and goal weight this information will then be store in the Weight and Goal models respectively along with the logged in users ID.
So far I have been able to add a form to the user show.html.erb template :
<%= form_for #user do |f| %>
<%= f.fields_for :weight do |builder| %>
<fieldset>
<%= f.label :value, "Current weight" %><br />
<%= f.text_field :value %><br />
</fieldset>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Which renders the form correctly but when I then click on the submit button it simply goes to an error page saying Unknown action- The action 'update' could not be found for UsersController. Im assuming iM doing something wrong as it should try and send to the create action.
Is there anyone out there who could help me back on the right path, Im very much a noob at rails.
Well this has nothing to do with all your models. This pertains to the fact you have not defined an update method in your controller.
When you have done that look into accepts_nested_attributes_for if you want to nest models.
Besides all that, a show page usually shows a read only for of the object. An edit page has the editable form of the object.
You are using the form_for Rails helper and passing #user to it, because #user is a persistent model (saved in the db) then the generated form will have the action to /users/:id with PUT method so the request will be sent to an action named update in your UsersController, it seems that you don't have that action defined in your UsersController
it should be somthing like the following:
def update
#user = Users.find(params[:id])
if #user.update_attributes(params[:user])
# do something if saving succeeds
else
# do something if saving fails
end
end
I believe, after searching for this question having similar issues, that it is not update that is missing but edit.
I know this is an old thread, and you have probably solved the issue, but if not try adding this:
def edit
#user = User.find(params[:id])
end

Rails form not invoking create controller method on POST

I have the following form in my /app/views/password_resets/new.html.erb view
<% form_tag password_resets_path do %>
<label><%= t(:email) %>:</label><br />
<%= text_field_tag "email" %><br />
<br />
<%= submit_tag t("reset_password") %>
<% end %>
along with a controller called PasswordResetsController containing a create method:
def create
#user = User.find_by_email(params[:email])
if #user
#user.deliver_password_reset_instructions!
self.notice = t("password_reset_instructions_are_mailed")
redirect_to root_url
else
flash[:error] = t("no_user_found")
render :action => :new
end
end
When I go to /password_resets/new, fill out the form, and submit, the create method is invoked properly, since the PasswordResetsController::create() method is invoked when a POST happens to /password_resets.
However, when I put the form in another view, say, /app/views/test/index.html.erb, fill out the form, an submit, I get
Unknown action
No action responded to index. Actions:
access_forbidden, admin_created?,
check_roles, create, edit, find_order,
included, new, role_requirements,
role_requirements=, title, title=, and
update
Any ideas why transplanting the form is not working?
Turns out the issue was related to SSL. This showed up in the log:
Filter chain halted as [:ensure_proper_protocol] rendered_or_redirected.
The page I had the form on required SSL, and Rails did not like me submitting the form from an SSL page to to a non-SSL one. So, as a workaround, since I'm using ssl_requirement, I just put
ssl_required :all
in the password_resets controller, and now things work.

acts_as_commentable examples?

I have a model that I want to be commentable. I am having difficulty creating a form on my model's 'show' view that will allow comments to be created. I am not finding any good or useful examples. Can anyone point me to or show me an example of how to do this?
Example:
A simple blog application. I have a model called Post. It is commentable. So on the 'show' view I want to show a Post and, at the bottom, have the fields that, when completed and submitted, create a new comment associated with the post and put it in the database.
Sounds straightforward and I have it working so I can display comments that I have seeded. I just can't get a form to work to put new ones in. Any help is appreciated.
Lets assume a Post model. Make sure, you have
class Post < ActiveRecord::Base
acts_as_commentable
end
then in the view of say Post#show
<%= form_tag "/posts/add_new_comment" do %>
<%= hidden_field_tag "id", post.id %>
<%= text_area_tag "comment[comment]" %>
<%= submit_tag "Post Comment" %>
<% end %>
then in the PostController
def add_new_comment
post = Post.find(params[:id])
post.comments << Post.new(params[:comment])
redirect_to :action => :show, :id => post
end
and in routes.rb
match "/posts/add_new_comment" => "posts#add_new_comment", :as => "add_new_comment_to_posts", :via => [:post]
Hope this gets u up and running.
This is very, very basic stuff and you clearly need some better structure and approach to your learning. Buying a book, such as Agile Web Development with Rails, is the only real way to learn, otherwise you'll wander from problem to problem without ever actually learning anything well.
Say you have a post that you want to comment.
#routes.rb
map.resources :posts do |post|
post.resources :comments
end
#post_controller.rb
def show
#post.find params[:id]
#comment = #post.comments.new
end
#posts/show.html.erb
<%- form_for [#post, #comment] do |f|-%>
<%= f.text_area :body -%>
<%= f.submit -%>
<%- end -%>
#comments_controller
def create
#post = #post.find params[:post_id]
#comment = #post.comments.new params[:comment]
if #comment.save
redirect_to #post
This is an old question, but I want to throw in my solution as well as the gem's README is still unhelpful after all these years. It builds upon #Kunday's answer. The following will be a tutorial to use the act_as_commentable gem to...
Allow users to create comments under each post.
Show all comments belonging to a post.
This assumes that you already have a working "blog", whether it be pictures or posts. Install gem, then run rails g comment to get started.
Allow users to create comments under each post.
First, inside the model that you want to use commentable gem, add the following line as suggested in the gem's README.
class Post < ActiveRecord::Base
acts_as_commentable
end
Then create a new comment controller with the create action. Please note that the :authenticate_user! is part of devise which is a gem for creating easy authentication. current_user is also part of devise as a helper. It is needed if you want to display the user's name/email under the comment body.
class CommentsController < ApplicationController
before_action :authenticate_user!
def create
post = Post.find_by(id: params[:id])
comment = post.comments.build(comment_params)
comment.user = current_user
if comment.save
flash[:notice] = "Comment has been created."
redirect_to post
else
flash[:alert] = "Comment has not been created."
end
end
private
def comment_params
params.permit(:comment)
end
end
Next, set up the routes. It's just this. This means that when someone sends a post request to comments, we will run to create action inside the comments controller.
post 'comments' => 'comments#create', as: "create_comment"
The as: "create_comment" gives it an alias, so you can do create_comment_path. Now, on the show view of Post, we'll add the form. The divs will help you add css.
<div class="comment-section">
<%= form_tag create_comment_path, method: "post" do %>
<%= hidden_field_tag "id", #post.id %>
<%= text_area_tag :comment %>
<%= submit_tag "Submit" %>
<% end %>
</div>
Now to show each comment under the Post show view.
The divs will help you add css, comment.user.name will work if your User class has a name column. Else, change it to email or whatever identifier you choose to use.
<div class="comment_list">
<% #comments.each do |comment| %>
<%= comment.comment %> <br>
<%= comment.user.name %> <br>
<br>
<% end %>
</div>
And finally, in order for #comments to exist in the show page, go to your Post controller, and under show, add the following:
def show
#post = Post.find_by(id: params[:id])
#comments = #post.comments.all
end
This should be good for the requirements. Good luck.

Resources