0

From the show.html.erb page I want to create a copy of the record on that page and be sent to the new.html.erb page. Rails dup method does that (and doesn't have and id or creation date), but I can't figure out how to get there.

The error I'm currently getting is this: Couldn't find Street with 'id'= pointing at the @street = Street.find(params[:id]).dup line in the streets_controller.rb. (This page has been updated with fixes to some of the problems I had. Thank you commenters.)

Part of my show.edit.erb page:

<p>
  <strong>Previous Street Name:</strong>
  <%= @street.previous_name %>
</p>

<p>
  <strong>&lsquo;Current/Next&rsquo; Street Name:</strong>
  <%= @street.current_name %>
</p>

<p>
  <strong>Earliest Date for &lsquo;Previous&rsquo; Name:</strong>
  <%= @street.date_earliest %>
</p>

<p>
  <strong>Latest Date for &lsquo;Previous&rsquo; Name:&nbsp;&nbsp;</strong>
  <%= @street.date_latest %>
</p>

<p>
  <strong>Entry covers from cross street to cross street or similar:</strong>
  <%= @street.cross_streets %>
</p>
<p>
  <strong>Approximate Number of Blocks:</strong>
  <%= @street.number_of_blocks %>
</p>

<p>
  <strong>Length of segment:</strong>
  <%= @street.extent_length.round(2) %> miles
</p>

And then some buttons on the same page:

<button type="button" class="btn btn-outline-primary" >
  <%= link_to 'Edit', edit_street_path(@street) %>
</button>

<button type="button" class="btn btn-outline-primary" >
  <%= link_to 'New Historic Street Entry', new_street_path %>
</button>

<%= link_to 'Duplicate This Entry', dup_street_path, :action => "dup", :id => @street.id, class: "btn btn-outline-primary" %> 

The last button is my first stab at getting the dup done. The problem is now in passing the id.

And in the streets_controller.rb

def dup
  @street = Street.find(params[:id]).dup
  render :new
end

I finally got the route working: get 'dup_street', to: 'streets#dup'

And for completeness: new.html.erb

<p id="notice"><%= notice %></p>
<% provide(:title, 'New Historic Street Name') %>

<%= render 'form_edit', street: @street %>

<br/>
<div class="btn btn-primary active">
  <%= link_to 'To List of Streets', streets_path %>
</div>

<%= link_to 'Duplicate This Entry', dup_street_path, :action => "dup", :id => @street.id, class: "btn btn-outline-primary" %> 

_form_edit.html.erb is:

<div class="container-fluid">
  <p>This is for a street name from Previous Name/Earliest Date to Current Name/Latest Date</p>
    <div class="row"> <!-- Setting up to have two columns -->
       <div class="col-4"> <!--Left hand column. -->
        <%= form_with(model: street, local: true) do |form| %>
          <% if street.errors.any? %>
            <div id="error_explanation">
              <h2><%= pluralize(street.errors.count, "error") %> prohibited this street from being saved:</h2>
              <ul>
              <% street.errors.full_messages.each do |message| %>
                <li><%= message %></li>
              <% end %>
              </ul>
            </div>
          <% end %>

          <div class="form-inputs">
            <div class="field">
              <%= form.label "City" %>
              <%= form.text_field :city, id: :street_city %>
            </div>

            <div class="field">
              <%= form.label "Previous Name" %>
              <%= form.text_field :previous_name, id: :street_previous_name %>
            </div>

            <div class="field">
              <%= form.label "Current Street Name" %>
              <%= form.text_field :current_name, id: :street_current_name, placeholder: "Name at end of period (Latest confirmed date)", :size=>"95%" %> 
            </div>

            <div class="row">
              <div class="col-lg-12 text-center font-bold">For Previous Street Name</div>
              <div class="field col-lg-6">
                <%= form.label "Earliest Confirmed Date" %>
                <%= form.text_field :date_earliest, id: :street_date_earliest %>
              </div>

              <div class="field col">
                <%= form.label "Latest Confirmed Date" %>
                <%= form.text_field :date_latest, id: :street_date_latest %>
              </div>
            </div>

              <div class="field">
                <%= form.label "Entry covers from cross street to cross street or similar" %>
                <%= form.text_area :cross_streets, id: :street_cross_streets, :maxlength=>"100%" %>
              </div>

            <div class="row">
              <div class="col-lg-12 text-center font-bold">Extent of This Item</div>
              <div class="field col-lg-6">
                <%= form.label "Approximate Number of Blocks" %>
                <%= form.text_field :number_of_blocks, id: :street_number_of_blocks %>
              </div>

              <div class="field col">
                <%= form.label "Length of segment, miles" %>
                <%= form.text_field :extent_length, id: :street_extent_length %>
              </div>
            </div>

            <div class="field">
              <%= form.label "Reference 1" %>
              <%= form.text_area :ref1, id: :street_ref1, :maxlength=>"95%" %>
            </div>

            <div class="field">
              <%= form.label "Reference 2" %>
              <%= form.text_area :ref2, id: :street_ref2 %>
            </div>

            <div class="field">
              <%= form.label "Reference 3" %>
              <%= form.text_area :ref3, id: :street_ref3 %>
            </div>

            <div class="field">
              <%= form.label :notes %>
              <%= form.text_area :notes, id: :street_notes %>
            </div>

            <div class="field">
              <%= form.label "Extent as JSON [lng lat]" %>
              <%= form.text_field :extent_json, id: :street_extent_json, placeholder: "Will be automagically filled in when line is drawn!" %>
            </div>
            <% if @street.extent_array? %>
              <div class="field">
                <%= form.label "Extend as string (array lat lng)This column is replaced by the one above and will be removed." %>
                <%= form.text_area :extent_array, id: :street_extent_array, placeholder: "Not currently being used except for pre-existing entries." %>
              </div>
             <% end %>
            <div class="actions">
              <%= form.submit "Create/Update Historical Street", class: "btn btn-primary" %>
            </div>
          </div> <!-- end form-inputs -->
        <% end %> <!-- End of form -->
       </div> <!-- end col-4, the left hand column -->

       <!-- The next two columns -->
       <%= render 'map_and_control_and_draw' %> <!-- middle column with map -->
       <%= render 'overlaymap_selector' %>   <!-- the third column for selector basemap -->

  </div> <!-- end row -->

</div>  <!-- end container-fluid -->

Seems like this would be a common request, but searching here and elsewhere and looking in my several Rails books; I only find things about Rails 2 or 3, and they don't go quite for enough for me to understand how to make that work in Rails 5. To reiterate the current error is: Couldn't find Street with 'id'= and the following from better_errors:

Request info
Request parameters: {"controller"=>"streets", "action"=>"dup"}
Rack session: (object too large. Modify ActionDispatch::Request::Session#inspect or increase BetterErrors.maximum_variable_inspect_size)
Local Variables: <blank>
Instance Variables:
@_action_has_layout: true
@_routes: nil
@_request: (object too large. Modify ActionDispatch::Request#inspect or increase BetterErrors.maximum_variable_inspect_size)
@_response: (object too large. Modify ActionDispatch::Response#inspect or increase BetterErrors.maximum_variable_inspect_size)
@_lookup_context: #<ActionView::LookupContext:0x00007fc0be919408 @details_key=nil, @cache=true, @prefixes=["streets", "application"], @rendered_format=nil, @details={:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}, @view_paths=#<ActionView::PathSet:0x00007fc0be919318 @paths=[#<ActionView::OptimizedFileSystemResolver:0x00007fc0bb607358 @pattern=":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}", @cache=#<ActionView::Resolver::Cache:0x7fc0bb607330 keys=10 queries=0>, @path="/Users/gscar/Documents/Croatian Restaurants Project-CroRes/LA Historical Street Names/la_hist_street/app/views">]>>
@_action_name: "dup"
@_response_body: nil
@marked_for_same_origin_verification: true
@_config: {}
@current_user: #<User id: 4, name: "Example User", email: "example@railstutorial.org", created_at: "2017-06-09 23:06:24", updated_at: "2017-06-09 23:06:24", password_digest: <bunch of numbers>", remember_digest: nil, admin: true, activation_digest: "$2a$10...", activated: true, activated_at: "2017-06-09 23:06:24", reset_digest: nil, reset_sent_at: nil>
@_params: <ActionController::Parameters {"controller"=>"streets", "action"=>"dup"} permitted: false>
Greg
  • 2,359
  • 5
  • 22
  • 35
  • 1
    Add `render :new` at the end of `dup` function. – Mahmoud Sayed Jan 15 '18 at 16:49
  • @Mahmoud Sayed Thank you. I updated as you suggested and updated the code to one button to make commenting easier. But I end up with a blank `new` page. – Greg Jan 15 '18 at 17:02
  • Can you add the new page source code ? – Mahmoud Sayed Jan 15 '18 at 17:04
  • check that the route generated from link_to helper to the dup page is correct. Post it in your answer. I think that the path is wrong – Pranav Singhal Jan 15 '18 at 18:36
  • @Pravav Singhal. You were right, my routes were wrong. I've updated and am now getting to the dup method, but am getting a new error: `Couldn't find Street with 'id'=`. I guess no `id` is being passed. It seems that the request goes to routes first and then to the dup method. – Greg Jan 15 '18 at 20:13

2 Answers2

2

There are no street_params at the time you're calling dup

Try this

def dup
  @street = Street.find(params[:id]).dup
  render :new
end
SteveTurczyn
  • 36,057
  • 6
  • 41
  • 53
  • SteveTurczyn. Thank you but it didn't help. I'll update my code to show that though since it seems like a step in the right direction. @Sayed. I added the code. – Greg Jan 15 '18 at 17:22
  • @Gerg also change `<%= link_to 'Duplicate This Entry', new_street_path, :action => "dup", :id => @street.id %>` to `<%= link_to 'Duplicate This Entry',controller: 'streets', :action => "dup", :id => @street.id %>` and don't forget to add this action in your routes. – Mahmoud Sayed Jan 15 '18 at 18:52
  • @Mahmoud Sayed the `controller: 'streets'` caused other problems, although I had since changed the routes which may have done the same thing. But I also found this `@_params "streets", "action"=>"dup"} permitted: false>` in my error messages. – Greg Jan 15 '18 at 20:47
  • So what exactly *is* the error message you're getting? – SteveTurczyn Jan 15 '18 at 21:05
  • The error is occurring on this line: ` @street = Street.find(params[:id]).dup` and the error is: `ActiveRecord::RecordNotFound at /dup_street Couldn't find Street with 'id'=1` and then in another part of the debugging `Request info Request parameters {"controller"=>"streets", "action"=>"dup"} Rack session (object too large. Modify ActionDispatch::Request::Session#inspect or increase BetterErrors.maximum_variable_inspect_size)` – Greg Jan 15 '18 at 21:53
  • I put the full `gem better_errors` message at the bottom of the original post. – Greg Jan 15 '18 at 22:00
  • I hard wired the controller like so: `@street = Street.find('610').dup` and it worked. I also had to stop another part of the page from rendering. But if the `id` can be passed we'll be almost there. Just to be clear, the new item had an id of 671 (which is the end of the database) and the information was duplicated. This `@street = Street.find(params['621']).dup` gives an `Couldn't find Street with 'id'=` error. – Greg Jan 15 '18 at 22:59
  • I think this is not clear. The `params[:id]` should contain the id of the old (being duplicated) record. At the point you're rendering new there is no id yet for the new record. When you show the old record, what's the URI? It presumably contains the id of the old record, that's what should be passed to the Street.find method. – SteveTurczyn Jan 16 '18 at 08:13
0

Once I knew how to express what I was looking for I found Rails - passing parameters in link_to which lead to final link_to:

<%= link_to 'Duplicate This Entry', dup_street_path(id: @street.id), action: "dup", class: "btn btn-outline-primary" %>

But @Steve Turczyn for @street = Street.find(params[:id]).dupand @Mahmoud Sayed for render :new provided the pieces to get me there. Thanks all.

Greg
  • 2,359
  • 5
  • 22
  • 35