如何在rails 4应用程序中使用分隔符将字符串字段连接到一个字段?

时间:2014-06-29 09:01:50

标签: ruby-on-rails postgresql ruby-on-rails-4 concatenation

我在表单中有多个复选框,其中我将每个字段的结果存储在我在模型中使用attr_accessor:attribute指定的相应临时字段中。我想用逗号分隔符将这些字段的内容加入到一个字段中,并将其存储到数据库中。

我的完整表格是这样的:

<%= form_for @company do |f| %>
  <% if @company.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize(@company.errors.count, "error") %> prohibited
      this company from being saved:</h2>
    <ul>
    <% @company.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
  <% end %>


  <p>

    <div class="row">
        <div class='col-sm-6'>
            <div class="form-group">
               <p>
    <%= f.label :name %><br>
    <%= f.text_field :name,class:'form-control' %>
  </p>
<p>
    <%= f.label :grade %><br>

    <%= f.select(:grade, options_for_select([['Dream', 'dream'], ['A++', 'a++'], ['A+', 'a+'],['A', 'a']])) %>
  </p>

  <p>
    <%= f.label :beCutoff %><br>
    <%= f.text_field :beCutoff,class:'form-control' %>


    </p>
    <%= f.label :branchesAllowed %><br>
 <%= f.check_box :coe, {}, "COE", "" %><%= label_tag :COE %><br>

  <%= f.check_box :ece,  {}, "ECE", ""%><%= label_tag :ECE %><br>
  <%= f.check_box  :ice, {}, "ICE", ""%><%= label_tag :ICE %><br>
  <%= f.check_box  :it,  {}, "IT", ""%><%= label_tag :IT %><br>
  <%= f.check_box :mpae, {}, "MPAE", ""%><%= label_tag :MPAE %><br>
  <%= f.check_box  :bt, {}, "BT", ""%><%= label_tag :BT %><br>
  <%= f.check_box  :is, {}, "IS", ""%><%= label_tag :IS %><br>
  <%= f.check_box  :sp,  {}, "SP", ""%><%= label_tag :SP %><br>
  <%= f.check_box  :pc,  {}, "PC", ""%><%= label_tag :PC %><br>
    <p>
    <%= f.label :backsAllowed %><br>
    <%= f.text_field :backsAllowed,class:'form-control' %>
  </p>
<p>
    <%= f.label :details %><br>
    <%= f.text_field :details,class:'form-control' %>
  </p>
  <p>
    <%= f.label :package %><br>
    <%= f.text_field :package,class:'form-control' %>
  </p>
   <p>
    <%= f.label :xiiCutoff %><br>
    <%= f.text_field :xiiCutoff,class:'form-control' %>
  </p>
    <p>
    <%= f.label :xCutoff %><br>
    <%= f.text_field :xCutoff,class:'form-control' %>
  </p>
  <%= f.label :deadline %><br>

                <div class='input-group date' id='datetimepicker1'>

                    <%= f.text_field :deadline ,class:'form-control',:readonly=>true%>
                    <span class="input-group-addon" ><span class="glyphicon glyphicon-calendar"></span>
                    </span>
                </div>
            </div>
        </div>
        <script type="text/javascript">
            $(function () {
                $('#datetimepicker1').datetimepicker({format: 'YYYY-MM-DD HH:mm:ss '});
            });

        </script>

    </div>

  <p>
    <%= f.submit %>
  </p>



<% end %>

我在模型中指定字段:coe,:ece,:ice等作为attr_accessor:

class Company < ActiveRecord::Base

     attr_accessor :coe,:ece,:ice,:it,:mpae,:bt,:is,:pc,:sp


     validate :deadline_on_or_before_now

  def deadline_on_or_before_now
    errors.add(:deadline, "can't be in the past") if
      !deadline.blank? and deadline < (Time.zone.now+19800).to_datetime
  end

    validates :name, presence: true,
                    length: { minimum: 2 };
    validates :grade,:beCutoff,:details,:package, presence: true;
    validates_inclusion_of :beCutoff,:xiiCutoff,:xCutoff, :in=> 0..100,:message=>"Out of Range";

end

我的控制器看起来像这样:

class CompaniesController < ApplicationController
    def new
        @company = Company.new
    end

    def edit

        @company = Company.find(params[:id])
    end

    def update
        @company = Company.find(params[:id])

        if @company.update(company_params)
            redirect_to @company
        else
            render 'edit'
        end
    end

    def create

        @company = Company.new(company_params)

        if @company.save
            redirect_to @company
        else
            render 'new'
        end
    end

    def index
        @companies = Company.all
    end
    def destroy
        @company = Company.find(params[:id])
        @company.destroy

        redirect_to companies_path
    end

    def show
        @company = Company.find(params[:id])

    end


    private
        def company_params

            params.require(:company).permit(:name, :beCutoff,:grade,:xiiCutoff,:xCutoff,:backsAllowed,:details,:package,:deadline,:branchesAllowed,:coe,:ece,:ice,:it,:mpae,:bt,:is,:sp,:pc) if params[:company]
        end
end

我想加入:coe,:ece,:ice等等字段并将其存储到:branchesAllowed(字符串字段)字段,带有一个commma分隔符,并且只要我需要单独使用它们就能分割这个字段。 我正在使用带有rails 4.1的postgresql。

3 个答案:

答案 0 :(得分:1)

如果我想这样做,我会去存储在字符串字段中的哈希。

before_save :create_string

def create_string
    fields = {}
    fields[:coe]=coe
    fields[:ece]=ece
    # etcetera
    branchesAllowed = fields.to_s # hash to string and then store the string
end

然后,检索值(比如在控制器或视图中):

values = eval(@company.branchesAllowed) # reversely, evaluate string to hash
@coe = values[:coe]
@ece = values[:ece]
# etcetera

答案 1 :(得分:0)

我会稍微改变一下。假设这些是您希望能够设置的Company的所有属性,您可以使用单个整数字段来存储此数据,方法是创建属性类型的数组并使用该数组中每个属性的索引作为二进制值,您可以使用它来标识是否设置了属性。

观看此Railscast以获得完整的解释,因为Ryan比我做得更好:http://railscasts.com/episodes/189-embedded-association

答案 2 :(得分:0)

最快最脏的方式是简单地连接模型中方法中的字段,并在before_save回调中调用该方法:

class Company < ActiveRecord::Base
  # . . .

  before_save :combine_branches   # or choose other callback type respectively
  def combine_branches
    self.branchesAllowed = ""
    self.branchesAllowed += "COE" if coe
    self.branchesAllowed += "ECE" if eve
    self.branchesAllowed += "ICE" if ice
    # … and so on … 
  end
end

现在,当您在控制器中调用saveupdate时,回调会在写入数据库之前触发并设置branchesAllowed字段。

然而,这并不是真的干燥也不容易扩展。如果您想添加另一个分支,则必须至少编辑3个不同的地方。

(呃)解决方案可能如下所示:

class Company < ActiveRecord::Base
  # keep a constant of possible branches tied to the model
  POSSIBLE_BRANCHES = [:coe, :ece, :ice, :it, :mpae, :bt, :is, :pc, :sp]

  # add the branches as virtual attributes (only assign methods)
  attr_writer *POSSIBLE_BRANCHES

  # add virtual attributes reader methods
  # --> define every branch as method, that looks if the value is currenly
  # stored in the branchesAllowed string and return true or false
  POSSIBLE_BRANCHES.each do |pb|
    define_method(pb) do
      self.banchesAllowed.split(',').include?(pb.to_s.upcase)
    end
  end

  # add the callback to combine the branches
  before_save :combine_branches
  def combine_branches
    self.banchesAllowed = POSSIBLE_BRANCHES.select { |pb| !!self.send(pb) }.map(&:upcase).join(',')
  end
end

然后您也可以在视图中使用它们:

<%= f.label :branchesAllowed %><br>
<% Company::POSSIBLE_BRANCHES.each do |pb| %>
  <%= f.check_box pb, {}, pb.to_s.upcase, "" %><%= label_tag pb.to_s.upcase %><br>
<% end %>

因此,如果您想稍后添加另一个分支,只需在数组常量中添加另一个符号即可完成。希望有所帮助。

<强>更新

由于复选框中的boolean值默认使用'1''0'(作为字符串),因此我不完全确定虚拟属性读取器方法是否应该返回而不是布尔值。