1

Some background: I have a Rails 4 model with a decimal column d. When being saved or viewed in the app, the value may need to be converted to or from an integer value, respectively, based on the current user's preference.

It seems most appropriate that the calculations should go in the model, and should have no knowledge of users.

After doing some searching, it seems to me the best way to achieve this is via 2 virtual attributes on the model: one for the current user's preferred format and one for the value, with any calculation applied.

So I have come up with something like this:

attr_accessor :format, :value_converted

def value_converted
  if format.nil?
    format = 'A'
  end
  if format == 'A'
    Converter.new(d).to_i if d
  else
    d if d
  end
end

def value_converted=(value)
  if format.nil?
    format = 'A'
  end
  if format == 'A'
    self.d = Converter.new(value.to_i).to_f
  else
    self.d = value
  end

Forms refer to the value_converted rather than the d, and this works fine for editing, updating and viewing. The problem is the #create action.

I believe the issue is happening because the setter is accessing format, and I can't seem to figure out a way to set format from #create before the setter is called, in other words when new creates the object.

I thought perhaps I could just pass the format along with the other parameters (as in this answer, so I tried merging it in, both within and after the standard strong parameters fare, but with no luck:

Both

@entry = current_user.entries.new(entry_params.merge(format: current_user.format))

and

params.require(:entry).permit(:value_converted, :other_param, ...).merge(format: current_user.format)

do not raise any errors, but are apparently ignored. However simply passing format to new in the console works fine.

So my question: Does anyone have a solution to this problem? Or perhaps a better/more appropriate way of going about it? It seems like it should be something simple.

Thanks for any help

Community
  • 1
  • 1
jrosw
  • 143
  • 1
  • 5

1 Answers1

1

For the moment, I got around this by simply setting the values of format and value_converted again in the controller before saving:

def create
  @entry = current_user.entries.new(entry_params)
  @entry.format = current_user.format
  @entry.value_converted = entry_params[:value_converted]
  if @entry.save
  ...
end

Though this is probably not the most elegant solution (I have no idea whether my implementation is thread-safe) it does seem to work.

jrosw
  • 143
  • 1
  • 5