Rails - >将数据库查询结果转换为链接的最佳方法

时间:2015-11-18 04:17:16

标签: ruby-on-rails

我有一个Rails应用程序,允许用户使用options_for_select从成员模型中选择配偶的名字。

<div class="form-group">
  <%= f.label "Spouse:", :class => "col-sm-2 control-label" %>
  <%= select_tag 'spouse', 
      options_for_select(
        @members.where("last_name = ?", @member.last_name)
          .collect{ |u| [ u.first_name + " " + u.last_name ] }, 
        @member.spouse
      ),
      :class => "col-sm-5", :style=>"padding:10px;",
      :prompt => 'None'
  %>
</div>

然后我接受用户的回答并将配偶的姓氏和名字存储在数据库中。

在视图中,我使用以下内容显示答案:

Spouse:<%= @member.spouse %>

我想将link_to添加到此代码段,以允许用户查看配偶的个人资料。

我认为问题在于我没有存储配偶的身份证号码,这阻止了link_to在节目视图中工作。

如何从_form.html.erb中的options_select命令获取配偶的成员ID?而且,如何在Show视图中设置link_to?

我的控制器代码如下:

def show
  @member = Member.find(params[:id])

  @show_courses = @member.courses
  @show_ministry = @member.ministries

  @birthday = @member.birthday
  @show_kids = @member.kids
  @show_strengths = member.strengths
  @show_spouse = @member.spouse
  @show_gender = @member.gender
end

def update
  params[:member][:course_ids] ||= []
  params[:member][:ministry_ids] ||= []
  params[:member][:kid_ids] ||= []
  params[:member][:strength_ids] ||= []
  params[:spouse]

  Member.update(@member, :spouse => params[:spouse])
  Member.update(@member, :gender => params[:gender])
  Member.update(@member, :strength_all => params[:strength_ids])

  @member = Member.find(params[:id])
  @members = Member.all
  @all_courses = @member.courses

更新:这是我的会员模型代码:

class Member < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
              validates :birthday, length: { maximum: 30 }, allow_nil: true

              validates :spouse, presence: true, allow_blank: true
              validates :email, presence: true, on: :create
              scope :spouse_names, -> { :spouse.order(last_name: :asc) } 

            def publish_month
              created_at.strftime("%B %Y")
            end
                # Export List
                def self.to_csv(options = {})
                  CSV.generate(options) do |csv|
                    csv << column_names
                    all.each do |member|
                      csv << member.attributes.values_at(*column_names)
                    end
                  end
                end

                # Import List
                def self.import(file)
                  spreadsheet = open_spreadsheet(file)
                  header = spreadsheet.row(1)
                  (2..spreadsheet.last_row).each do |i|
                    row = Hash[[header, spreadsheet.row(i)].transpose]
                    member = find_by_id(row["id"]) || new
                    parameter = ActionController::Parameters.new(row.to_hash)
                    member.update(parameter.permit(:id, :birthday, :first_name, :last_name, :email, :phone, :street, :city, :state, :zip, :spouse, :strength_ids, :gender, :password))
                    member.save!
                    end
                end

                def self.open_spreadsheet(file)
                  case File.extname(file.original_filename)
                  when ".csv" then Roo::CSV.new(file.path, csv_options: {encoding: "iso-8859-1:utf-8"})
                  when ".xls" then Excel.new(file.path, nil, :ignore)
                  when ".xlsx" then Excelx.new(file.path, nil, :ignore)
                  else raise "Unknown file type: #{file.original_filename}"
                  end
                end

                has_and_belongs_to_many :courses
                has_and_belongs_to_many :ministries
                has_and_belongs_to_many :kids
                has_and_belongs_to_many :strengths

                has_attached_file :avatar, :styles => { mini: "50x50", medium: "300x300>", thumb: "100x100>" }, 
                    :default_url => "default_avatar"

                validates_attachment_content_type :avatar, content_type: ["image/jpeg", "image/gif", "image/png"] 

                def first_and_last
                    "#{first_name} #{last_name}"
                end

            end

2 个答案:

答案 0 :(得分:1)

好的......您可能需要重新设计用户模型并查看个人资料...

这是一种方法...我想可能还有其他一些我不知道ATM的确定,所以让我们开始..

注意:我假设你使用的是rails 4.2 ..其他版本的步骤有点不同..

注意:我想最低限度地更改您的代码..

  1. 删除您的spouse属性,并在has_one模型中建立belongs_toMember关系。

    从shell生成此迁移

    rails g migration AddSpouseToMembers spouse:references
    

    并验证这些行

    add_reference :members, :spouse
    add_foreign_key :spouse, :members, column: :spouse_id
    

    在这两行之前加上这一行。

    remove_column :members, :spouse
    

    并运行迁移

    您可以添加上述relation,只需将其添加到Member模型中即可。

     has_one :spouse, class_name: "Member", foreign_key: :spouse_id
     belongs_to :spouse, class_name: "Member", foreign_key: :spouse_id
    
  2. 将您在控制器代码中指定配偶的行更改为

     Member.update(@member, :spouse => Member.find(params[:spouse]))
    
  3. 将您的观点更改为

     Spouse:<%= link_to @member.spouse.first_name, @member.spouse if @member.spouse.present? %>
    
  4. 注意:非常重要的一个..我不知道你的系统所以使用一些VCS ..这可能不适合你。

    希望有所帮助

答案 1 :(得分:0)

你真的需要重构那些Controller方法,每次调用@ member.xxxx都会触发一个单独的查询,所以你的show方法现在包含大约5个查询(一些或属性看起来好像)!您设置的所有信息都已成为@member的一部分。因此,Rails编写show方法的方法是做类似的事情:

def show
  @member = Member.find(params[:id]).includes(:spouse, :courses, :ministries, :kids) #define all related models
end

在您的视图中,您可以调用要显示的部分,最好是通过渲染这样的部分:

  render @member.courses

将调用partial courses/_course.html.erb

同样适用于您的更新,调用更新3次,创建3个单独的UPDATE查询(查看终端中的服务器以确认)。此外,Rails足够智能,可以直接保存所有相关的模型数据。您还应该使用Rails 4强参数来访问表单提交的数据:

def update
  @member = Member.find(params[:id])
  @member.update(member_params)
end

  private

  def member_params
    params.require(:member).permit(:birthday, :gender, course_ids: [], ministry_ids: [], kid_ids: []) # complete this for your specific case, add all the options you would like the form to save
  end