Search code examples
mysqlruby-on-rails-4activerecordvirtual-attribute

Rails virtual attribute with ActiveRecord


I have a MySQL database table with the following simplified schema:

create_table "sensors", force: :cascade do |t|
  t.integer  "hex_id",     limit: 8, null: false
end

where hex_id is declared as a BIGINT in MySQL. I would like for the user to type in a hexadecimal value, then convert it to base 10 and save it in hex_id. To accomplish this, I thought I would create a virtual attribute called hex to store a hexadecimal string of characters. My Sensor model looks like this:

class Sensor < ActiveRecord::Base  
  attr_accessor :hex

  validates :hex, presence: true

  before_create :hex_to_bigint
  before_update :hex_to_bigint

  private
  def hex_to_bigint
    self.hex_id = hex.to_s(10)
  end
end

and the controller is using standard rails-generated code:

  def new
    @sensor = Sensor.new
  end

  # POST /sensors
  def create
    @sensor = Sensor.new(sensor_params)

    if @sensor.save
      redirect_to @sensor, notice: 'Sensor was successfully created.'
    else
      render :new
    end
  end

I created a view with a form that uses the hex attribute.

<%= f.label :hex do %>HEX ID:
    <%= f.text_field :hex, required: true, pattern: '^[a-fA-F\d]+$' %>
<% end %>

When I click submit, the params array has the following contents:

{"utf8"=>"✓", "authenticity_token"=>"some_long_token", "sensor"=>{"hex"=>"E000124EB63E0001"}, "commit"=>"Create Sensor"}

My problem is that the attribute hex is always empty, and my validation fails. There are many resources on the web that explain how to use virtual attributes, but very few that explain how to use them in conjunction with ActiveRecord. I have spent hours looking for a way to solve this rather simple problem but have found nothing that works. Any help is appreciated. My ruby version is 2.0.0p481. Thanks!


Solution

  • Please add hex in permitted params. see the code below

    private
    
    # Never trust parameters from the scary internet, only allow the white list through.
    def sensor_params
      params.require(:sensor).permit(:hex_id, :hex)
    end
    

    I hope this will help you