[Translation] 165: Batch Edit record (Edit Multiple)

165: Batch Edit record (Edit Multiple)


View original Railscast

Translator: darkbaby123

Proofreading: This is no proofreader, which brother if helpful and snails can contact students, or give me a message

52 sets demonstrated how to edit a number of examples of database records. Sample program that allows you to select more than one task once, then each of the selected task (Task) will be set to "complete."

[Translation] 165: Batch Edit record (Edit Multiple)

This focus on the idea that we would be expanded. But this time, we can let the user choose to update a group record number of properties, not on a set of individual attributes.

Online Store Application



The following shows that we have to transform the application. Currently, if we want to modify the form of the last two records, we must individually edit them. If you want to modify the record very few, this is not a problem. However, if faced with piles of records which is very boring. Now we will modify this procedure, it can also modify multiple attribute group record.



Modify the index view



Each product before we will add a checkbox, so that we can easily choose to modify the product. But before that, we first show all the products table tag wrapped with form. At present we do not have a Controller level products used to edit multiple action, so first url address empty, and then later fill it.

<% form_tag ... do %>


We do not have to specify the form of presentation, so it defaults to POST. Although this form will take us to a display a new page for all selected products, we seem to be using GET, but because we want to pass the id number of products in the past, this is GET not.

Each row in the table, we need to add a checkbox, its value is the corresponding product id (even the title part in the table with an empty <th>, to ensure the form is aligned).

<td><%= check_box_tag "product_ids[]", product.id %></td>


Note check_box_tag's name, it is a square brackets at the end, it is up to all transfer values will be assembled in an array.

Finally, we add in the table below the submit button.

<%= submit_tag "Edit Checked" %>


Now our index view should look like:

<h1>Products</h1>
<% form_tag ... do %>
<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Category</th>
      <th>Price</th>
    </tr>
  </thead>
  <tbody>
    <% for product in @products %>
      <tr>
        <td><%= check_box_tag "product_ids[]", product.id %></td>
        <td><%= product.name %></td>
        <td><%= product.category.name %></td>
        <td><%= number_to_currency product.price, :unit => "&pound;" %></td>
        <td><%= link_to "Edit", edit_product_path(product) %></td>
        <td><%= link_to "Destroy", product_path(product), :confirm => "Are you sure?", :method => :delete %></td>
      </tr>
    <% end %>
  </tbody>
</table>
<%= submit_tag "Edit Checked" %>
<% end %>
<%= link_to "New Product", new_product_path %>


Modify products controller



Our products controller contains useful RESTful action. Now we have to add two more action to edit and update records.

def edit_multiple
end

def update_multiple
end


The usefulness of these two action and standard edit and update about, but they used to deal with multiple records of the editing and updating. One edit_multiple method requires the corresponding view, we had a while to write it.

In our program, Products is a RESTful resources, we must modify the routes file so that the two new action can be accessed. Products because we want to add the collection method, we use: collection parameters to add these two methods.

map.resources :products, :collection => { :edit_multiple => :post, :update_multiple => :put }


: Collection parameters need to be a hash, where hash of key representatives of the name of action, the value of this action on behalf of the html method. As mentioned above, we use POST as edit_multiple the method, although ideally we should use GET.

Now our definition of good action, and we can return to index view, to fill in the correct url address form_tag

<% form_tag edit_multiple_products_path do %>


Now we refresh the index page, you can see the product in front of each checkbox, the following "Edit Checked" button will take us to the edit_multiple page.



The new form



If we select some products, then click the "Edit Checked" button, you will see a missing template error. This is because we do not create the view code, so the next step is to complete it. We will view the code written in the / app / views / products / edit_multiple.html.erb file. But before we look at the click button, development of information generated in the log.

Processing ProductsController#edit_multiple (for 127.0.0.1 at 2009-06-06 19:24:37) [POST]
  Parameters: {"product_ids"=>["3", "4", "5"], "commit"=>"Edit Checked", "authenticity_token"=>"s5z3KEJpBM7zC2JooC/relZ2oZtVpfxL/IMklpcBuYU="}


In the Parameters section, we can see our selected product id to an array of organizations with. In the controller, we will use these parameters to find the product selected before.

def edit_multiple
  @products = Product.find(params[:product_ids])
end


Turning now to our edit_multiple view. In our previous program, we have a partial on the form, it is used in new and edit product page. Looks like we can use this form to take over. But because it does some changes to accommodate batch records, so we simply create a new form.

In the view we first define the beginning of a block without closing the form_for (translators note: original writing form_tag, but the actual code is form_for, so translation to change a bit). Because this form is used to update multiple products, and we as its first parameter to specify a symbol instead of the actual Product object. We would also like for it specifies: url and: method (Note that PUT, it should be specified separately).

<% form_for :product, :url => update_multiple_products_path, :html => { :method => :put } do |form| %>


In the form we need to set all of the selected product id s, otherwise the submission form, we do not know which products will be updated. We can use a series of hidden_field_tag to store the product id s, we make a list to be updated to show these products.

<ul>
  <% for product in @products %>
    <li>
      <%= h product.name %>
      <%= hidden_field_tag "product_ids[]", product.id%>
    </li>
  <% end %>
</ul>


Next, we will add the form elements that form the properties of Product. These properties include the product name, category names, prices, and whether the sale of information. When we submit this form, we just want to update those who filled out the specific value of the property. Therefore, those with a choice of drop-down box, we need to add a blank option, so users can select an "empty" to skip these properties changes.

<ol>
  <li>
    <%= form.label :category_id %>
    <%= form.collection_select :category_id, Category.all, :id, :name, :include_blank => true %>
  </li>
  <li>
    <%= form.label :name %>
    <%= form.text_field :name %>
  </li>
  <li>
    <%= form.label :price %>
    <%= form.text_field :price %>
  </li>
  <li>
    <%= form.label :discontinued %>
    <%= form.select :discontinued, [["Yes", true], ["No", false]], :include_blank => true %>
  </li>
  <li>
    <%= form.submit "Submit" %>
  </li>
</ol>


Finally, we close the form_for the block, we have completed the form.

<% end %>


Now if we refresh the page, we will see our list of selected products, as well as the following product information is used to modify the form. Note that all of the drop-down boxes have been set to null value, so we do not go to modify their values in the database.



Preparation for the updated action



We have now almost completed, but we need to write code for the update_multiple way, when the submission form on the map, update all selected products.

def update_multiple
  @products = Product.find(params[:product_ids])
  @products.each do |product|
    product.update_attributes!(params[:product].reject { |k,v| v.blank? })
  end
  flash[:notice] = "Updated products!"
  redirect_to products_path
end


In update_multiple start, we use an array of products id s (from the hidden form fields transfer up to) get the selected products, and then we loop through and update each product. Because we only update the attributes is not empty, so we reject traversing each parameter and removed the value of empty property. Note that we use is with an exclamation point (!) Of update_attributes! Way, because we do not do any validation on the model. If this program is a real product, we do check, but beyond the scope of the discussion of this set. Use update_attributes! That if some data is not correct, the program will be thrown. All the products are updated once completed, we set up a flash message and then jump back to product list page.

Let us see if it can work. We have two products, Video Game Console and Video Game Disc, was placed on Toys & Games categories. Now we want to change Categories Electronics. If we select these two products and click "Edit Checked" button (Translator's Note: Original is the "Submit" button, but the actual page is the "Edit Checked"). We will see them listed in the edit_multiple page.



If we choose from the category drop-down box, select "Electronics" and then click "Submit" button, we will return to product list page.



You can see, these two product categories have been changed to "Electronics", but other properties are not changed.

Further



Currently we have provided a very effective way to simultaneously edit multiple model objects. But in the end of this episode, we will go further, so the price can be a relative value to change. For example, so that we can reduce the price of all furniture 20%. We can now select more than one product, if we change the form of the price, then all of the products will become the same price. If we make use of virtual property, the logic of relative price change becomes very intuitive. Virtual property in the 16th concentrated presentations, if you want to know them, you can go to see the video or read the article .

Product model we will create a virtual attribute price_modification. We will modify the edit_multiple view form so that it will change our new property instead of directly modifying the price attribute.

<li>
  <%= form.label :price_modification %>
  <%= form.text_field :price_modification %>
</li>


Now we have to set a new model in the Product attribute getter and setter.

class Product < ActiveRecord::Base
  belongs_to :category

  def price_modification
    price
  end

  def price_modification=(new_price)
    if new_price.ends_with? "%"
      self.price += (price * (new_price.to_f / 100)).round(2)
    else
      self.price = new_price
    end
  end
end


getter method is very straightforward: we only need to return to price on the line, but the setter method of a bit more complicated. If the input value (new_value) end with a percent sign, we will convert floating point values (new_price.to_f), divided by 100 and then multiplied by the original price, to find the price on the specific values. Then add it and the original price. If that specific value is negative, the price will fall. Finally, we use ActiveSupport extension round way for the new price to retain two decimal places.

Now, let us start or cheap furniture. We selected two of furniture and then modify them.



Then in the "Price modification" column, fill in "-20%."



When we submitted the form and return to the product list, we can see are lower prices for those products selected by 20%.



Concentrate on the technology that is useful and can be used in a range of scenarios. After the experiment, you should be able to find in your Rails application in many places, can modify the properties are relatively useful.
  • del.icio.us
  • StumbleUpon
  • Digg
  • TwitThis
  • Mixx
  • Technorati
  • Facebook
  • NewsVine
  • Reddit
  • Google
  • LinkedIn
  • YahooMyWeb

Related Posts of [Translation] 165: Batch Edit record (Edit Multiple)

  • hibernate using c3p0 connection pooling

    Private http://www.lifevv.com/tenyo/doc/20070605102040991.html c3p0 for open source's JDBC connection pool, with the release hibernate. This article describes how to use the hibernate configuration in c3p0. c3p0 connection pool configuration is v ...

  • Hibernate configuration parameters hibernate.hbm2ddl.auto

    Hibernate in the configuration file: <properties> <property name="hibernate.hbm2ddl.auto" value="create" /> </ properties> Parameter Description: validate load hibernate, the authentication to create a database t ...

  • Build flex + spring + blazeds + hibernate application

    Build flex + spring + blazeds + hibernate application First, set up the project blazeds 1, will blazeds.war extract to a directory, such as: myflex /; 2, set up java works were such as: MyFlex, in the orientation of selection create project from exis ...

  • Hibernate connection pool configuration

    Hibernate connection pool configuration <! - Jdbc -> <property name="connection.driver_class"> oracle.jdbc.driver.OracleDriver </ property> <property name="connection.url"> jdbc: oracle: thin: @ 10.203.14.132:15

  • Hibernate.cfg.xml configuration file (including the primary key generation strategy Introduction)

    Hibernate.cfg.xml configuration file: <? xml version = "1.0" encoding = "utf-8"?> <! DOCTYPE hibernate-configuration PUBLIC "- / / Hibernate / Hibernate Configuration DTD / / EN" "hibernate-configuration-2.0.dtd

  • hibernate generic generic DAO

    package org.lzpeng.dao; import java.io.Serializable; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.criterion.Criterion; import org.springside.modules.orm.hibernate.Page; /** * * @version 2009-1-10 *

  • Java technology: Eclipse explain the use of techniques

    Editor settings: Window -> Preferences -> Java-> Editor appearance: Display line number, emphasizing symmetry shown in square brackets, to emphasize that the existing line to show Print Margins its check, Tab width set 4, print made from the fiel

  • Struts2 + hibernate + spring problem user log in

    dao layer services layer action jsp <tr> <td align="center"> <b> user name: </ b> </ td> <td> <s: textfield name = "czyNumber" cssClass = "textstyle" theme = "simple" size = &q

  • Hibernate secondary cache

    Hibernate cache: 2-bit cache, also known as process-level cache or SessionFactory level cache, secondary cache can be shared by all of the session Cache configuration and the use of: Will echcache.xml (the document code in hibernate package directory ...

  • Hibernate's lazy strategy

    hibernate Lazy strategy can be used in: <class> tag, it can be true / false Tags can <PROPERTY> values true / false type of necessary tools to enhance <set> <list> can tag values true / false / extra <many-to-one> <on ...

blog comments powered by Disqus
Recent
Recent Entries
Tag Cloud
Random Entries