Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Rails: belongs_to association breaks multistep form

I am updating a legacy Rails App from 3.2.5 to Rails 7. In the App I have a multistep form, that follows Railscasts # 217. This means I have an Order model with:

attr_writer :current_step

# Associations
  belongs_to :bill_to_land, class_name: "Land", foreign_key: :bill_to_land_id
  belongs_to :ship_to_land, class_name: "Land", foreign_key: :ship_to_land_id
  belongs_to :order_status
  belongs_to :shipping_service
  has_many :order_items
  has_many :products, through: :order_items

# Validations
  validates_presence_of :shipping_name, :if => lambda { |o| o.current_step == "shipping" }
  validates_presence_of :ship_to_land, if: -> { current_step == "shipping" }
  validates_presence_of :billing_name, :if => lambda { |o| o.current_step == "billing" }
  validates_presence_of :bill_to_land, if: -> { current_step == "billing" }

def current_step
  @current_step || steps.first
end

def steps
  %w[shipping billing confirmation]
end

def next_step
  self.current_step = steps[steps.index(current_step)+1]
end

def previous_step
  self.current_step = steps[steps.index(current_step)-1]
end

def first_step?
  current_step == steps.first
end

def last_step?
  current_step == steps.last
end

def all_valid?
  steps.all? do |step|
    self.current_step = step
    valid?
  end
end

In my Order Controller I have something like:

def new
  session[:order_params] ||= {}
  @order = Order.new(session[:order_params])
  @order.current_step = session[:order_step]
end

def create
  session[:order_params].deep_merge!(params[:order]) if params[:order]
  @order = Order.new(session[:order_params])
  @order.current_step = session[:order_step]
  if @order.valid?
    if params[:back_button]
      @order.previous_step
    elsif @order.last_step?
      @order.save if @order.all_valid?
    else
      @order.next_step
    end
    session[:order_step] = @order.current_step
  end
  if @order.new_record?
    render "new"
  else
    session[:order_step] = session[:order_params] = nil
    flash[:notice] = "Order saved!"
    redirect_to @order
  end
end

with a view such as this:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

<% form_for @order, data: { turbo_confirm: 'Are you sure to order?' } do |f| %>
  <%= f.error_messages %>
  <%= render "#{@order.current_step}_step", :f => f %>
  <p><%= f.submit "Continue", data: { turbo: false } %></p>
  <p><%= f.submit "Back", :name => "back_button" unless @order.first_step?, data: { turbo: false } %></p>
<% end %>

This used to work before upgrading. Now the multistep is broken, because bill_to_land is validated already on the first step. I guess the problem are not the validations per se, but that all belongs_to associations are validated already on the first step of the form. I can get the multistep proceeding by commenting out the if @order.valid? in my controller, but that deactivates all validations.

The only adjustment I had to make to the original code during upgrade was to add data: { turbo: false } to the submit tags in my view.

Does anyone know why this implementation of multistep worked before, why it stopped working and how I should proceed in order to get it working again?

Thank you very much in advance.

>Solution :

Since Rails 5.0 version belongs_to is required by default

You can turn this option off:

# config/application.rb
config.active_record.belongs_to_required_by_default = false

Or add optional: true to your belongs_to associations:

belongs_to :bill_to_land, class_name: "Land", foreign_key: :bill_to_land_id, optional: true
belongs_to :ship_to_land, class_name: "Land", foreign_key: :ship_to_land_id, optional: true
belongs_to :order_status, optional: true
belongs_to :shipping_service, optional: true
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading