简体   繁体   中英

how to render a partial using link_to with rails 4.2.2

I would like to have my user click a 'Bio' link located in their Profile Page that will display their bio contents pulled from the database. For this I have created a partial lovelies/_bio.html.erb because i would like to load the 'user bio' on their 'Profile Page' and not send them off to another page.

Presently, the partial is unable to be found. This is my code below.

In my routes.rb file, i have created a url path for the bio action which translates to

    bio_lovely_path url -> /lovelies/:id/bio 

This is done in this manner since i need to retrieve that particular user's information i created it as a member.

config/routes.rb

resources :lovelies do
  member do
    get 'bio'
  end
 end

My link is in my layouts/_header.html.erb

 if logged_in?
  <li class="header-log"><%= link_to "Bio", bio_lovely_path, :remote => true %></li>
else
//display none logged in links
 <%end%>

My controller where I have the action is called

LovelyController, the bio action is defined as follows

//display the current user bio

    def bio
      @lovely = Lovely.find(params[:id])
      respond_to |format|
       format.js
      end
    end

I have a jQuery call in my lovelies.coffee file to render the lovelies/_bio.html.erb partial to the div in my lovelies/show.html.erb

    jQuery ->$('#partial).html '<%= escape_javascript(render 'bio') %>

My output says throws a 500 error - Failed to load resource.

My understanding is that the jQuery adds that html to the <div> in show.html.erb which process it as ruby and should result in the _bio.html.erb being rendered. I am new to Rails and would really appreciate suggestions and guidance on how to go about solving this issue. Thanks

It sounds like what you are trying to do is make an AJAX call in Rails, judging from the :remote => true in the link helper. You are almost there; however, you aren't quite doing what Rails expects.

When a link that looks like this

= link_to 'Bio', bio_lovely_path(@lovely), :remote => true
# small change from the code you gave - because your path `lovelies/:id/bio` 
# has `:id` in it, you must provide the object you are referring to, `@lovely`.
# in fact, this is probably where your 500 error came from.

is clicked, it's as though it triggers an AJAX call like so:

// you don't have to write this; `:remote => true` ensures that it gets done 
// for you.
$.ajax({
    url: '/lovelies/<@lovely.id>/bio',
    type: 'get',
    dataType: 'script'
})

This hits your lovelies#bio controller action as data type js . You did the right thing there by telling it to respond_to the js format. This will allow it to render a js file. That is, at the end of the controller action, Rails will look for a corresponding js.erb file to execute. (Usually, it looks for a html.erb file, but you have, by using :remote => true , told it to use JavaScript this time.)

app/views/lovelies/bio.js.erb 1

$('#partial').html('<%= escape_javascript(render(partial: "bio.html.erb")).html_safe %>');

Formerly, you had approximately this code in lovelies.coffee , which won't work. For one, Rails won't know to execute it after the controller action. For another, files in your assets folder are limited in their ERB capabilities (though they can do a little, if you give them the .erb extension).

1 You can use CoffeeScript, .coffee.erb , if you prefer. I don't know the specifics of that, though; I avoid CoffeeScript when I can.


Now that I've attempted to explain the AJAX process when using the Rails :remote => true attribute, let me propose an alternative. I've recently recognized that for a task as simple as inserting a few more elements into a page, it's usually easier to just include them in the first place. Hide them by giving their container the display: none CSS property, and then reveal them when the button is clicked with jQuery's .slideDown() or something similar. It will let you skip the routing, controller action, js.erb file, and all that hassle.

Basically, I'd recommend to (most of the time) save the fancy AJAX calls in Rails for when you need to delete, create, or update. It isn't usually worth it for dynamically adding a little extra information to the page when there's a simpler way.

A partial is supposed to be rendered as part of a different page using render partial: 'name_of_partial' within another file. However, your controller has a bio method, which will need a bio.html.erb file for rails to use for the main bio page at that path. Note the lack of an underscore at the start of the filename.

Either use a different page and render your _bio.html.erb partial within it (and don't have a separate path), or have a page that's just for the bio.

Found a simple solution

  1. Create a container to hold the rendered partial.
  2. Use Coffeescript events to trigger the partial to be rendered once the associated id is clicked.

html file - //button to click and display bio on the page

<button id="display-bio">Lovely Bio </button>

//the div which displays the bio on the page

<div id="bio" style='display:none'>
    <%= render 'layouts/bio'%>
</div>

code in coffeescript

//the code in coffee script to trigger the event

$('#display-bio).click ->
    $('#bio).show()

I think that's pretty simple.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM