Search code examples
ruby-on-railsruby-on-rails-3formsactiverecordscaffolding

How does Rails import existing rows when you "Edit" in scaffolding?


That was probably a very badly worded question, but I'm curious how Rails knows to bring in the form data when you click edit. For example, if I scaffolded a model called Post, and typed in a title and content for that Post, later when I edit it, the form is automatically filled in.

I looked at the controller and the form partial, but it doesn't seem like it contains anything to tell it to fill it up with the existing data.

The reason I am asking this is because I want to allow users to "import" other people's posts into their form and edit it. How would I do this?


Solution

  • To answer the first part of your question, start by looking at the link to edit your model - in the index view file (app/views/posts/index.html.erb) it will look like:

    <%= link_to 'Edit', edit_post_path(post) %>
    

    When you open the index page in your browser, this builds a link like:

    http://*servername*/post/*id*/edit
    

    The resource routing knows that this calls the edit action of the post_controller, and that the id value is in the URL.

    Now take a look at the edit action in your post_controller (app/controllers/posts_controller.rb) - it looks like:

    def edit
      @post = Post.find(params[:id])
    end
    

    all this does is use the id value that was passed through the URL to find the Post in the database with that id, and save it in the variable @post. If you look in the code of the edit view file (app/views/posts/edit.html.erb) it mostly just uses the form partial (/app/views/posts/_form.html.erb) and that file contains the code for rendering the actual form you see in the browser.

    <%= form_for(@post) do |f| %>
    

    This line starts building the form using the @post variable that got set in the PostsController edit action. Inside the block for this code, you see things like -

    <div class="field">
      <%= f.label :title %>
      <%= f.text_field :title %>
    </div>
    

    This code builds a text field in the form tied to the :title property of @post - if a value exists in that property, the text_field method knows to populate the text field with that value.

    The second part ('I want to allow users to "import" other people's posts into their form and edit it') is a lot more open-ended and depends more on what you actually want to do in your app - you could just allow all users to see all other users posts and edit them directly (kind of like a wiki, but with destructive edits). Or you could make posts editable only by the user that created them, but viewable by others, and then you could create a controller action that allows a user to copy the contents of another user's post into a new post owned by the current user. Or other things - it really just depends what you want.