tim_xyz
tim_xyz

Reputation: 13481

Rails: How to pass a url path to a form_for partial in Rails?

I'm trying to pass a url and variable to a form partial in Rails.


Method #1:
This works, but I'd rather not hardcode post_create_path into the form, so that it can be used for #update as well.

new.html.erb

<%= render partial: 'shared/form', locals: { form: @form } %>

_form.html.erb

<%= form_for form, url: post_create_path do |f| %>
...
<% end %>

Method #2:
This does not work.

new.html.erb

<%= render partial: 'shared/form', locals: { form: @form, url: post_create_path } %>

_form.html.erb

<%= form_for form, url: url do |f| %>
...
<% end %>

Error:

undefined local variable or method `url' for #<#:0x007f8d4d831fd0>

What I've also tried:

  1. Just url instead of url:url but getting the same error.
  2. Following this thread: How to pass url to partial/form?

I've been trying to make this work for a couple hours now and feel like I'm running out of options to try. Any help in pointing out what I'm doing wrong would be super appreciated!

Upvotes: 4

Views: 6261

Answers (3)

Promise Preston
Promise Preston

Reputation: 28820

I had the same challenge when working on a Rails application with namespaced routes, but sa77's answer helped me.

Just to add to it.

My routes file is like this:

Rails.application.routes.draw do
  namespace :users do
    resources :students
  end
end

So my new.html.erb was modified like this:

<h1>New User</h1>

<%= form_with(model: @user, url: users_students_path, local: true) do |form| %>
  <%= render partial: 'form', user: @user, locals: { form: form } %>
<% end %>

<%= link_to 'Back', users_students_path %>

And my edit.html.erb was modified like this:

<h1>Editing User</h1>

<%= form_with(model: @user, url: users_student_path(@user), local: true) do |form| %>
  <%= render partial: 'form', user: @user, locals: { form: form } %>
<% end %>

<%= link_to 'Show', users_student_path %> |
<%= link_to 'Back', users_students_path %>

And then my _form.html.erb file was modified like this:

<div class="field">
  <%= form.label :email %>
  <%= form.text_field :email %>
</div>

<div class="field">
  <%= form.label :password %>
  <%= form.text_field :password %>
</div>

<div class="actions">
  <%= form.submit %>
</div>

That's all.

I hope this helps

Upvotes: 0

builder-7000
builder-7000

Reputation: 7627

Use the locals hash as a form_for argument:

# new.html.erb
<%= render partial: 'shared/form', form: @form, locals: { url: post_create_path, method: :post} %>

# edit.html.erb
<%= render partial: 'shared/form', form: @form, locals: { url: post_update_path, method: :put} %>

# _form.html.erb
<%= form_for form, locals do |f| %>
...
<% end %>

locals is just a hash and you can give it any name (like vars). Then use it consistently in the views and the form.

Upvotes: 1

sa77
sa77

Reputation: 3603

you can use different actions by opening form_for on edit and new view templates and then pass the form object to the partial which contains all the fields of the form that are common to both create and update

new.html.erb

<%= form_for @post, :url => { :action => "create" } do |form| %>
  <%= render partial: 'shared/form', locals: { f: form } %>

edit.html.erb

<%= form_for @post, :url => { :action => "update" } do |form| %>
  <%= render partial: 'shared/form', locals: { f: form } %>

shared/_form.html.erb

  <%= f.text_field :title %>
  ...
  <%= f.submit "Save" %>
<% end %>

Upvotes: 10

Related Questions