devise user under nested route - ruby-on-rails

I have a resource called "Store" that can have many accounts registered, but how im supposed to do this using device? i've setup this
class Store
has_many :accounts
end
class Account
belongs_to :store
end
Panel::Application.routes.draw do
resources :stores do
devise_for :accounts
end
end
but im getting
Showing panel/app/views/accounts/registrations/new.html.haml where line #2 raised:
undefined method `account_registration_path' for #<Module:0x007f9a67940918>
This is bc its expecting something like "account_store_registration_path" but where all this logic goes
rake routes output
account_store_password POST /accounts/stores/:store_id/password(.:format) devise/passwords#create
new_account_store_password GET /accounts/stores/:store_id/password/new(.:format) devise/passwords#new
edit_account_store_password GET /accounts/stores/:store_id/password/edit(.:format) devise/passwords#edit
PATCH /accounts/stores/:store_id/password(.:format) devise/passwords#update
PUT /accounts/stores/:store_id/password(.:format) devise/passwords#update
cancel_account_store_registration GET /accounts/stores/:store_id/cancel(.:format) devise/registrations#cancel
account_store_registration POST /accounts/stores/:store_id(.:format) devise/registrations#create
new_account_store_registration GET /accounts/stores/:store_id/sign_up(.:format) devise/registrations#new
edit_account_store_registration GET /accounts/stores/:store_id/edit(.:format) devise/registrations#edit
PATCH /accounts/stores/:store_id(.:format) devise/registrations#update
PUT /accounts/stores/:store_id(.:format) devise/registrations#update
DELETE /accounts/stores/:store_id(.:format) devise/registrations#destroy
account_store_confirmation POST /accounts/stores/:store_id/confirmation(.:format) devise/confirmations#create
new_account_store_confirmation GET /accounts/stores/:store_id/confirmation/new(.:format) devise/confirmations#new
GET /accounts/stores/:store_id/confirmation(.:format) devise/confirmations#show

So to accomplish this i did something very simple
I define an additional route for the account:
Panel::Application.routes.draw do
devise_for :accounts
resources :stores do
resources :accounts
end
end
I generated an accounts controller and views, and used the Devise generated model. So I used the new controller to create accounts and the devise helpers to manage the login logic.
So now i can have Accounts that belongs to an store

Related

Missing :id in my routes in rails4

hi,
I am having a problem with my routes. Just noticed a strange thing. I have no :id in my show/edit/... routes.
This is my rake.routes output:
WARNING: Nokogiri was built against LibXML version 2.9.0, but has dynamically loaded 2.9.2
Prefix Verb URI Pattern Controller#Action
new_person_session GET /persons/sign_in(.:format) devise/sessions#new
person_session POST /persons/sign_in(.:format) devise/sessions#create
destroy_person_session DELETE /persons/sign_out(.:format) devise/sessions#destroy
person_password POST /persons/password(.:format) devise/passwords#create
new_person_password GET /persons/password/new(.:format) devise/passwords#new
edit_person_password GET /persons/password/edit(.:format) devise/passwords#edit
PATCH /persons/password(.:format) devise/passwords#update
PUT /persons/password(.:format) devise/passwords#update
supplier_password POST /suppliers/password(.:format) devise/passwords#create
new_supplier_password GET /suppliers/password/new(.:format) devise/passwords#new
edit_supplier_password GET /suppliers/password/edit(.:format) devise/passwords#edit
PATCH /suppliers/password(.:format) devise/passwords#update
PUT /suppliers/password(.:format) devise/passwords#update
facilitator_password POST /facilitators/password(.:format) devise/passwords#create
new_facilitator_password GET /facilitators/password/new(.:format) devise/passwords#new
edit_facilitator_password GET /facilitators/password/edit(.:format) devise/passwords#edit
PATCH /facilitators/password(.:format) devise/passwords#update
PUT /facilitators/password(.:format) devise/passwords#update
customer_password POST /customers/password(.:format) devise/passwords#create
new_customer_password GET /customers/password/new(.:format) devise/passwords#new
edit_customer_password GET /customers/password/edit(.:format) devise/passwords#edit
PATCH /customers/password(.:format) devise/passwords#update
PUT /customers/password(.:format) devise/passwords#update
cancel_customer_registration GET /customers/cancel(.:format) devise/registrations#cancel
customer_registration POST /customers(.:format) devise/registrations#create
new_customer_registration GET /customers/sign_up(.:format) devise/registrations#new
edit_customer_registration GET /customers/edit(.:format) devise/registrations#edit
PATCH /customers(.:format) devise/registrations#update
PUT /customers(.:format) devise/registrations#update
DELETE /customers(.:format) devise/registrations#destroy
home_index GET /home/index(.:format) home#index
root GET / home#index
suppliers_index GET /suppliers/index(.:format) suppliers#index
facilitators_index GET /facilitators/index(.:format) facilitators#index
customers_index GET /customers/index(.:format) customers#index
new_customers GET /customers/new(.:format) customers#new
customers_newCustomer POST /customers/newCustomer(.:format) customers#newCustomer
customers_editCustomer GET /customers/editCustomer(.:format) customers#editCustomer
parties POST /parties(.:format) parties#create
new_parties GET /parties/new(.:format) parties#new
edit_parties GET /parties/edit(.:format) parties#edit
GET /parties(.:format) parties#show
PATCH /parties(.:format) parties#update
PUT /parties(.:format) parties#update
DELETE /parties(.:format) parties#destroy
parties_index GET /parties/index(.:format) parties#index
visitors_new POST /visitors/new(.:format) visitors#new
visitors_create POST /visitors/create(.:format) visitors#create
this is my routes.rb:
Rails.application.routes.draw do
# devise_for :people
devise_for :persons, :skip => :registrations
devise_for :suppliers, :facilitators, skip: [:registrations, :sessions]
devise_for :customers, :skip => :sessions
# routes for all users
authenticated :persons do
end
# routes only for customers
authenticated :customers, lambda {|u| u.type == "Customer"} do
end
# routes only for companies
authenticated :facilitators, lambda {|u| u.type == "Facilitator"} do
end
# routes only for suppliers
authenticated :suppliers, lambda {|u| u.type == "Supplier"} do
end
# mde toevoegeingen
get 'home/index'
root to: "home#index"
get 'suppliers/index'
get 'facilitators/index'
get 'customers/index'
resource :customers, :only => :new
match 'customers/newCustomer', to: 'customers#newCustomer', via: :post
match 'customers/editCustomer', to: 'customers#editCustomer', via: :get
resource :parties
get 'parties/index'
match 'visitors/new', to: 'visitors#new', via: :post
match 'visitors/create', to: 'visitors#create', via: :post
end
My urls show a '.' instead of a '/' before the 'id'. this is an example url for the show method of a model:
http://localhost:3000/parties.2
The strange thing is that the normal routing is working. Strange because the dot is intended for defining the format.
Now I need the format becase of a remote: true behaviour I am implementing I am getting into troubles.
What did I do wrong?
regards Martijn
Try to change:
resource :parties
To:
resources :parties
Just like Brad Werth said in comments.
the plural resources
resources :photos
creates
GET /photos Photos index display a list of all photos
GET /photos/new Photos new return an HTML form for creating a new photo
POST /photos Photos create create a new photo
GET /photos/1 Photos show display a specific photo
GET /photos/1/edit Photos edit return an HTML form for editing a photo
PUT /photos/1 Photos update update a specific photo
DELETE /photos/1 Photos destroy delete a specific photo
in contrast to Singular Resources
You can also apply RESTful routing to singleton resources within your
application. In this case, you use map.resource instead of
map.resources and the route generation is slightly different. For
example, a routing entry of
resource :geocoded
GET /geocoder/new Geocoders new return an HTML form for creating the new geocoder
POST /geocoder Geocoders create create the new geocoder
GET /geocoder Geocoders show display the one and only geocoder resource
GET /geocoder/edit Geocoders edit return an HTML form for editing the geocoder
PUT /geocoder Geocoders update update the one and only geocoder resource
DELETE /geocoder Geocoders destroy delete the geocode resource

How to have a 'model' index and then also a 'model' index for each user(models_path & user_models_path)

I have a Tool model and I want to be able to have both a regular tools index (tools_path) that lists all the tools in the database for all users & also an users tool index(users_tools_path) that lists all the tools for a particular user.
I am not sure what the rails way of implementing this is. I am using devise and my instinct was to do the following in my routes:
Rails.application.routes.draw do
devise_for :users
root 'tools#index'
resources :users do
resources :tools
end
resources :tools
end
This gets me the following routes:
Prefix Verb URI Pattern Controller#Action
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
root GET / tools#index
user_tools GET /users/:user_id/tools(.:format) tools#index
POST /users/:user_id/tools(.:format) tools#create
new_user_tool GET /users/:user_id/tools/new(.:format) tools#new
edit_user_tool GET /users/:user_id/tools/:id/edit(.:format) tools#edit
user_tool GET /users/:user_id/tools/:id(.:format) tools#show
PATCH /users/:user_id/tools/:id(.:format) tools#update
PUT /users/:user_id/tools/:id(.:format) tools#update
DELETE /users/:user_id/tools/:id(.:format) tools#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
tools GET /tools(.:format) tools#index
POST /tools(.:format) tools#create
new_tool GET /tools/new(.:format) tools#new
edit_tool GET /tools/:id/edit(.:format) tools#edit
tool GET /tools/:id(.:format) tools#show
PATCH /tools/:id(.:format) tools#update
PUT /tools/:id(.:format) tools#update
DELETE /tools/:id(.:format) tools#destroy
This is my tools controller:
class ToolsController < ApplicationController
before_action :set_tool, only:[:show, :edit, :update, :destroy]
before_action :authenticate_user!, only:[:new, :destroy, :edit], notice: 'you must be logged in to proceed'
def index
#tools = Tool.all
end
def show
end
def new
#user = current_user
#tool = #user.tools.build
end
def create
#tool = Tool.new(tool_params)
#tool.save
redirect_to #tool
end
def edit
end
def update
#tool.update(tool_params)
redirect_to #tool
end
def destroy
#tool.destroy
redirect_to tools_path
end
private
def set_tool
#tool = Tool.find(params[:id])
end
def tool_params
params.require(:tool).permit(:name, :description)
end
end
These are my models:
class Tool < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :tools
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Unfortunately at this point when I navigate to users/id/tools all the tools in the database are listed instead of only the tools for that particular user. Also when I look at the active record instances of each tool in my database the user_id column is nil
However I am stuck here. Obviously the code will be different for each index so I can't use the same index action for both situations or the same index.html.erb view page either.
I am wondering wheat the next step would be?
Here are a few things I am thinking I could do:
1) create a new action in my tools controller something like user_index and include the user & tool logic to fetch the tools associated to a particular user. I would also have to create a new user_index.html.erb view with the view code. Then I would delete the nested resource and add a route like: match 'users/:id/tools' => 'tools#user_index', :via => get
2) I can delete the stand alone resources :tools route and the add a get :user_index, :on => :collection in my nested tool resource. Then add a user_index action to my controller like in solution #1. The only problem here is that then all my routes would have the user/:id prefix which I do not want.
What is the best solution in this case? Also, why are my active record tool instances not saving the id of the user that created them? Is there a way to get them to save the user id without nesting the resources?
What is the rails way for this?
To only show the tools of a particular user, instead of doing:
#tools = Tool.all
You can make an instance variable that is an array of Tools that are assigned to a particular user. For example:
#user = User.find(params[:id])
#tools = Tool.where(user_id: #user.id)
This will only collect the tools where the tools user_id matches the user ID of the user loaded into the show view.
Then when you do your loop, it will show the right tools for that user.
With the answer above you can use:
#tools = (#user.present?) ? #user.tools : Tool.all
To be able to set the user of each tool you have to edit your:``
params.require(:tool).permit(:name, :description)
To include user
params.require(:tool).permit(:name, :description, :user)

Ruby Rails Path Show All Item by User

A RoR beginner here. I am trying to implement a page 'My Products' to show all products added by current user. Currently I have set my 'All Products' page as my index root "products#index". My Product has Controller but my User does not not Controller because I am using Devise. I have a few questions which I still couldnt get it right.
Because currently
Product
belongs_to :user
User
has_many :products
routes
devise_for :users
resources :products
rake routes I have
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
user_registration POST /users(.:format) devise/registrations#create
new_user_registration GET /users/sign_up(.:format) devise/registrations#new edit_user_registration GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
products GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:id/edit(.:format) products#edit
product GET /products/:id(.:format) products#show
PATCH /products/:id(.:format) products#update
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy
Currently what I have in mind to achieve this:
Create a UserController to have #user = User.all then because with association I can use #user.product. (I saw some people said that I shouldn't create new controller because of Devise?) However, I tried to test with rails console before doing the implementation.
product = Product.first
product.user #here I get all details about user
user = User.first
user.product #here I get error. Why it works for product to find user but not both ways?
Next, this then makes me wonder how do I create configure the route to get path /users/:id/products . Should I use a nested resource?
Next question, I tried to have
resources :users do
resources :products
end
resources :products
I typed in rake routes again. I am confused
user_products GET /users/:user_id/products(.:format) products#index
products GET /products(.:format) products#index
Question:
Can 2 path has the same Controller#Action?
user_products_path and products_path are 2 different path where user_products_path represents user's product. and products_path represents all products
Sorry for the long post.I really wish to clarify those things. Thanks a lot if you could help!! :)
user.product #here I get error. Why it works for product to find user but not both ways?
As User has_many :products, you need to use correct association name as:
user.products # it will give you all products of an user
Can 2 path has the same Controller#Action?
In short, YES. You can specify controller and action name explicitly in your route.rb like:
get 'users/:id/products' => 'products#index', :as => :user_products_path
Note that in your case, it will be going into products#index by default also.
user_products_path and products_path are 2 different path where user_products_path represents user's product. and products_path represents all products
Correct, it's absolutely fine. As you are using devise, you don't need to use id parameter coming from the URL i.e. users/:id/products. You can get the user directly from current_user, which is better in terms of security also. Keep in mind that if you have admin role who can see details of every user then you will need to manage id in that case.
Because you're just starting out, I'll keep this example simple with having easy to read logic. However, there are better ways to configure and optimize this so that you're not relying on if statements in your controller.
class ProductsController < ApplicationController
def index
if params[:user_id]
#user = User.find(params[:user_id])
#products = #user.products.all
else
#products = Product.all
end
end
end
One reason why this is bad practice is that you're relying on the user_id param to be valid. If the user_id param is not valid, then the second line #products = #user.products.all will return undefined method for Nil class.
Also, in your views, if you reference #user then you will get an error if you're just listing out all products.
Also, there isn't any security being done where anyone can see anyone's products if they know or try to guess the user's id.
However, this should work in your instance. You may also want to consider that if the user_id is present to then call current_user.products.all so that it will only return the current user's products instead of the particular user_id's. However, it is really up to how you're designing the application that will determine the best route to take.
What I'll typically do is if the /products route should be for the administrative level, I'll namespace it and put the appropriate security around the namespacing so that it does not allow general users to access it, but rather only administrators of the site.

Devise with Rails 4: user show route doesn't exist

I am using the devise gem to handle all the sign up and sign in stuff. But I also want to add user profiles to my application, so I generated a user controller with only a show action. Then I added get 'users/:id' => 'users#show' to routes.rb. In fact, typing /users/1 works, but I can't find a way to name the route. What I want is to get something like show_user_path or user_path so I can link to a given user's content and show that user's profile.
Here is my routes.rb
Pinteresting::Application.routes.draw do
resources :pins
get 'users/:id' => 'users#show'
devise_for :users
root "pins#index"
get "about" => "pages#about"
And here are the routes I get with it (I highlighted the one I expect to be something like show_user_path):
pins_path GET /pins(.:format) pins#index
POST /pins(.:format) pins#create
new_pin_path GET /pins/new(.:format) pins#new
edit_pin_path GET /pins/:id/edit(.:format) pins#edit
pin_path GET /pins/:id(.:format) pins#show
PATCH /pins/:id(.:format) pins#update
PUT /pins/:id(.:format) pins#update
DELETE /pins/:id(.:format) pins#destroy
#this is the one I want a path! GET /users/:id(.:format) users#show
new_user_session_path GET /users/sign_in(.:format) devise/sessions#new
user_session_path POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session_path DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password_path POST /users/password(.:format) devise/passwords#create
new_user_password_path GET /users/password/new(.:format) devise/passwords#new
edit_user_password_path GET /users/password/edit(.:format) devise/passwords#edit
PATCH /users/password(.:format) devise/passwords#update
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration_path GET /users/cancel(.:format) devise/registrations#cancel
user_registration_path POST /users(.:format) devise/registrations#create
new_user_registration_path GET /users/sign_up(.:format) devise/registrations#new
edit_user_registration_path GET /users/edit(.:format) devise/registrations#edit
PATCH /users(.:format) devise/registrations#update
PUT /users(.:format) devise/registrations#update
DELETE /users(.:format) devise/registrations#destroy
root_path GET / pins#index
about_path GET /about(.:format) pages#about
For devise, User is not the resource, it's just a scope. What devise cares about is authentication.
Although the paths are nested under /user, you will notice that the resources that are defined are actually things like sessions, registrations, passwords...
Just add resources :users in your routes and create a UsersController (and the views).
If you don't want to create all the resources for users and just be able to user user_path(user) with your get 'users/:id, you can name that route using the as option, like this:
get 'users/:id' => 'users#show', as: user
The answer above is great but I think it's worth noting here that if you don't want to create a different controller, but want to add an action to, say, your registrations controller that you inherit from the Devise::RegistrationsController, then you need to use the devise scope block:
devise_scope :user do
get 'users/:id' => 'registrations#show', as: user
end
the answer supposed to be like this:
get 'user/:id' => 'users#show', as: :user

devise redirect on login error: ActiveRecord::RecordNotFound in DocumentsController#show

I 'm trying to redirect to a specific page after sign_in & sign_up. I have two models users & resources. After sign_in I want to show list of documents that belong to the user.
If there are no documents then it should redirect to users/:id/document#create otherwise users/:id/document#index.
Any suggestions how do i do that?
I get the following error for the redirect path defined in my controller.
ActiveRecord::RecordNotFound in DocumentsController#show
Couldn't find Document without an ID
Application_controller.rb
def after_sign_in_path_for(user)
user_documents_url(user)
end
Routes.rb
root :to => 'home#index'
devise_for :users
resources :users do
resources :documents
end
devise_for :users do get '/users/sign_out' => 'devise/sessions#destroy' end
Routes
root / home#index
new_user_session GET /login(.:format) devise/sessions#new
user_session POST /login(.:format) devise/sessions#create
destroy_user_session DELETE /logout(.:format) devise/sessions#destroy
user_password POST /password(.:format) devise/passwords#create
new_user_password GET /password/new(.:format) devise/passwords#new
edit_user_password GET /password/edit(.:format) devise/passwords#edit
PUT /password(.:format) devise/passwords#update
cancel_user_registration GET /cancel(.:format) devise/registrations#cancel
user_registration POST / devise/registrations#create
new_user_registration GET /sign_up(.:format) devise/registrations#new
edit_user_registration GET /edit(.:format) devise/registrations#edit
PUT / devise/registrations#update
DELETE / devise/registrations#destroy
user_confirmation POST /confirmation(.:format) devise/confirmations#create
new_user_confirmation GET /confirmation/new(.:format) devise/confirmations#new
GET /confirmation(.:format) devise/confirmations#show
user_documents POST /users/:user_id/documents(.:format) documents#create
new_user_documents GET /users/:user_id/documents/new(.:format) documents#new
edit_user_documents GET /users/:user_id/documents/edit(.:format) documents#edit
GET /users/:user_id/documents(.:format) documents#show
PUT /users/:user_id/documents(.:format) documents#update
/user/:user_id/documents(.:format) user/documents#index
Thanks
The code itself has no problem as I see. But you need to build some "documents" data before this test, either by FactoryGirl or stubs.
Because you really don't have "documents" data for any users, of course Rails gave you to RecordNotFound error.
use this method according to following code
def after_sign_in_path_for(resource_or_scope)
// redirect path
end
i hope this will help
I fixed my problem by following this question.Following is my routes.rb
resources :users do
resources :documents, only: [:index]
end
resource :documents, except: [:index]
this gives me document#index path as well as document#new path.

Resources