3

I am trying to learn how to think the way rails expects. It has been a 4+ year struggle and I'm still not there.

I've asked variations on this question so many times now and I still can't decipher a principle I can use to think for myself when it comes to writing paths.

I have models for user and setting. The associations are:

User

has_one :setting, dependent: :destroy

Setting

belongs_to :user

My routes are:

resources :users, shallow: true do
    scope module: :users do
      resources :settings 
    end

My Settings controller and views are nested inside a folder called 'users'.

I am trying to add a link to my nav bar that links to my setting show page.

I have tried 20+ different variations, the significant majority of them are guesses. Nothing I think should work does.

When I rake routes, I can see:

users/settings#show  PATCH    /settings/:id(.:format) 

I understand this to mean that I should be able to write:

 users_settings_path(@current_user.settings)

I can't.

I have tried:

<%= link_to "Settings", [@current_user, settings_path] %>

I have also tried each of these:

users_settings_path(@current_user.setting)
users_settings_path(@settings)
users_settings_path(setting_url)
users_settings_path(setting_id)
users_setting_path [@current_user, setting_path] 
[@current_user, setting]
[@current_user, settings] 
[@current_user.settings, settings] 
[@current_user.setting, setting]
[@current_user.settings, settings]

In each case, I get an error that says:

undefined method `setting' for nil:NilClass

I think this error message means that the user does not have a setting. However, that error message doesnt make any sense because I have added a line to my users registration controller that says:

class Users::RegistrationsController < Devise::RegistrationsController

  def create
    super do |user|
      if user.persisted?
        User::CompleteRegistrationService.call(user: user)
      end
    end
  end

I then have a service class that has:

class User::CompleteRegistration < ActiveRecord::Base

    def self.call(user: u)
      new(user: user).call
    end

    def initialize(user: u)
      self.user = user
    end

    def call
      Setting::SetupService.call(user: user)
    end


    private

    attr_accessor :user
end

Then I have:

class Setting::SetupService < ActiveRecord::Base

    def self.call(user: u)
      new(user: user).call
    end

    def initialize(user: u)
      self.user = user
    end

    def call
      setting = Setting.create!(user: user)
      # Dashboard.create(profile: profile)
    end

    private

    attr_accessor :user
end

So, I expect that when I create a user, this service class operates to create a setting.

I can't figure out whether I'm writing the link in the nav bar incorrectly (I have tried at least 30 variations on my best guess - so Im not hopeful that I haven't stumbled across the correct formation), or my service class doesnt work to create a setting when a user is created.

Can anyone see where I'm going awry?

I can see in my console that I have a user, but I don't seem to have any Setting instances:

Setting.first
  Setting Load (5.2ms)  SELECT  "settings".* FROM "settings" ORDER BY "settings"."id" ASC LIMIT $1  [["LIMIT", 1]]
 => nil 

My logs show an error with the service class method that is in my registrations controller.

The log says:

NameError - uninitialized constant User::CompleteRegistrationService:
  app/controllers/users/registrations_controller.rb:9:in `block in create'
  devise (4.2.0) app/controllers/devise/registrations_controller.rb:18:in `create'
  app/controllers/users/registrations_controller.rb:7:in `create'

The problem is that I don't understand how to make sense of the logs. Uninitialised Constant means that a User has not been initialised. That can't be true because the user has persisted to the database (so the error message doesnt make any sense).

Can anyone see where I'm getting lost?

I tried renaming the User::CompleteRegistration to Users::CompleteRegistrations (and making all references to 'User' become 'Users' in the service class and the registration controller- but I get the same error message in the logs.

Mel
  • 2,481
  • 26
  • 113
  • 273
  • You are calling `User::CompleteRegistrationService` but your class's name is `User::CompleteRegistration` - this is why you are getting a NameError. Changing the definition to `class User::CompleteRegistrationService < ActiveRecord::Base` and renaming the file to something like user/complete_registration_service.rb should to the trick. – Adam Cooper Feb 06 '17 at 18:01

0 Answers0