Namespacing issue in rails - ruby-on-rails

I have a class A in module M like below
Module M
class A
def method1
# how to instantiate a model having same name as A
#like A.first
end
end
end
In my models I have a class A
class A < ActiveRecord::Base
end

You can access the global scope using the :: operator, e.g:
Module M
class A
def method1
::A.first
end
end
end

Related

In namespaced api (Api::V1) I can't access serializers

Api::V1 is the namespacing of my schedules#index resource. But the controller won't access the serializer.
module Api
module V1
class ApiController < ApplicationController
include ActionController::Serialization
include Concerns::ErrorHandler
before_action do
namespace_for_serializer = Api::V1
end
end
end
end
module Api
module V1
class SchedulesController < ApiController
def index
#schedules = current_user.schedules
render json: #schedules
end
end
end
end
module Api
module V1
class ScheduleSerializer < ActiveModel::Serializer
attributes :id
end
end
end
I've tried everything. Declare the serializer directly vs each_serializer: ScheduleSerializer which just returns an "uninitialized constant" error.
What am I missing?

Modularize an ActiveRecord class

If I have classes like this,
class A < ActiveRecord::Base
include ExampleModule
end
class B < ActiveRecord::Base
include ExampleModule
end
module ExampleModule
module ClassMethods
...
end
def included(base)
...
end
end
how do I get the a reference to class A or B inside of ExampleModule upon referencing including this module into either one of those classes? I'm asking this question because I wanted to do something like adding has_one :association or after_create :do_something to class A or B via including ExampleModule such as below.
class A < ActiveRecord::Base
include ExampleModule
end
class B < ActiveRecord::Base
include ExampleModule
end
module ExampleModule
has_one :association
after_create :do_something
module ClassMethods
...
end
def included(base)
...
end
end
Is there a better way to do this as well? Thanks!
If you extend ActiveSupport::Concern, you should be able to do it when the module is included:
module ExampleModule
extend ActiveSupport::Concern
def do_something
# ...
end
included do
has_one :association
after_create :do_something
end
end
If what you're wanting to do is call has_one or after_create depending on which class is including the module you can do this
module Extender
def self.included(base)
if base.name == A.name
# do stuff for A
has_one :association
elsif base.name == B.name
# do stuff for B
after_create :do_something
end
end
end

In Module Class method,is that possible to get the Class which mixedin that Module?

I have a Module A, and there are several Class need to Mixin it, there is a method should be wrote as Class Method of that Module, but this method need to get data from the Tables which match these Classes. It that realizable?
module Authenticate
def password=(password)
if password.present?
generate_salt
self.hashed_password = Authenticate.encrypt_password(password, salt)
end
end
class << self
def encrypt_password(password,salt)
Digest::SHA2.hexdigest(password + salt)
end
end
private
def generate_salt
self.salt = self.object_id.to_s + rand.to_s
end
end
require 'authenticate_module'
class Administrator < ActiveRecord::Base
validates :password, :confirmation => true
attr_accessor :password_confirmation
attr_reader :password
include Authenticate
end
This is that method:
def authenticate(name,password)
if user = ???.find_by_name(name)
if user.hashed_password == Authenticate.encrypt_password(password,user.salt)
user
end
end
end
Use ActiveSupport::Concern to add class methods to every class that includes your module, then calling self in that method will return the class name.
It will be something like:
module Authenticate
extend ActiveSupport::Concern
module ClassMethods
def authenticate(name, password)
self.class # returns the name of the class that includes this module
end
end
end
class User
include Authenticate
end
# Now You can call
User.authenticate(name, password)
What ActiveSupport::Concern does is that whenever a class includes the module, it extends that class with the ClassMethods which here is equivalent to doing
class User
include Authenticate
extend Authenticate::ClassMethods
end

Overriding a parent method and making it private/protected

I'm trying to make the create method private/protected for an ActiveRecord model. I want to do something like this:
class Product < ActiveRecord::Base
def self.create(options)
private
super(options)
end
end
so that I am unable to do Product.create(...). However, I need to do this
class Pencil < Product
def self.create(options)
options["category"] = "stationary"
super(options)
end
end
so that I can do this Pencil.create(...). Thanks in advance!
class Product < ActiveRecord::Base
class << self
def create(options)
super(options)
end
private :create
end
end
class Pencil < Product
class << self
def create(options)
options["category"] = "stationary"
super(options)
end
end
end

Rails 3 Including Nested Module Inside Controller

I have a controller that I'd like to include some standard methods.
class Main::UsersController < Main::BaseController
include MyModule::ControllerMethods
end
uninitialized constanct MyModule::ClassMethods::InstanceMethods
My module looks like this, which is also wrong, and was originally meant for a model. What's the best way to do it so that I can use it with a controller as well?
module MyModule
def self.included(base)
base.has_one :example, :autosave => true
base.before_create :make_awesome
base.extend ClassMethods
end
module ClassMethods
...
include InstanceMethods
end
module InstanceMethods
...
end
module ControllerMethods
...
# I want to include these in my controller
def hello; end
def world; end
end
end
Use extend instead of include for your ClassMethods. You should also split your model and controller modules:
module MyModule
module ModelMethods
def acts_as_something
send :has_one, :example, :autosave => true
send :before_create, :make_awesome
send :include, InstanceMethods
end
module InstanceMethods
...
end
end
module ControllerMethods
...
# I want to include these in my controller
def hello; end
def world; end
end
end
ActiveRecord::Base.extend MyModule::ModelMethods
Your Model would then look like this:
class Model < ActiveRecord::Base
acts_as_something
end

Resources