Use model of diiferent name in a different controller - ruby-on-rails

I have a controller FormsController and a Active Model ApplicationForm. I have made this model by including include ActiveModel::Validations, include ActiveModel::Conversion, extend ActiveModel::Naming. When I'm using #form=ApplicationForm I'm getting NameError uninitialized constant FormsController::ApplicationForm. How do I resolve this issue, I just want to use this Model as class which can provide object to hold form values temporarily for further processing.

Here is how to use it from a directory. Assuming it is in a directory app/forms and you have done correctly added the forms to the autoload paths for rails.
#form = ::Forms::ApplicationForm.new(your_params)
Your module will have to be named like this
module Forms
class ApplicationForm
#your form code
end
end

Related

Retrieve Model type in Rails Helper

Does a helper class in Rails 5 (for example UserHelper) have access to the model type it is related to (User)?
I have some shared logic AddFilter that requires the model type to work propery. I now enforce a method filter_for to specify which model is used:
module AddFilter
def filter_for
raise "filter_for not implemented"
end
#...other code
end
Currently I include that logic in many of my helpers:
module UserHelper
include AddFilter
def filter_for
User
end
end
It is possible to retrieve the model type in the AddFilter directly?
Apparently since helpers are included in controllers, a feature from controllers can be used:
# add_filter.rb
def filter_for
controller_path.classify.constantize
end
This retrieves the controller path, classifies the name, then tries to find the constant specified.
Still feels rather hacky, better solutions appreciated!

Module/Class clash trying to namespace models in Rails

As my app is getting a bit big now, I'm trying to use namespacing to help organise my models a little better.
I've created a app/models/theme.rb file which will act as a gateway to the rest of the theme related models which will go in a theme subdirectory.
# app/models directory
theme.rb
theme/compiler.rb
theme/instance.rb
theme/revision.rb
Where instance.rb will start something like....
class Theme::Instance < ActiveRecord::Base
end
and theme.rb is simply...
class Theme
def initialize(args)
# some stuff here
end
end
But anytime I create a new model using a generator, it tries to overwrite a new theme.rb as per below.
rails g model theme::revision
#new theme.rb
module Theme
def self.table_name_prefix
'theme_'
end
end
I could just get rid of the module and copy the def self.table_name_prefix method to each class but that doesn't seem very DRY. I would like to use the table prefix as it keeps things more obvious in the DB. Is there a 'correct' Rails way of going about this that I've missed?
I guess the easiest way is to define Theme as a module that all classes extends
The Theme::Instance imply that the Instance class is contained in a Theme module.
As an alternative, you can create a ThemeUtils module that contains all common method that is included in each class, like a plugin in /lib

Ruby Wrapper Class results in NameError uninitialized constant

I'm trying to model some UI elements.
I've created a series of classes in /app/models/wrappers/*
For this post i'm going to focus on a class called InputTextVO
I have:
class InputTextVO
...
end
/app/models/wrappers/InputTextVO.rb
When I try and initialize it in my controller I get the following:
NameError in InputsController#index
uninitialized constant InputsController::InputTextVO
#ivo = InputTextVO.new
RubyMine can locate the class and doesn't report any errors in my controller.
You must to add a module if you want to create a subdirectory in the model directory. You can do it like this :
class Wrappers::InputTextVO
...
end
Wrappers::InputTextVO.new #....
It should work.
You can also create a new directory like this app/wrapper.

How does including a module work inside a controller?

If I do:
rails generate scaffold account/user username
I get a controller that looks like this:
class Account::UsersController < ApplicationController
def index
#account_users = Account::User.all
end
...
end
If I include the Account Module, then it looks like all the database calls don't need to be prefixed with "Account::". I.e.
class Account::UsersController < ApplicationController
include Account
def index
#account_users = User.all #this works because I included the Account Module above
end
...
end
Now if I were to move my
controllers/account/users_controller.rb
file to:
controllers/admin/account/users_controller.rb
The file looks like this (note: I also corrected my routes file after this move):
class Admin::Account::UsersController < ApplicationController
include Account
def index
#account_users = User.all #this call does not work now
end
...
end
But I get an error saying "uninitialized constant Admin::Account::UsersController::User"
It looks like rails is trying to make a database call on the "User" model without the "Account::" module in front of it.
So how does including modules in controllers work? Why does this not work when I move my controller into a different file (and leave the model in the same location from the generated scaffold) but it works with the scaffold generated files? How can I fix this issue?
Resolving the name of a module is done relative to the current module. Try and change it to:
include ::Account
or
include ::Admin::Account
(depending on the module in which your User model is defined)
This will tell ruby to look in the global namespace for the module Account
I guess I didn't realize you can just explicitly require the path to the module you would like to include. I learned this after reading up on modules some more...
So adding an explicit call to "require 'account/user'" just outside the controller class makes it so including the module in the controller works.

Auto-create the containing module of a class

In Rails you can create a model under app/foo/bar.rb, with bar.rb containing:
class Foo::Bar
def some_method
puts "I work fine"
end
end
If you try to do this in a pure ruby app you'd get a NameError: uninitialized constant Foo unless you've already initialized a module Foo.
What is Rails doing that allows it to create classes without first initializing their containing module? Is it possible to import this behavior through something like activesupport, or are we left to implement on our own?
Rails modifies the Class class to include a const_missing method which gets called when an undefined class is used. It then loads things to try and load the requested class.
The implementation of this in ActiveSupport is in lib/active_support/dependencies.rb.
actually model class created is extend to < ActiveRecord::Base

Resources