active-hash / active_hash

A readonly ActiveRecord-esque base class that lets you use a hash, a Yaml file or a custom file as the datasource
MIT License
1.2k stars 179 forks source link

Add a :private field option #200

Closed djberg96 closed 4 years ago

djberg96 commented 4 years ago

The idea here is that data may be coming from an external source, and you don't want it all to be publicly accessible, but you still want it to be accessible internally for other methods. So, for example, you would have something like this:

class Foo < ActiveHash::Base
  field :name
  field :age
  field :stuff, :private => true

  # Let's pretend this array of hashes came from an external source
   self.data = [
     {:name => "Dan", :age => 50, :stuff => "secret"},
     {:name => "Joe", :age => 35, :stuff => "also secret},
  ]

  private

  def some_internal_method
    puts "This is: " + stuff # Want stuff here
  end
end

Foo.first.stuff # should be a NoMethodError

WIP for now until I can figure it a proper implementation, and also see if such a thing is of interest.

Followup to https://github.com/zilkey/active_hash/issues/199

djberg96 commented 4 years ago

@kbrock simplified as per your recommendation, thanks! Also, added specs.

djberg96 commented 4 years ago

@zilkey Ok, should be good to go.

kbrock commented 4 years ago

Is there a way to define a spec for this? It would probably be your test.rb with minimal changes

djberg96 commented 4 years ago

@kbrock I added a spec (though note that I'm also trying to get the specs updated to rspec3 in a separate PR).

kbrock commented 4 years ago

For future readers:

Using ruby private for a getter/setter will hide an attribute from other classes in the way desired.

Thanks @djberg96 for working this one through


    it "honors the private option" do
      Country.data = [{:name => "US", :secret => "xxx"}, {:name => "Canada", :secret => "yyy"}]
      class Country
        private
        def secret ; self[:secret] ; end
      end

      Country.should_not respond_to(:secret)
      Country.first.send(:secret).should eq("xxx")
    end
kbrock commented 3 years ago

@djberg96 I think the already_defined? is much better than the existing solution. think that would be nice in a pr you're probably tired of this feature, so I can cherry-pick those into a separate pr

djberg96 commented 3 years ago

@kbrock I will leave it to you to pick what you want out of that PR. :)