1

I have a model with an initializer in it, which basically creates a user from a user hash.

After it gets the user information, it checks whether the "privileges" key in the hash is an array. If it's not, it turns it into an array.

Now the obvious way of doing this would be crafting an entire user_hash so that it would skip those "create user" lines and then check if it turns the input into an array if necessary. However, I was wondering if there is a more DRY way of doing this?

Here is the user model I'm talking about:

def initialize(opts={})
  @first_name = opts[:user_hash][:first]
  @last_name = opts[:user_hash][:last]
  @user_name = opts[:user_hash][:user_name]
  @email = opts[:user_hash][:email]
  @user_id = opts[:user_hash][:id]

  @privileges = {}

  if opts[:privs].present?
    if !opts[:privs].kind_of?(Array)
      opts[:privs] = [opts[:privs]]
    end
  end
end
2
  • Is opts[:privs] used somewhere? Commented Jul 11, 2014 at 11:55
  • yes, I just trimmed the irrelevant code but basically it's used to set the privileges for the user. Commented Jul 11, 2014 at 12:07

3 Answers 3

2

You can pass a double which returns the needed value when the proper key is requested, and itself (or something else) otherwise:

it 'turns privs into an array' do
  opts = double(:opts)
  allow(opts)to receive(:[]).and_return(opts)
  allow(opts)to receive(:[]).with(:privs).and_return('not array')

  expect(MyClass.new(opts).privileges).to eq(['not array'])
end

Btw, your code could be simplified using the splat operator:

privs = [*opts[:privs]]

sample behavior:

privs = nil
[*privs]
# => []

privs = ['my', 'array']
[*privs]
# => ["my", "array"]

privs = 'my array'
[*privs]
# => ["my array"]
Sign up to request clarification or add additional context in comments.

Comments

0

You can even use the idempotent Kernel#Array

def initialize(opts = {})
  @first_name = opts[:user_hash][:first]
  @last_name = opts[:user_hash][:last]
  @user_name = opts[:user_hash][:user_name]
  @email = opts[:user_hash][:email]
  @user_id = opts[:user_hash][:id]
  @privileges = {}

  Array(opts[:privs])
end

I hope that helps

Comments

0

Rather than testing the implementation (value is turned into an array), I would test the desired behavior (takes single privilege or multiple privileges):

describe User do

  describe '#initialize' do

    it "takes single privilege" do
      user = User.new(user_hash: {}, privs: 'foo')
      expect(user.privileges).to eq(['foo'])
    end

    it "takes multiple privileges" do
      user = User.new(user_hash: {}, privs: ['foo', 'bar'])
      expect(user.privileges).to eq(['foo', 'bar'])
    end

  end

end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.