Home > Blockchain >  How can I pass a specific url to simple_form for new and edit actions
How can I pass a specific url to simple_form for new and edit actions

Time:06-09

I'm trying to render a simple form to create and edit a campaign resource. Normally, in a rails application, I would render the form like so:

<%= simple_form_for @campaign do |f| %>
  ....inputs.....
<% end %>

Normally, this would be enough to perform both a new and edit action for the campaign. However in this scenario, I can't use the same approach because the urls for new and edit cannot be inferred. They are two different urls. Here is my code:

New Action

.max-w-4xl.mx-auto
  .mt-5.bg-white.shadow.sm:rounded-lg
    .px-4.py-5.sm:p-6
      %h3.text-lg.leading-6.font-medium.text-gray-900
        New Campaign

      .mt-5
        = render 'form'
Edit Action

.max-w-4xl.mx-auto
  .mt-5.bg-white.shadow.sm:rounded-lg
    .px-4.py-5.sm:p-6
      %h3.text-lg.leading-6.font-medium.text-gray-900
        Editing Campaign: "#{@campaign.name}"

      .mt-5
        = render 'form'

For the new action, I have simple form coded like so:

= simple_form_for(@campaign, as: :campaign, method: :post, url: partner_campaigns_path(@partner)) do |f|

For the edit action I have simple form like this:

= simple_form_for(@campaign, as: :campaign, method: :patch, url: campaign_path(@campaign)) do |f|

I want to keep my _form.html.haml but I can't seem to pass the distinct urls into it. I've tried to pass the url and action as local variables for rendering a partial but they seem to always be blank. Example below:

= render 'form', locals: { url: campaign_path(@campaign), http_action: :patch }

Everytime I do a variation of this approach, I can't get the url or http_action variable. Am I doing something incorrect?

CodePudding user response:

You can use #new_record? or #persisted? methods to achieve this

- http_method = @campaign.new_record? ? :post : :patch
- url = @campaign.new_record? ? partner_campaigns_path(@partner) : campaign_path(@campaign)
= simple_form_for(@campaign, as: :campaign, method: http_method, url: url) do |f|

Or you can incapsulate this logic in a helper method

module ApplicationHelper
  def resolve_form_options(campaign, partner)
    if campaign.new_record?
      { url: partner_campaigns_path(partner), method: :post }
    else
      { url: campaign_path(campaign), method: :patch }
    end
  end
end
= simple_form_for(@campaign, as: :campaign, **resolve_form_options(@campaign, @partner)) do |f|

CodePudding user response:

You can pass a variable from the new and edit pages from where the form partial is being rendered. Something like - <%= render 'form', request_method: 'new' %> if passing from the new view. And then inside the form partial, you can do -

= simple_form_for(@campaign, as: :campaign, method: request_method == 'new' ? :post : :patch, URL: (request_method == 'new' ? partner_campaigns_path(@partner) : campaign_path(@campaign) )) do |f|.

I think this might not be the correct way to do so and might be better ways to do. But if it works, then hey please mark the answer as correct. :)

  • Related