148

I have a method that needs to loop through a hash and check if each key exists in a model's table, otherwise it will delete the key/value.

For example:

number_hash = { :one => "one", :two => "two" } 

and the Number table only has a :one column so :two will be deleted.

How do I check if a model has an attribute or not?

4 Answers 4

248

For a class

Use Class.column_names.include? attr_name where attr_name is the string name of your attribute.

In this case: Number.column_names.include? 'one'

For an instance

Use record.has_attribute?(:attr_name) or record.has_attribute?('attr_name') (Rails 3.2+) or record.attributes.has_key? attr_name.

In this case: number.has_attribute?(:one) or number.has_attribute?('one') or number.attributes.has_key? 'one'

Sign up to request clarification or add additional context in comments.

7 Comments

For bonus points use Hash#select: number_hash.select { |key, value| Number.column_names.include? key }
In Rails 3.2+, use number.has_attribute? which accepts a Symbol or a String
I believe if an object delegates a method to another object, this method will erroneously suggest the column exists. I was checking my models for ones that had a user, but had to instead look for user_id since some models delegated user.
How about using attribute_method? for a class: Number.attribute_method? 'one'
You can simply add record.try(:column_name) it will return then nil if column not exists
|
15

If you need to check for aliases as well, you can use Number.method_defined? attr_name or number.class.method_defined? attr_name.

I had to do this for a Mongoid object that had aliased fields.

1 Comment

I found ModelName.attribute_method? :attr_name was what worked in my instance
10

In your instance object, you could use also defined? instance.attribute or instance.respond_to? :attribute.
These are more generic solution to check a model attribute or any method as well.

1 Comment

Please keep in mind: instance.respond_to?(:attribute) == false ; instance.attribute ; instance.respond_to?(:attribute) == true
5

if very simplified

for Model columns < attributes < methods

for record columns = attributes < methods

Model.columns <> Model.record.columns/attributes

column

Checking the existence of a column for a model Foo.column_names.include? 'column_name'

Does the column exist for the record? foo.has_attribute?('column_name')

attribute

Checking the existence of a attribute for a model Foo.attribute_method?(:attribute_name)

Does the attribute exist for the record? foo.has_attribute?(:attribute_name)

method

Checking the existence of a method for a class Foo.method_defined?(:method_name)

Does the method exist for the instance? foo.respond_to?(:method_name)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.