Mel Mel - 1 month ago 8
Ruby Question

Rails 5 - Namespaced folders

I am trying (and not getting very far) to understand how to use namespaced folders in my Rails 5 app.

I have tables in my schema for users, identities and settings.

The associations are:

User

has_many :identities, dependent: :destroy
has_one :setting, dependent: :destroy


Setting

belongs_to :user


Identity

belongs_to :user


I have organised my controller folders so that I have app/controllers/users/identities_controller.rb and app/controllers/users/settings_controller.rb

Each of those controllers has this first line:

class Users::SettingsController < ApplicationController
class Users::IdentitiesController < ApplicationController


I have organised my views folders in a similar way.

I have app/views/users/settings/show.

I don't have views for identities, except for a partial called _authentications.html.erb. Currently that is stored in the app/views/users folder. I'm trying to move it to the app/views/users/settings folder and render it from the app/views/users/settings/show page.

In my routes file I have:

resources :users, shallow: true do
scope module: :users do
resources :assign_roles
resources :identities
resources :profiles
resources :settings
end


When I render the authentications partial from the app/views/users show page, I have no errors. Everything works. I am getting stuck because there is something that Im not understanding & I don't know what it is.

I'm trying to move the authentications partial to app/views/users/settings so that I can render it from app/views/users/settings/show.

When I try to do that, I get an error that says:

undefined method `identities' for nil:NilClass


That error references this block of my authentications partial:

<% if @user.identities.map(&:provider).include?('linkedin') %>
<span class="glyphicon glyphicon-ok"></span>
<% else %>
<%= link_to 'Connect your Linkedin account', user_linkedin_omniauth_authorize_path %>
<% end %>


I don't understand whether I'm supposed to try to add settings in that if statement somehow? I tried if @setting.user.identities (only as a guess), but it didn't work.

Can anyone see what I'm doing wrong? I can't seem to find a plain english explanation of how to get started with nesting and namespacing.

Add settings controller

class Users::SettingsController < ApplicationController
before_action :set_setting, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
after_action :verify_authorized

def index
@settings = Setting.all
authorize @settings
end

def show
# authorize @setting
end


def new
@setting = Setting.new
authorize @setting

end

def edit
end

def create
@setting = Setting.new(setting_params)
authorize @setting

respond_to do |format|
if @setting.save
format.html { redirect_to @setting }
format.json { render :show, status: :created, location: @setting }
else
format.html { render :new }
format.json { render json: @setting.errors, status: :unprocessable_entity }
end
end
end

def update
respond_to do |format|
if @setting.update(setting_params)
format.html { redirect_to @setting }
format.json { render :show, status: :ok, location: @setting }
else
format.html { render :edit }
format.json { render json: @setting.errors, status: :unprocessable_entity }
end
end
end

def destroy
@setting.destroy
respond_to do |format|
format.html { redirect_to settings_url }
format.json { head :no_content }
end
end


private
# Use callbacks to share common setup or constraints between actions.
def set_setting
@setting = Setting.find(params[:id])
authorize @setting
end

# Never trust parameters from the scary internet, only allow the white list through.
def setting_params
params.require(:setting).permit( :newsletter )
end

end

Answer

There's no @user variable being set in your show action, which is why you're getting that NoMethodError undefined method 'identities' for nil:NilClass error. @user returns nil in your partial. You can either set this in the controller with @user = current_user (assuming you are using devise) or replace @user with current_user in your partial.

Having said all of that - is there any particular reason that you want to namespace all of your controllers like this? Just because you have set up a has_many or has_one relationship between your models doesn't necessarily mean that you have to namespace your controllers as well. If you have a good reason to do it then fine; if not then you could consider moving the controllers out of the users namespace.

Comments