2

Is there a way, via ActiveRecord, to access the "real_field" (let's say)?

For example. If I have a Model Company and do Company.create(name: "My Company Name") (with I18n.locale = :en), that name value won't be saved in the Company record, but in the Mobility table for the string.

So doing Company.last will return

#<Company id: 5, name: nil>

But doing Company.last.name will return My Company Name (assuming the locale is set properly)

Is there a way to do something like Company.last.real_name that would give me the actual value of the record? In this case nil. I would also like to have a real_name=.

mobility (0.4.2) i18n (>= 0.6.10, < 0.10) request_store (~> 1.0)

Backend: key_value

Nick L Scott
  • 712
  • 1
  • 8
  • 21

2 Answers2

2

Try this:

Company.last.read_attribute :name

Or this:

Company.last.name_before_type_cast
mdesantis
  • 8,257
  • 4
  • 31
  • 63
  • 1
    That's perfect. Thanks. Also, if someone comes looking for the same thing, using `write_attribute` and then `.save` will save the field – Nick L Scott Feb 07 '18 at 15:40
  • 2
    You can also use the shorthand `company[:name]` instead of `company.read_attribute :name`, or `company[:name] = ...` instead of `company.write_attribute :name, ...`. – Chris Salzberg Feb 08 '18 at 10:46
  • 1
    You can also pass the `super` option to Mobility, which would normally do the same thing: `company.name(super: true)`. – Chris Salzberg Feb 08 '18 at 10:47
  • Nice points @ChrisSalzberg! They would even deserve another answer IMHO; specially the last one, which seems the most idiomatic using Mobility – mdesantis Feb 08 '18 at 14:24
2

The accepted answer is correct as a general approach with any ActiveRecord model: read_attribute and write_attribute will always fetch and set the column value regardless of any overrides defined in the model. As I commented, there are shorthandes for these methods as well:

company[:name]         #=> returns the value of the name column
company[:name] = "foo" #=> sets the value of the name column to "foo"

In addition, in Mobility specifically, there is an option you can pass to a getter (and setter) which will skip whatever Mobility would normally do for an attribute:

company.name(super: true) # skips Mobility and goes to its parent (super) method,
                          # which would typically be the column value.

In a situation where perhaps you are using another gem which also does something special to attributes, this approach might work better.

There is also a setter option, however it's a bit more tricky to use:

company.send(:name=, "foo", super: true) # sets name to "foo", skipping Mobility

If you are using Mobility together with another gem that overrides attribute getters and/or setters, then the super option may be useful; otherwise read/write attribute is probably fine.

Chris Salzberg
  • 27,099
  • 4
  • 75
  • 82