Shady
Shady

Reputation: 804

Identifying objects in Rails - Sometimes with :id and sometimes with the object itself?

another pretty general question about Ruby on rails:

def destroy
    @post = Post.find(params[:post_id])
    @comment = @post.comments.find(params[:id])
    @comment.destroy
    redirect_to post_path(@post)
  end

Looking at the find method, I call it with the parameter id (which is incoming through the REST request, I guess)

Now here

<%= link_to 'Destroy Comment', [comment.post, comment],
                method: :delete,
                data:{confirm: 'Are you sure?' } %>

I assemble the route with the id of both comment.post + comment. To me it seems like the comment.post.id and comment.id are given implicitly (magic^^), which is fine for me, but I tried to code it, and I get an exception.

Why is it that way? And can somebody guide me to the right part of the documentation where exactly this behavior is described? Im pretty lost with all this smart and automatic stuff ruby does....

Thanks!

Upvotes: 0

Views: 54

Answers (1)

Jon
Jon

Reputation: 10908

You're confusing two very different things.

This is doing a request to ActiveRecord to find an instance of Post with a matching id:

Post.find(id)

This next line is using the built in UrlHelper to construct an HTML link in your view for the given resource:

link_to 'Link Text', resource

In your particular case, you specify the :method as being :delete. Through the configuration in your routes.rb file, rails then maps this DELETE request for a [POST, Comment] nested resource to the posts_comment_path and passes in the post_id for comment.post and the id for comment.

This isn't so magic if you dig through the Rails source code a little. The link_to documentation states that the second argument can accept any valid options accepted by url_for. (click here for link_to docs)

The url_for documentation (available here) says this:

<%= url_for(@workshop) %>
# calls @workshop.to_param which by default returns the id
# => /workshops/5

# to_param can be re-defined in a model to provide different URL names:
# => /workshops/1-workshop-name

So, not so magic really. It's definitely worth spending a little time following the chain of calls that rails makes when you call something like link_to as it demystifies a lot of what you initially see as quite complex.

Upvotes: 1

Related Questions