打印

同一个表单提交一对多关联的多个Model

同一个表单提交一对多关联的多个Model

最近做了一个小项目.在项目中有一个提交产品,产品有一个信息介绍..产品与介绍是一对多的关系..在添加产品的时候要进行同一表单提交多个Model..查看了一些资料,实现的方法如下.
首先来看看数据库和Model的
数据库脚本迁移文件
[code="ruby"]
class CreateProductInfos < ActiveRecord::Migration
  def self.up
    create_table :product_infos do |t|
      t.string :title,:limit=>100,:null=>false
      t.string :content,:null=>false
      #对应的产品
      t.integer :product_id
      t.timestamps
    end
  end

  def self.down
    drop_table :product_infos
  end
end

class CreateProducts < ActiveRecord::Migration
  def self.up
    create_table :products do |t|
      t.string :name, :limit => 100, :null => false
      t.text :remark, :null => true
      t.string :img_path
      t.timestamps
    end
  end
  def self.down
    drop_table :products
  end
end
[/code]
在Model部分..添加上关联.
[code="ruby"]
class ProductInfo < ActiveRecord::Base
  belongs_to :product
end
class Product < ActiveRecord::Base
  has_many :product_infos
end
[/code]


View设计,View部分主要部分注意,
[code="java"]
<%= link_to_remote "添加产品信息" , :update => "product_types",:url => { :action => "add_product_type" },:position => 'bottom'  %>
[/code]
使用Ajax方式请求服务器.返回的数据更新倒product_types元素上..这个元素就是一个td..代码在最下边贴吧..
controller很简单,就是返回一个模板,主要的目的是动态的添加信息
[code="java"]
  def add_product_type
    render :partial => "product_type"
  end
[/code]
product_type很简单,就是两个产品信息的文本框
[code="java"]
<p>
        <%=text_field_tag "product_infos[][title]","",:size=>20%>
        <%=text_field_tag "product_infos[][content]","",:size=>40%>
</p>
[/code]
写到这里就实现了一个动态添加一个商品信息的页面..当用户点击"添加产品信息"按钮的时候,就会在页面上增加两个文本框,点一次多一个,点一次多一个!!很简单吧~~嘿嘿
然后就是controller上save方法了..我们在页面上添加了一个product_infos[],那么controller上通过params[:product_infos]取出商品信息,然后添加倒商品上.保存到数据库就OK啦.
Controller的设计
[code="ruby"]
def save
    #获取所有商品的类型.
    @product_types = ProductType.find :all
    if request.post?
      #使用表单数据创建一个商品对象
      @product = Product.new params[:product]
      #迭代页面传递来的所有产品信息
      params[:product_infos].each do |info|
      #根据信息创建一个信息实体
        product_info = ProductInfo.new info
        #如果产品信息的标题存在,
        if product_info.title.size > 0
          将产品信息和产品关联上
          @product.product_infos << product_info
        end
      end
      #保存产品
      if @product.save
        #如果存在图片,那么上传图片,更新商品信息
        img_path = add_file @product.img if @product.img.size > 0
        if img_path
          @product.update_attributes(:img_path => "/uploads/"+img_path)
        end
        goto_index "保存成功"
      end
    end
  end
[/code]
这个是完整的View页面...
[code="java"]
<%form_tag ({:action=>:save},:multipart =>true) do%>
        <table width="100%">
                <tr>
                        <td width="50px">产品名:</td>
                        <td>
                                <%=collection_select "product","product_type_id",@product_types,"id","name"%>
                        </td>
                </tr>
                <tr>
                        <td>标题:</td>
                        <td><%=text_field "product","name"%></td>
                </tr>
                <tr>
                        <td colspan="2">
                                <%=file_field "product","img"%>
                        </td>
                </tr>
                <tr>
                        <td colspan="2">
                                <%= fckeditor_textarea("product", "remark", { :toolbarKit => 'Simple', :width => '95%', :height => '350px' }) %>
                        </td>
                </tr>
                <tr>
                        <td colspan="2">
                                <table width="100%">
                                        <tr>
                                                <td width="150px">信息标题</td>
                                                <td>信息内容</td>
                                        </tr>
                                        <tr>
                                                <td colspan="2" id="product_types">
                                                        <%render :partial => "product_type"%>
                                                </td>
                                        </tr>
                                </table>
                        </td>
                </tr>
                <tr>
                        <td colspan="2">
                                <%= link_to_remote "添加产品信息" , :update => "product_types",:url => { :action => "add_product_type" },:position => 'bottom'  %>
                        </td>
                </tr>
                <tr>
                        <td colspan="2">
                                <%= submit_tag "保存" %>
                        </td>
                </tr>
        </table>
<%end%>
[/code]
修改view和save.rhtml是一样的..只不过多了一个循环,先把数据库中已有的信息显示出来.
[code="html"]
<%for info in @product.product_infos%>
        <p>
                <%=text_field_tag "product_infos[][title]",info.title,:size=>20%>
                <%=text_field_tag "product_infos[][content]",info.content,:size=>40%>
        </p>
<%end%>
[/code]
更新部分的Collector和save的稍有不同.我使用update_attributes更新数据库,那么就要把infos添加到params[:product]中.应该实现params[:product][:product_infos] = Array.new
在Array.new中是一个一个的ProductInfo.new
代码如下
[code="ruby"]
  def update
    @product_types = ProductType.find :all
    @product = Product.find params[:id]
    if request.post?
      #创建一个新的元素
      params[:product][:product_infos] = Array.new
      #迭代页面提交上来infos
      params[:product_infos].each do |info|
        #创建ProductInfo实体
        product_info = ProductInfo.new info
        #如果ProductInfo实体的标题有效
        if product_info.title.size > 0
          #将ProductInfo添加到hash中
          params[:product][:product_infos] << product_info
        end
      end
      #根据hash更新商品
      if @product.update_attributes params[:product]
        img_path = add_file @product.img if @product.img.size > 0
        if img_path
          @product.update_attributes(:img_path => "/uploads/"+img_path)
        end
        goto_index "修改成功"
      end
    end
  end
[/code]

TOP

论坛不支持[code]看起来不太舒服哦~~~~

TOP

试试看支持不 好象是支持的哦
[code="ruby"]
class CreateProductInfos < ActiveRecord::Migration
  def self.up
    create_table :product_infos do |t|
      t.string :title,:limit=>100,:null=>false
      t.string :content,:null=>false
      #对应的产品
      t.integer :product_id
      t.timestamps
    end
  end

  def self.down
    drop_table :product_infos
  end
end

class CreateProducts < ActiveRecord::Migration
  def self.up
    create_table :products do |t|
      t.string :name, :limit => 100, :null => false
      t.text :remark, :null => true
      t.string :img_path
      t.timestamps
    end
  end
  def self.down
    drop_table :products
  end
end
[/code]
在Model部分..添加上关联.
[code="ruby"]
class ProductInfo < ActiveRecord::Base
  belongs_to :product
end
class Product < ActiveRecord::Base
  has_many :product_infos
end
[/code]


View设计,View部分主要部分注意,
[code="java"]
<%= link_to_remote "添加产品信息" , :update => "product_types",:url => { :action => "add_product_type" },:position => 'bottom'  %>
[/code]
使用Ajax方式请求服务器.返回的数据更新倒product_types元素上..这个元素就是一个td..代码在最下边贴吧..
controller很简单,就是返回一个模板,主要的目的是动态的添加信息
[code="java"]
  def add_product_type
    render :partial => "product_type"
  end
[/code]
product_type很简单,就是两个产品信息的文本框
[code="java"]
<p>
        <%=text_field_tag "product_infos[][title]","",:size=>20%>
        <%=text_field_tag "product_infos[][content]","",:size=>40%>
</p>
[/code]
写到这里就实现了一个动态添加一个商品信息的页面..当用户点击"添加产品信息"按钮的时候,就会在页面上增加两个文本框,点一次多一个,点一次多一个!!很简单吧~~嘿嘿
然后就是controller上save方法了..我们在页面上添加了一个product_infos[],那么controller上通过params[:product_infos]取出商品信息,然后添加倒商品上.保存到数据库就OK啦.
Controller的设计
[code="ruby"]
def save
    #获取所有商品的类型.
    @product_types = ProductType.find :all
    if request.post?
      #使用表单数据创建一个商品对象
      @product = Product.new params[:product]
      #迭代页面传递来的所有产品信息
      params[:product_infos].each do |info|
      #根据信息创建一个信息实体
        product_info = ProductInfo.new info
        #如果产品信息的标题存在,
        if product_info.title.size > 0
          将产品信息和产品关联上
          @product.product_infos << product_info
        end
      end
      #保存产品
      if @product.save
        #如果存在图片,那么上传图片,更新商品信息
        img_path = add_file @product.img if @product.img.size > 0
        if img_path
          @product.update_attributes(:img_path => "/uploads/"+img_path)
        end
        goto_index "保存成功"
      end
    end
  end
[/code]
这个是完整的View页面...
[code="java"]
<%form_tag ({:action=>:save},:multipart =>true) do%>
        <table width="100%">
                <tr>
                        <td width="50px">产品名:</td>
                        <td>
                                <%=collection_select "product","product_type_id",@product_types,"id","name"%>
                        </td>
                </tr>
                <tr>
                        <td>标题:</td>
                        <td><%=text_field "product","name"%></td>
                </tr>
                <tr>
                        <td colspan="2">
                                <%=file_field "product","img"%>
                        </td>
                </tr>
                <tr>
                        <td colspan="2">
                                <%= fckeditor_textarea("product", "remark", { :toolbarKit => 'Simple', :width => '95%', :height => '350px' }) %>
                        </td>
                </tr>
                <tr>
                        <td colspan="2">
                                <table width="100%">
                                        <tr>
                                                <td width="150px">信息标题</td>
                                                <td>信息内容</td>
                                        </tr>
                                        <tr>
                                                <td colspan="2" id="product_types">
                                                        <%render :partial => "product_type"%>
                                                </td>
                                        </tr>
                                </table>
                        </td>
                </tr>
                <tr>
                        <td colspan="2">
                                <%= link_to_remote "添加产品信息" , :update => "product_types",:url => { :action => "add_product_type" },:position => 'bottom'  %>
                        </td>
                </tr>
                <tr>
                        <td colspan="2">
                                <%= submit_tag "保存" %>
                        </td>
                </tr>
        </table>
<%end%>
[/code]
修改view和save.rhtml是一样的..只不过多了一个循环,先把数据库中已有的信息显示出来.
[code="html"]
<%for info in @product.product_infos%>
        <p>
                <%=text_field_tag "product_infos[][title]",info.title,:size=>20%>
                <%=text_field_tag "product_infos[][content]",info.content,:size=>40%>
        </p>
<%end%>
[/code]
更新部分的Collector和save的稍有不同.我使用update_attributes更新数据库,那么就要把infos添加到params[:product]中.应该实现params[:product][:product_infos] = Array.new
在Array.new中是一个一个的ProductInfo.new
代码如下
[code="ruby"]
  def update
    @product_types = ProductType.find :all
    @product = Product.find params[:id]
    if request.post?
      #创建一个新的元素
      params[:product][:product_infos] = Array.new
      #迭代页面提交上来infos
      params[:product_infos].each do |info|
        #创建ProductInfo实体
        product_info = ProductInfo.new info
        #如果ProductInfo实体的标题有效
        if product_info.title.size > 0
          #将ProductInfo添加到hash中
          params[:product][:product_infos] << product_info
        end
      end
      #根据hash更新商品
      if @product.update_attributes params[:product]
        img_path = add_file @product.img if @product.img.size > 0
        if img_path
          @product.update_attributes(:img_path => "/uploads/"+img_path)
        end
        goto_index "修改成功"
      end
    end
  end
[/code]

TOP

复制内容到剪贴板
代码:
#这样好象可以
[code=ruby]
def index
  
end
[/code]

TOP

高亮都没有.很不舒服....论坛程序应该换个好点的了.!!

TOP