I have done this command: rails g controller father/child and it has genersted this for me:
class Father::ChildController < ApplicationController
end
But my goal is to have this:
module Father
class ChildController < ApplicationController
end
end
Are these two the same? or I should use generate controller in a different way to achive that module like syntax?
They not the same. The second one is equivalent to the following:
class Father::ChildController < Father::ApplicationController
end
Related
I am trying to keep the namespace of a class when including a module.
Lets say I have these Models:
class Shop < ApplicationRecord
self.abstract_class = true
end
class A::Shop < ::Shop
end
class B::Shop < ::Shop
end
And this controller:
module A
class ShopController < AuthenticatedController
include Basic::Features
def test
p Shop.new #YES! its a A::Shop
end
end
end
And this Module:
module Basic
module Features
def test
p Shop.new #Shop (abstract)
end
end
end
In the above example, the namespace is overwritten when including the module.
As I want to use the Basic::Features module at multiple places in my codebase, I would like to automatically switch between A::Shop and B::Shop when including it in the controller.
Anybody any idea if this is possible, and how.
Here is one option:
module Basic
module Features
def test
p Object.const_get('::' + self.class.to_s.split('::').first + '::Shop')
end
end
end
It will not work if you have deeper namespaces, e.g. A::B::Shop, but it could be made to work. Also in rails you could use deconstantize instead of split.
I think the reason you code does not work is because it is looking in A::ShopController namespace and since not found it then tries the root namespace, ::, and finds Shop.
I'm have a Rails project which has an api part and the regular one. They have some common methods, for example, I have two controllers like so:
class PlacementController < ApplicationSafeController
def zip
file = ZipService::ZipGenerator.create_zip
send_data(file.read, type: 'application/zip')
File.delete(file.path)
end
end
and
class Api::ZipsController < ApiController
def single_zip
file = ZipService::ZipGenerator.create_zip
send_data(file.read, type: 'application/zip')
File.delete(file.path)
end
end
And both my ApiController and ApplicationSafeController inherit from ApplicationController. My question is, what is the best way to clean this up without making the root ApplicationController dirty? (by adding a new method there). Thanks!
You a module/concern to share code. Enclose shareable code in a module, then include that module in the required controllers. It's the Ruby way of doing this thing.
module Zippable
def zip
file = ZipService::ZipGenerator.create_zip
send_data(file.read, type: 'application/zip')
File.delete(file.path)
end
end
class PlacementController < ApplicationSafeController
include Zippable
#Example Usage
def show
zip
end
end
class Api::ZipsController < ApiController
include Zippable
end
I have a model called ToolFilter with a column of 'tool_type'. The string here refers to a class for a tool. I put a method in my application_controller called tools_list that gets the descendants of Tool.This works nicely in my frontend, but ToolFilter is complaining about the method tools_list.
class ToolFilter < ActiveRecord::Base
validate :existence_of_tool
def existence_of_tool
unless tools_list.include? tool_type
errors.add(:tool_type, "Invalid tool_type {{tool_type}}, use 'tools_list' to see a list of valid tool_object_types")
end
end
class ApplicationController < ActionController::Base
helper_method :tools_list
def tools_list
Rails.application.eager_load!
Tool.descendants
end
It's a bit strange to tell a model about other classes in the file system, but I need to validate that it is one of these. Should I put tools_list is a module and include it in ToolFilter? Any suggestions?
Write this to include helper in your model
ApplicationController.helpers.tool_list
Though I will not recommend calling helper in model.
And checking tools with classes is damm bad idea.
I ended up creating a module called ToolExtention which has these helper methods in them. I then included this module in my controllers wherever it was needed and moved my logic from the views into the controller which I believe is better practice.
module ToolExtension
def self.tools_list
Rails.application.eager_load!
Tool.descendants
end
...
class ProjectsController < ApplicationController
include ToolExtension
...
ToolExtension.tools_list
I have had multiple projects in where I had to add a controller inside of a module for namespace and different users reasons. After reading this question I had a better understanding of the difference but don't really know which one is best. The thing is that I have always written it like this:
# Version A: app/controllers/example_module/example_controller.rb
module ExampleModule
class ExampleController < ExampleModuleBaseController
end
end
# app/controllers/example_module/example_module_base_controller.rb
class ExampleModule::ExampleModuleBaseController < ApplicationController
end
When you run:
rails g controller ExampleModule/Example
it creates:
# app/controllers/example_module/example_controller.rb
class ExampleModule::ExampleController < ApplicationController
end
After correcting the inheritance it would be:
# Version B: app/controllers/example_module/example_controller.rb
class ExampleModule::ExampleController < ExampleModule::ExampleModuleBaseController
end
Which version is the correct one? Version A or Version B?
In rails i have a lot of tables and need to define a lot of Model classes to use for controller, but i want to put all the model classes into one module file, and then make controller to use the model class in the module, but i don't know how to do it.
Could someone give me help on the problem? Appreciate your help very much.
app/models/widgets/blue_widget.rb
class Widgets::BlueWidget < ActiveRecord::Base
// etc.
end
app/controllers/blue_widget_controller.rb
def index
#widgets = Widgets::BlueWidget.all
end
You can also namespace the controllers.
Edit:
lib/widgets.rb
module Widgets
class BlueWidget
end
class RedWidget
end
end
controller:
require 'lib/widgets'
def index
#widgets = Widgets::BlueWidget.all
end
Is that what you mean?
You can also generate models directly in subdirectorys and get them im modules:
rails g model user/likes name:string like:boolean
and you will get your generated files.
The generated model would be in app/models/user/likes.rb
class User::Likes < ActiveRecord::Base
end