【问题标题】:Saving a model with has_many association使用 has_many 关联保存模型
【发布时间】:2012-11-30 22:56:50
【问题描述】:

我正在为学校构建审核应用程序。用户只有在登录后才能查看学校。

你现在可以做什么:

您可以撰写评论并添加 1 - 5 之间的评分。应用程序会保存评论。

我想要它做什么:

我想保存记录的 user_id。因此,评论属于用户和学校。

但我对如何做到这一点有点困惑。欢迎任何想法和指导方针=)

审查模型:

class Review < ActiveRecord::Base
  belongs_to :school
  belongs_to :user
  attr_accessible :content, :rating
end

学校模式:

class School < ActiveRecord::Base
  has_many :reviews
  ..more code..
end

用户模型:

class User < ActiveRecord::Base  
  has_many :reviews
  ...more code..
end

审核控制者:

class ReviewsController < ApplicationController
    def create
        @school = School.find(params[:school_id])
        @review = @school.reviews.create!(params[:review])
        redirect_to @review.school, notice: "Review has been created."
    end
end

审核表

<%= form_for [@school, Review.new] do |f| %>
        <h3>Write a review</h3>
        <div class="reviews_comments_container">
            <div class="review_box">
                <ol class="radio-rater">
                    <%= f.radio_button(:rating, 1) %>
                    <%= f.radio_button(:rating, 2) %>
                    <%= f.radio_button(:rating, 3) %>
                    <%= f.radio_button(:rating, 4) %>
                    <%= f.radio_button(:rating, 5) %>
                </ol>
            </div>
            <div class="review_box" id="review_textarea">
                <%= f.text_area :content, rows: 4, cols: 70 %>
            </div>
            <div class="review_box">
                <%= f.submit 'Save your review', :class => "btn" %>
            </div>
        </div>
    <% end %>

迁移文件:

class CreateReviews < ActiveRecord::Migration
  def change
    create_table :reviews do |t|
      t.text :content
      t.integer :rating
      t.belongs_to :school
      t.belongs_to :user
      t.timestamps
    end
    add_index :reviews, [:school_id, :user_id]
  end
end

【问题讨论】:

  • 我猜你的意思是你想通过将它包含在 ReviewsController 的创建操作中来将它保存在评论表中?然后您应该在创建操作中包含:@user_id = current_user(如果您在评论表中有 user_id 列)。
  • 是的,这就是基本概念。但是如何在 Rails 中编写它??

标签: ruby-on-rails ruby ruby-on-rails-3


【解决方案1】:

有几种不同的方法可以做到这一点。您已经正确设置了关联,因此它归结为您的控制器。您的:school_id 已经设置,因为您的create 调用方式:

@review = @school.reviews.create!(params[:review])

您可以手动设置:user_id

params[:review][:user_id] = current_user.id
@review = @school.reviews.create!(params[:review])

假设您的登录系统中有一个current_user 方法,这是相当标准的。您的创建操作可能会有所改进。试试这样的:

def create
    @school = School.find(params[:school_id])
    @review = @school.reviews.new(params[:review])

    #Assuming your authentication provides the current_user method
    @review.user_id = current_user.id

    if @review.save
        redirect_to @review.school, notice: "Review has been created."
    else
        render :new
    end
end

如果验证失败或由于某种原因无法将记录保存到数据库中,则可以更好地控制错误处理。此外,您的reviews_controller 中应该有一个new 操作,这将使它看起来像这样:

class ReviewsController < ApplicationController
    def new
        @school = School.find_by_id(params[:school_id])
        @review = Review.new
    end

    def create
        @school = School.find(params[:school_id])
        @review = @school.reviews.new(params[:review])

        #Assuming your authentication provides the current_user method
        @review.user_id = current_user.id

        if @review.save
            redirect_to @review.school, notice: "Review has been created."
        else
            render :new
        end
    end
end

这样,在您的form_for 调用中,您可以将Review.new 调用更改为@review,这样会更好。

更新:

对不起,我的错。作为this SO answer shows,可以将Review.new放在form_for标签中。这对我来说似乎有点 hacky,但我在几个地方证实了这一点。

【讨论】:

  • 很好的解释,我把表格改成了这样: 我得到这个错误: NilClass:Class 的未定义方法 `model_name'
  • 应该是&lt;%= form_for [@school, @review] do |f| %&gt;
  • 您是否将new 方法添加到您的评论控制器?我将编辑答案以使其更具体。
  • 是的,我添加了您在 ReviewController 中提供的新方法和创建方法。
  • 你能发布你的路线文件吗?如果你使用的是嵌套资源,你也应该在你的路由中做一些改变。
【解决方案2】:

如果您使用 Devise 对用户进行身份验证,则 current_user 是对象,在身份验证后返回。在您的评论控制器中:

class ReviewsController < ApplicationController
  def create
    @school = School.find(params[:school_id])

    @review = @school.reviews.build(params[:review])
    @review.user_id = current_user

      if @review.save
    redirect_to @review.school, notice: "Review has been created."
       end
  end
end

如果您必须在表 'reviews' 中包含一个名为 user_id 的新列,那么您应该创建一个新迁移,然后创建 'rake db:migrate'。 (根据您的迁移,您似乎有此列)。

编辑:嵌套资源的路由:

resources :schools do
  resources :reviews do
end

【讨论】:

  • @user_id = current_user 不起作用。这只是创建了一个名为 user_id 的实例变量。 Rails 无法以这种方式知道它是针对@review 的。
  • 你是对的,应该是@review.user_id = current_user。
猜你喜欢
  • 2015-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多