14

I have to connect to an existing database used by our freeradius server. One table has a column called attribute which I'm trying to access.

When accessing, I get his error:

ActiveRecord::DangerousAttributeError 
attribute? is defined by ActiveRecord

I've tried to select and rename this column in my model:

def self.default_scope
    Radcheck.select("attribute as newattribute")
end

But that's not working either.

Can anyone recommend a way around this? I'd really like to rename the column in rails!

Jenny Blunt
  • 1,576
  • 1
  • 18
  • 41

3 Answers3

11

On a similar question I found this answer: https://stackoverflow.com/a/9106597/1266906

Without having to care about which attributes are reserved by ActiveRecord in Rails 3.0 just add

gem 'safe_attributes'

to your Gemfile and the gem will try to take care of all colliding names automatically.

As with the other answer you need to use Radcheck[:attribute] or Radcheck.read_attribute :attribute / Radcheck.write_attribute :attribute, 'value' to access fields with internally reserved names, but the gem ensures validations like validates_presence_of :attribute will work as usual.

Further details are available at https://github.com/bjones/safe_attributes

Community
  • 1
  • 1
TheConstructor
  • 4,285
  • 1
  • 31
  • 52
  • 1
    I came across the same issue with an attribute valid in my legacy database. Using "safe_attributes" did work out of the box. – dhenze Apr 17 '12 at 07:25
  • 2
    Just a note for Googlers: This gem will work for pretty much any reserved word *except* for `attribute`. From the readme: "It is virtually impossible to have a column named 'attribute' in your schema when using ActiveRecord." – Chris Bloom Nov 15 '14 at 00:03
  • If using Hirb also, you might need to disable before trying to render the model columns in the console, with Hirb.disable. – Anatortoise House May 03 '17 at 16:01
2

I have never run into such situation but i think this should work

class Radcheck < ActiveRecord::Base
    default_scope :select=> 'attribute as newattribute'
end

You should use instance method default_scope not class one

Also you have an option to use instance method, like:

RadCheck.read_attribute :attribute

Hope it helps

sarvavijJana
  • 1,212
  • 10
  • 11
  • Thanks - I've tried this and I still get the blasted error. Do I need to alter my controller action as well? Currently I have this: @radcheck = Radcheck.all Thanks – Jenny Blunt Oct 10 '11 at 21:23
-1

Here is a solution that does require a change to the external database, but it is a very minor change, and it will work with any column name even `attribute`. No gem required.

In your external/legacy database create a view that renames the problematic column. e.g.

CREATE VIEW radcheck_view AS (
  SELECT id, username, op, value, attribute rad_attribute 
  FROM radcheck
);  

Here the problem column is being renamed attribute to rad_attribute.

Don't forget to grant appropriate permissions on the view. In my case it is read-only usage:

GRANT SHOW VIEW ON radius.radcheck_view TO <rails_user> IDENTIFIED BY '<password>';

Then, in your rails model use the view as table_name

class RadiusRadcheck < RadiusExternal
    self.table_name = 'radcheck_view'
end  
sheepdog
  • 625
  • 5
  • 19
  • Given that external databases would be owned and managed by a different application, this is quite a dangerous idea, not that it would even work as the external structure should not be editable by the reading application. – shashin May 15 '23 at 23:52