I have an ActiveRecord class called User. I'm trying to create a concern called Restrictable
which takes in some arguments like this:
class User < ActiveRecord::Base
include Restrictable # Would be nice to not need this line
restrictable except: [:id, :name, :email]
end
I want to then provide an instance method called restricted_data
which can perform some operation on those arguments and return some data. Example:
user = User.find(1)
user.restricted_data # Returns all columns except :id, :name, :email
How would I go about doing that?
A Rails Concern is a module that extends the ActiveSupport::Concern module. Concerns allow us to include modules with methods (both instance and class) and constants into a class so that the including class can use them. The code inside the included block is evaluated in the context of the including class.
People use Rails concern for mainly for two things: First, to reduce the size of a model that could be separated into several models, and therefore reducing the size. Second, to avoid declaring the same class over and over again.
ActiveSupport's Concern module allows us to mix in callbacks, class and instance methods, and create associations on target objects. This module has an included method, which takes a block, as well as an append_features method and class_methods block, which you can read about in the source code.
If I understand your question correctly this is about how to write such a concern, and not about the actual return value of restricted_data
. I would implement the concern skeleton as such:
require "active_support/concern"
module Restrictable
extend ActiveSupport::Concern
module ClassMethods
attr_reader :restricted
private
def restrictable(except: []) # Alternatively `options = {}`
@restricted = except # Alternatively `options[:except] || []`
end
end
def restricted_data
"This is forbidden: #{self.class.restricted}"
end
end
Then you can:
class C
include Restrictable
restrictable except: [:this, :that, :the_other]
end
c = C.new
c.restricted_data #=> "This is forbidden: [:this, :that, :the_other]"
That would comply with the interface you designed, but the except
key is a bit strange because it's actually restricting those values instead of allowing them.
I'd suggest starting with this blog post: https://signalvnoise.com/posts/3372-put-chubby-models-on-a-diet-with-concerns Checkout the second example.
Think of concerns as a module you are mixing in. Not too complicated.
module Restrictable
extend ActiveSupport::Concern
module ClassMethods
def restricted_data(user)
# Do your stuff
end
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With