I’m using Rails 5. When my user is logged in, I want to replace the ‘/users/4’ action with a generic ‘/dashboard’ home link. I would also like the remove the user’s ability to typing in ‘/users/##’ into the browser, instead only allowing them to visit ‘/dashboard’. How do I do this? Currently, in my config/routes.rb I have
get '/dashboard', to: 'users#show'
resources :users
and in my users_controller.rb file I have
def show
#user = User.find(params[:id])
#user_subscriptions = UserSubscription.find_active_subscriptions_by_user(#user)
end
But currently when I visit “/dashboard” in my browser, I get the error
Couldn't find User with 'id'=
How can I set up my route to disable the show action but allow /dashboard to successfully navigate to the action above?
What I like to do is something like this
get '/dashboard' => 'users#show', as: :dashboard
now on your view you can do
link_to 'Dashboard', dashboard_path(current_user)
and in the controller you can do
def show
params[:id] == current_user.id unless params[:id]
#user = User.find(params[:id])
#user_subscriptions = UserSubscription.find_active_subscriptions_by_user(#user)
end
Related
I attempted to use the sinatra-flash gem with my application and get an "undefined local variable or method 'flash'" error when I try to run it.
my_app:
require 'sinatra/base'
require 'sinatra/flash'
class GGInfraUserManager < Sinatra::Base
enable :sessions
register Sinatra::Flash
...(rest of app)
post '/' do
flash[:error] = "Password must be a minimum of 8 characters" unless new_password.match /.{8}/
log.info "#{Time.now} password meets policy requirements"
end
redirect '/'
end
In my erb view file (at the top):
<div id="flash" class="notice">
<a class="close" data-dismiss="alert">×</a>
<%= flash.now[:error] %>
</div>
Can someone please tell me how to correct this error so that the flash functionality will work?
While the gem seems comfortable enough to use why not implement it yourself. It's in fact just a couple of lines:
#in your app.rb:
helpers do
#a partial helper
def partial(template, locals = {})
slim template, :layout => false, :locals => locals
end
#the flash helper
def flash
#flash = session.delete(:flash)
end
end
get '/' do
session[:flash] = ["Some happy news", "alert-success"]
end
Then you can add a partial view which I called partial_flash.slim
-if flash
-message, status = #flash
.alert class=(status) = message
You call that partial usually from your layout file or any other view that needs a flash message:
==partial :partial_flash
So a route is called, the layout is loaded and checks if flash. If there is, it displays a flash message with a specified class. I use Twitter Bootstrap, so alert-success is a green message box.
You can see an example app here: https://github.com/burningTyger/farhang-app
I'm making AJAX based application with Devise as authentication system. The problem I encountered is that when I sign in with Devise with AJAX, then when view changes and log out button appears it's showing this error when clicked:
ActionController::InvalidAuthenticityToken in Customization::SessionsController#destroy
ActionController::InvalidAuthenticityToken
Parameters:
{"_method"=>"delete",
"authenticity_token"=>"hitX5aEjoTzi3tKP3y76+c60MuJumv5mwNEjyGUOQiY="}
Here you have my devise session controller's create method for signing in (I had to change few things to make AJAX happen):
# POST /resource/sign_in
def create
self.resource = warden.authenticate!(auth_options)
sign_in(resource_name, resource)
yield resource if block_given?
if user_signed_in?
flash[:logged] = "Zalogowany"
respond_to do |format|
format.html { redirect_to root_path }
format.js { render "sign_in_success.js.erb" }
end
end
end
sign_in_success.js.erb file:
$("body").empty();
$("body").append("<%= j(render template: 'layouts/user') %>");
button inside "layouts/user":
a href="#{destroy_user_session_path}" data-method="delete" rel="nofollow"
button.btn.btn-primary.m-r-20 type="button"
b Log Out
How do I send Authenticity Token with AJAX? Can I send it to "layouts/user" via locals option in render and use it this way?
I have solution. The problem was that csrf_meta_tags, was not updated when new session was created. The solution to that problem was to include additional code inside sign_in_success.js.erb file:
$("body").empty();
$("meta[name='csrf-token']").remove()
$("meta[name='csrf-param']").remove()
$("head").append("<meta name='csrf-token' content='<%= form_authenticity_token %>'>");
$("head").append("<meta name='csrf-param' content='<%= request_forgery_protection_token %>'>");
$("body").append("<%= j(render template: 'user/logged_signed') %>");
With code seen above firstly we are empting body element , then we are removing from DOM meta tags created by csrf_meta_tags helper. After that we are manually adding new csrf-token and csrf-param, this time our new authenticity token is assigned to meta name="csrf-token".
After that when we click on our log_out button rendered by "user/logged_signed" template we are logged out successfully and back at our root_path.
I recently implemented a new homepage (index.html) on my rails app (into folder public/index.html) with /signin and /signup paths. Before I implemented index.html on my website, I have been redirecting users to root_url (which is home.html.erb) after sign in or sign up.
When they sign out, I've been redirecting them to root_path.
The problem is that after this new index.html, when users try to log in or sign up, they get redirected back to index.html. Is there a place to have them log in successfully to the original root_url without requiring many code edits?
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:session][:email])
if user && user.authenticate(params[:session][:password])
sign_in user
redirect_to root_path
else
flash.now[:error] = "Invalid email/password combination"
render 'new'
end
end
def destroy
sign_out
redirect_to root_path
end
end
UsersController
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome!"
redirect_to root_path
else
render 'new'
end
end
This is what I have in my routes.rb
root to: 'static_pages#home'
First off the only difference between root_url and root_path (and in general between foo_url and foo_path) is that the former is a full url (i.e. http://example.com/...) whereas the latter is just the path (the bit after the hostname). For a simple redirect they'll have the same result.
If public/index.html exists then that is where visits to '/', (i.e. root_path) will go.
If you want users to be sent to a different page after signup then change your redirect. For example if your routes file had
get '/home' => 'home#index', :as => :home
then redirecting to home_path would send people to the index action of the home controller.
The problem seems to be that your public/index.html overrides your root_path Rails route.
You cannot access the root_path if there is a file called index.html in your public directory.
You need to rename index.html to something else or use another path other than your root_path
EDIT:
Another option is to have two different erb templates for the root_path. Then in the controller action for the root_path, you could do this:
class StaticPages < ApplicationController
def home
if user_signed_in?
render 'home_signed_in'
else
render 'home_signed_out'
end
end
end
You would then need to create two erb templates at,
/app/views/static_pages/home_signed_in.html.erb
and
/app/views/static_pages/home_signed_out.html.erb
You would also need to define or replace the user_signed_in? method in my example code with your own method to detect if the user is signed in. And don't forget to remove /public/index.html
Try to change root_path with home_ControllerName_path, where ControllerName must be the name of the controller handling the home action.
go to your routes.rb file and make following change
root :to => 'main#home_page'
you can redirect to any route by modifying root: in config/routes.rb file
The code below is not working for some reason. As I click at "test" it redirects me to /home/test and shows nothing.
view/home/index.html.erb
<%= link_to "test", { :controller => "home", :action => "test" }, :remote => true %>
<div id='test_div'>
</div>
view/home/index.js.erb
$("#test_div").html("some text");
controller
class HomeController < ApplicationController
def test
"test123 test456"
respond_to() do |format|
format.js {render :layout => false}
end
end
end
What should I do to refresh div_test using ajax?
What does your routes file look like? Can you post it on here? Do a rake routes and post the output.
Here are some things that may help you:
Rails documentation for routing
Also, check out the Ajax on Rails Documentation and the section on link_to_remote. The link_to_remote function is not in Rails. What version of rails are you on? Bash: $ rails -v
Look at this answer on S.O. regarding AJAX on Rails calls.
Edit: Here is another answer regarding this that may help.
Another answer on SO for updating existing element
Edit: looking over this again, I dont think you need () after respond_to or the {...} in link_to. Look at the third link. I think you need to put the page in a partial and render it. Its not rendering right now since its render :layout => false
I have a form I built using Formtastic in Rails 3. The form submits to the #create action of ClientsController, and if the save is successful the controller redirects to a "thank you" page. If the save is not successful, it redirects to the page where the form is embedded. I'd like to be able to show the validation errors inline on the form page, but after the redirect back to that page, the errors object comes back empty.
What can I do so I can display the validation errors on the form?
Here is the code from the controller.
if client.save && event.save
redirect_to "/thank-you"
else
redirect_to :back
end
Some additional details: I am using RefineryCMS so there is no view for the page where the form is, and therefore I can't render the view.
You need to save your errors into session.
if client.save && event.save
session[:client_create_errors] = nil
redirect_to "/thank-you"
else
session[:client_create_errors] = client.errors
redirect_to :back
end
now you can access errors object from anywere using session[:client_create_errors]
Why not:
render :action => 'name-of-the-view-the-form-is-in'
instead of the redirect_to :back ?