Rails模型的实例只能通过控制台创建

时间:2013-04-01 20:28:01

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

我一直在关注创建Rails博客(http://www.roberthuberdeau.com/articles/4-How-to-create-a-blog-in-Ruby-on-Rails-3)的教程,并且基本上已经一直到最后。

然而,在所有的迁移之后,我现在正在努力。每当我完成以前用于创建文章的表单时,我都无法在索引页面上看到它们。我已经挖出来并且相信错误的根源是当我按下“创建文章”时我没有保存任何文章。

为了测试这个,我使用控制台创建了一篇文章,它应该出现,因此我认为问题出现在创建文章的形式和控制器之间(尽管我很乐意对此进行更正)。

每当我尝试下面的日志中都会出现以下内容:

Started POST "/articles" for 127.0.0.1 at 2013-04-01 21:12:58 +0100
Processing by ArticlesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"XLeHm+4Tgd6n9vt4RxAQ5YVTbWTi+UnqkmBso9Iuo+4=", "article"=>{"title"=>"I rule", "body"=>"Change teams.", "tag_names"=>"kill", "published"=>"1"}, "commit"=>"Create Article"}
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
  Role Load (0.1ms)  SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles"."id" = "roles_users"."role_id" WHERE "roles_users"."user_id" = 1 AND "roles"."name" = 'Admin' LIMIT 1
  Role Load (0.1ms)  SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles"."id" = "roles_users"."role_id" WHERE "roles_users"."user_id" = 1 AND "roles"."name" = 'Moderator' LIMIT 1
  Role Load (0.1ms)  SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles"."id" = "roles_users"."role_id" WHERE "roles_users"."user_id" = 1 AND "roles"."name" = 'Member' LIMIT 1
Redirected to http://localhost:3000/
Completed 302 Found in 5ms (ActiveRecord: 0.5ms)

使用数据库架构:

ActiveRecord::Schema.define(:version => 20130401171646) do

  create_table "articles", :force => true do |t|
    t.string   "title"
    t.text     "body"
    t.datetime "created_at",                    :null => false
    t.datetime "updated_at",                    :null => false
    t.integer  "user_id",                       :null => false
    t.boolean  "published",  :default => false
  end

  create_table "comments", :force => true do |t|
    t.integer  "article_id"
    t.string   "name"
    t.string   "email"
    t.text     "body"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
  end

  create_table "roles", :force => true do |t|
    t.string   "name"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
  end

  create_table "roles_users", :id => false, :force => true do |t|
    t.integer "role_id"
    t.integer "user_id"
  end

  create_table "taggings", :force => true do |t|
    t.integer  "article_id"
    t.integer  "tag_id"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
  end

  create_table "tags", :force => true do |t|
    t.string   "name"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
  end

  create_table "users", :force => true do |t|
    t.string   "email",                  :default => "", :null => false
    t.string   "encrypted_password",     :default => "", :null => false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          :default => 0
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at",                             :null => false
    t.datetime "updated_at",                             :null => false
  end

  add_index "users", ["email"], :name => "index_users_on_email", :unique => true
  add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true

end

文章控制者:

class ArticlesController < ApplicationController
  before_filter :authenticate_user!, :except => [:index, :show]
  # GET /articles
  # GET /articles.xml
  def index
    @articles = Article.published.page(params[:page]).per(5).ordered

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @articles }
    end
  end

  # GET /articles/1
  # GET /articles/1.xml
  def show
    @article = Article.find(params[:id])
    @comment = Comment.new(:article=>@article)

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @article }
    end
  end

  # GET /articles/new
  # GET /articles/new.xml
  def new
    @article = Article.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @article }
    end
  end

  # GET /articles/1/edit
  def edit
    @article = Article.find(params[:id])
    authorize! :edit, @article
  end

  # POST /articles
  # POST /articles.xml
  def create
    authorize! :create, @article
    @article = Article.new(params[:article])
    @article.user_id = current_user.id

    respond_to do |format|
      if @article.save
        format.html { redirect_to(@article, :notice => 'Article was successfully created.') }
        format.xml  { render :xml => @article, :status => :created, :location => @article }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @article.errors, :status => :unprocessable_entity }
      end
    end
  end

  # PUT /articles/1
  # PUT /articles/1.xml
  def update
    @article = Article.find(params[:id])
    authorize! :update, @article
    respond_to do |format|
      if @article.update_attributes(params[:article])
        format.html { redirect_to(@article, :notice => 'Article was successfully updated.') }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @article.errors, :status => :unprocessable_entity }
      end
    end
  end

  # DELETE /articles/1
  # DELETE /articles/1.xml
  def destroy
    @article = Article.find(params[:id])
    authorize! :destroy, @article
    @article.destroy

    respond_to do |format|
      format.html { redirect_to(articles_url) }
      format.xml  { head :ok }
    end
  end


end

文章模型:

class Article < ActiveRecord::Base
  attr_accessible :body, :title, :tag_names
  has_many :comments, :dependent => :destroy
  has_many :taggings, :dependent => :destroy
  has_many :tags, :through => :taggings
  validates_presence_of :title, :body
  validates_uniqueness_of :title
  attr_writer :tag_names
  after_save :assign_tags
  validates_numericality_of :user_id  
  belongs_to :user
  scope :published, lambda {{:conditions => ['published = ?', true]}}
  scope :ordered, lambda {{:order => "Created_at DESC" }}
  def tag_names
    @tag_names || tags.map(&:name).join(' ')
  end

  private

  def assign_tags
    if @tag_names
      self.tags = @tag_names.split(/\,/).map do |name|
        Tag.find_or_create_by_name(name)
      end
    end
  end
end

表单部分用于创建文章:

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

      <ul>
      <% @article.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </div>
  <div class="field">
    <%= f.label :body %><br />
    <%= f.text_area :body %>
  </div>
  <div class="field">
    <%= f.label :tag_names, "Tags" %>  
    <%= f.text_field :tag_names %>  
  </div>
  <div class="field">
    <%= check_box("article", "published" ) %>
    <%= "Publish article" %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

非常感谢你能给我的任何帮助。

按要求:

Ability.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user

    if user.role? :Admin
      can :manage, :all
      can :publish, Article
    elsif user.role? :Moderator
      can :read, [Article, Comment]
      can [:edit, :update], Comment
    elsif user.role? :Member
       can :read, :all
       can :create, [Article, Comment]
       can [:edit, :update], Comment
    end
  end
end

P.S。我能看到的唯一其他错误(我不知道它是否相关或完全不同)是在尝试查看文章(show.html.erb)时收到以下错误:

Processing by ArticlesController#show as HTML
  Parameters: {"id"=>"1"}
  Article Load (0.2ms)  SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? LIMIT 1  [["id", "1"]]
Completed 500 Internal Server Error in 44ms

ActiveModel::MassAssignmentSecurity::Error (Can't mass-assign protected attributes: article):
  app/controllers/articles_controller.rb:18:in `new'
  app/controllers/articles_controller.rb:18:in `show'

2 个答案:

答案 0 :(得分:1)

我猜测authorize! :create, @article中的ArticleController.create行存在问题。在执行时,尚未创建@article

根据CanCan来源,我认为以下可能会做你想要的:

def create
   authorize! :create, Article
   @article = Article.new(params[:article])
   @article.user_id = current_user.id
   ...

答案 1 :(得分:0)

因为这个原因,没有创建这篇文章。

authorize! :create, @article

你必须向我们展示你的能力模型,能力.rb。

你可能也想尝试一下。 bundle install并重新启动服务器。