[Rails Level 2] RENDERING EXTREMITIES -- Ex (Return in Json, resoure route)

RENDER

Complete the method below so that if the ammo is low it will render the fire_and_reload view, otherwise it should render the fire_weapon view.

复制代码
1. In this case, render will take a single argument that maps to the name of the view.
2. If you don't call render, Rails will automatically render the view of the same name as the action
3. The correct answer should be:

class WeaponsController < ApplicationController 
  def fire_weapon
    @weapon = Weapon.find(params[:id]) 
    @weapon.fire!

    if @weapon.low_ammo?
      render :fire_and_reload 
    end
  end 
end
复制代码

 

CUSTOM RESOURCE ROUTES

Create two custom member routes on the weapons resource, so you have a put method calledtoggle_condition and a put method called reload.

复制代码
1. To add routes to the :weapons resource pass a block, like this:
resources :weapons do
  # custom routes go here
end

2. To add a custom route, call the HTTP method and then pass in the name, like this:
resources :weapons do
  put :toggle_condition, on: :member
end

RailsForZombies::Application.routes.draw do
  resources :zombies do
    resources :weapons do
      put :toggle_condition, on: :member
      put :reload, on: :member
    end
  end
end
复制代码

 

RENDER JSON

Complete the create method below. When @weapon.save is successful it should render the @weapon object in JSON, have status :created, and set the location to the @weapon's show url. When @weapon.save fails it should return the @weapon.errors and have the status:unprocessable_entity.

复制代码
1. To render a @weapon as json, you can do this:
render json: @weapon

2. render takes the options :status and :location, like this:
render json: @weapon, status: :created, location: @weapon

class WeaponsController < ApplicationController 
  def create
    @weapon = Weapon.new(params[:weapon]) 
    if @weapon.save
      render json: @weapon, status: :created,
      location: @weapon
    else
      render json: @weapon.errors, status: :unprocessable_entity
    end
  end 
end
复制代码

 

RENDER JSON W/OPTIONS

Complete the controller so that it returns in JSON only the amount of ammo which is left in the weapon. If the ammo has less than 30 bullets it should return the status code :ok, and if not it should return the status code :unprocessable_entity.

复制代码
1. To limit the json that is output, you'd use to_json and pass in the :only option, like this:
@weapon.to_json(only: :ammo)

2. render takes the option :status, like this:
render json: @weapon.to_json(only: :ammo), status: :ok 

class WeaponsController < ApplicationController
  def reload
    @weapon = Weapon.find(params[:id]) 

    if @weapon.ammo < 30
      @weapon.reload(params[:ammo_to_reload])
      render json: @weapon.to_json(only: :ammo), status: :ok
    else
      render json: @weapon.to_json(only: :ammo), status: :unprocessable_entity
    end
  end
end
复制代码

 

MORE TO JSON OPTIONS

Modify the show action so that the JSON it renders includes the zombie record the @weapon belongs to. Also make it exclude the :id:created_at, and :updated_at fields.

复制代码
1. To exclude some data in a to_json call, use :except, like this:
@weapon.to_json(except: [:updated_at, :id, :created_at])

2. To include an association in a to_json call, use the :include option, like this:
@weapon.to_json(except: [:updated_at, :id, :created_at], include: :zombie)

class WeaponsController < ApplicationController
  def show
    @weapon = Weapon.find(params[:id])
    render json: @weapon.to_json(except: [:id, :created_at, :updated_at], include: :zombie)
  end
end
复制代码

 

AS JSON

Edit the as_json method so the Zombie class only returns the zombie's name and weapons (useinclude). Only return the weapon's name and ammo.

class Zombie < ActiveRecord::Base
  has_many :weapons

  def as_json(options=nil)
    super (options || {only: :name, include: {weapons: {only: [:name, :ammo]}}})
  end 
end

 

LINK REMOTE

Modify the show.html.erb view below so that both the Toggle link and the Reload form use AJAX. All you need to do is add the option that makes them ajaxified.

http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to

复制代码
1. Use the remote option to make a link use Ajax, like this:
link_to "Toggle", toggle_condition_weapon_path(@weapon), remote: true

<ul>
  <li>
    <em>Name:</em> <%= @weapon.name %>
  </li> 
  <li>
    <em>Condition:</em>
    <span id="condition"><%= @weapon.condition %></span>
    <%= link_to "Toggle", toggle_condition_weapon_path(@weapon), remote: true %>
  </li> 
  <li>
    <em>Ammo:</em>
    <span id="ammo"><%= @weapon.ammo %></span>
  </li>
</ul>

<%= form_for @weapon, url: reload_weapon_path(@weapon), remote: true do |f| %>
  <div class="field">
    Number of bullets to reload:
    <%= number_field_tag :ammo_to_reload, 30 %> <br /> <%= f.submit "Reload"%>
  </div>
<% end %>
复制代码

 

AJAX RESPONSE

Modify the toggle_condition action so that it responds to JavaScript, and complete thetoggle_condition.js.erb using jQuery to update the condition span with the @weapon's changed condition and make it highlight.

复制代码
<p id="notice"><%= notice %></p>
<ul>
  <li>
    <em>Name:</em>
    <%= @weapon.name %>
  </li>
  <li>
    <em>Condition:</em>
    <span id="condition"><%= @weapon.condition %></span> 
    <%= link_to "Toggle", toggle_condition_user_weapon_path(@user, @weapon), remote: true %>
  </li>
</ul>
复制代码

Answer:

weapons_controller.rb:

复制代码
class WeaponsController < ApplicationController
  def toggle_condition
    @weapon = Weapon.find(params[:id]) 
    @weapon.toggle_condition 

    respond_to do |format|
      format.html { redirect_to @weapon, notice: 'Changed condition' }
      format.js
    end
  end
end
复制代码

toggle_condition.ks.erb:

复制代码
1. To get an action to respond to an Ajax request, you need to add format.js, like this:
respond_to do |format|
  format.html { redirect_to @weapon, notice: 'Changed condition' }
  format.js 
end

2. You can add javascript code with erb tags in toggle_condition.js.erb, like this:
$('#condition').text("<%= @weapon.condition %>").effect("highlight")

//=require jQuery_ui

$("#condition").text("<%= @weapon.condition %>").effect('highlight')
复制代码

 

AJAX RESPONSE II

Now write the controller and JavaScript code needed to properly reload the weapon using the ajaxified form. In the reload.js.erb use jQuery to update the #ammo text to the current @weapon.ammo value and if the ammo value is over or equal to 30, fadeOut the #reload_form div.

复制代码
<p id="notice"><%= notice %></p>
<ul>
  <li>
    <em>Name:</em>
    <%= @weapon.name %>
  </li>
  <li>
    <em>Condition:</em>
    <span id="condition"><%= @weapon.condition %></span> 
    <%= link_to "Toggle", toggle_condition_user_weapon_path(@user, @weapon), remote: true %>
  </li>
  <li>
    <em>Ammo:</em>
    <span id="ammo"><%= @weapon.ammo %></span>
  </li>
</ul>
 
<div id="reload_form">
<%= form_for [@user, @weapon], url: reload_user_weapon_path(@user, @weapon), remote:true do |f| %>
  <div class="field">
    Number of bullets to reload:
    <%= number_field_tag :ammo_to_reload, 30 %> <br />
    <%= f.submit "Reload" %>
  </div>
<% end %>
</div>
 
<%= link_to 'Edit', edit_weapon_path(@weapon) %> |
<%= link_to 'Back', weapons_path %>
复制代码

Answer:

复制代码
#weapons_controller.erb

class WeaponsController < ApplicationController
  def reload
    @weapon = Weapon.find(params[:id]) 

    respond_to do |format|
      if @weapon.ammo < 30
        @weapon.reload(params[:ammo_to_reload])
      
        format.json { render json: @weapon.to_json(only: :ammo), status: :ok }
        format.html { redirect_to @weapon, notice: 'Weapon ammo reloaded' }
     else
        format.json { render json: @weapon.to_json(only: :ammo), status: :unprocessable_entity }
        format.html { redirect_to @weapon, notice: 'Weapon not reloaded' }
      end
      format.js
    end
  end
end
复制代码
$("#ammo").text("<%= @weapon.ammo %>")
<% if @weapon.ammo >= 30%>
  $("#reload_form").fadeOut();
<% end %>

 

COFFEESCRIPT

Instead of returning jQuery which gets executed on the client-side, lets write the ajax request in CoffeeScript communicating with JSON. It should do the same thing as the last challenge, updating & highlighting the ammo, and fading out the form (hint: fade out the wrapper element) if ammo is equal or above 30. 
Tip for your ajax form: data: {ammo_to_reload: ammo}.

复制代码
class WeaponsController < ApplicationController
  def reload
    @weapon = Weapon.find(params[:id]) 
 
    respond_to do |format|
      if @weapon.ammo < 30
        @weapon.reload(params[:ammo_to_reload])
      
        format.json { render :json => @weapon.to_json(:only => :ammo), status: :ok }
        format.html { redirect_to @weapon, notice: 'Weapon ammo reloaded' }
      else
        format.json { render :json => @weapon.to_json(:only => :ammo), status: :unprocessable_entity }
        format.html { redirect_to @weapon, notice: 'Weapon not reloaded' }
      end
    
      format.js
    end
  end
end
复制代码
复制代码
<p id="notice"><%= notice %></p>
<ul>
  <li>
    <em>Name:</em>
    <%= @weapon.name %>
  </li>
  <li>
    <em>Condition:</em>
    <span id="condition"><%= @weapon.condition %></span> 
    <%= link_to "Toggle", toggle_condition_user_weapon_path(@user, @weapon), remote: true %>
  </li>
  <li>
    <em>Ammo:</em>
    <span id="ammo"><%= @weapon.ammo %></span>
  </li>
</ul>
 
<div id="reload_form">
<%= form_for [@user, @weapon], url: reload_user_weapon_path(@user, @weapon), remote:true do |f| %>
  <div class="field">
    Number of bullets to reload:
    <%= number_field_tag :ammo_to_reload, 30 %> <br />
    <%= f.submit "Reload" %>
  </div>
<% end %>
</div>
 
<%= link_to 'Edit', edit_weapon_path(@weapon) %> |
<%= link_to 'Back', weapons_path %>
复制代码

Answer:

复制代码
$(document).ready ->
  $('div#reload_form form').submit (event) ->
    event.preventDefault()
    url = $(this).attr('action')
    ammo = $('#ammo_to_reload').val()
    $.ajax
      type: 'put',
      data: {ammo_to_reload: ammo},
      url: url,
      dataType: 'json',
      success: (json)->
        $("#ammo").text(json.ammo).effect('highlight')
        if json.ammo >= 30
          $("#reload_form").fadeOut()
复制代码

 

posted @   Zhentiw  阅读(640)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示