Экземпляр модели Rails можно создать только через консоль

Я следовал руководству по созданию блога 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 %>

Любая помощь, которую вы можете дать мне в этом, будет принята с благодарностью.

По запросу:

Способность.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'

person Kali_89    schedule 01.04.2013    source источник
comment
что делает эта строка? authorize! :create, @article   -  person Zippie    schedule 02.04.2013
comment
@Zippie Мое (возможно, ошибочное) понимание состоит в том, что это позволяет выполнять это действие только авторизованным пользователям? Немного о том, откуда я взял эту идею: github.com/ryanb/cancan/ вики/авторизация-контроллера-действий   -  person Kali_89    schedule 02.04.2013


Ответы (2)


Я предполагаю, что есть проблема со строкой authorize! :create, @article в файле ArticleController.create. В тот момент, когда это выполняется, @article еще не создан.

Судя по источнику CanCan, я думаю, что следующее может сделать то, что вы хотите:

def create
   authorize! :create, Article
   @article = Article.new(params[:article])
   @article.user_id = current_user.id
   ...
person Dan Wich    schedule 01.04.2013
comment
Спасибо, что так быстро ответили мне - я только что внес предложенное вами изменение, и я боюсь, что оно не сработало, сейчас я просмотрю документы CanCan и посмотрю, где я могу ошибаться. - person Kali_89; 02.04.2013
comment
Ok. Я думаю, что другой подход, который с большей вероятностью сработает, - просто переместить строку authorize! :create, @article после @article.user_id = current_user.id. Таким образом, у него есть экземпляр модели для авторизации. - person Dan Wich; 02.04.2013
comment
Ну, я изменил порядок так, чтобы он шел: @article = Article.new(params[:article]) @article.user_id = current_user.id authorize! :create, @article, но это тоже не работает. Кошмар. (похоже, мы думали об одном и том же!) - person Kali_89; 02.04.2013
comment
Нет ошибки или что? Статья просто никогда не появляется на главной странице? - person Dan Wich; 02.04.2013
comment
Кроме того, сработает ли это, если полностью удалить вызов authorize!? - person Dan Wich; 02.04.2013
comment
Нет ошибки, просто не сохраняется статья (когда я проверяю все статьи в консоли, я вижу только ту, которую я создал с помощью консоли). Когда я удалю авторизацию! call он работает как надо. - person Kali_89; 02.04.2013
comment
Еще одна возможная подсказка добавлена ​​​​в нижней части вопроса - обнаружена еще одна ошибка, которая может быть связана или не связана с этой. - person Kali_89; 02.04.2013
comment
Хорошо, я думаю, что по какой-то причине authorize! отправляет вас обратно на главную страницу, потому что у вас нет разрешения на :create. Вы уверены, что вошли в систему как Member? Похоже, только им разрешено :create статью. И я думаю, что вы можете решить эту другую ошибку, добавив attr_accessible :article, :article_id к вашей модели Comment. - person Dan Wich; 02.04.2013
comment
На данный момент у меня есть только один пользователь, и он помечен как администратор. Не позволит ли :manage, :all пользователю создавать статьи? В любом случае, я добавил can :create, [Article, Comment] в модель администратора, но она все равно не создается. Подсказка на другую ошибку исправила - теперь показываются отдельные статьи :) - person Kali_89; 02.04.2013
comment
Вы правы, :manage включает другие разрешения. Вы можете попробовать выполнить несколько отладочных проверок, добавив p can?(:create, Article), p current_user и p current_user.role?(:Admin) вместо authorize!, а затем просмотреть их вывод в консоли/журнале. - person Dan Wich; 02.04.2013
comment
Наконец-то решил проблему с помощью этих подсказок - current_user был зарегистрирован как администратор, но я неправильно установил идентификатор администратора - спасибо за всю помощь! - person Kali_89; 04.04.2013

Статья создается не из-за этого.

authorize! :create, @article

Вам нужно будет показать нам свою модель способностей, Ability.rb.

Вы также можете попробовать очевидное. bundle install и перезапустите сервер.

person Jason Kim    schedule 01.04.2013
comment
Спасибо, я изменил контроллер, как показано ниже, и он не сработал, то же самое с bundle install и перезапуском. Модель способностей под вопросом... - person Kali_89; 02.04.2013
comment
Снова отредактировали вопрос, так как есть другая ошибка, которая может вызывать или не влиять на эту проблему. - person Kali_89; 02.04.2013