简体   繁体   中英

How can I expand the micropost model from Hartl's Ruby on Rails tutorial?

I've gone through Michael Hartl's RoR tutorial, and I'd like to expand the micropost model to allow a user to post an item that contains a keyword, price range, and condition field. I've replaced the "content" method in his tutorial with these new methods in the micropost form, micropost model, db migration, factories, and controller. However, when I try to load the form, I get the following error:

Showing C:/Sites/rails_projects/sample_app/app/views/shared/_micropost_form.html.erb where line #4 raised:

undefined method `keyword' for #<Micropost:0x54bd7e0>
Extracted source (around line #4):


  <%= form_for(@micropost) do |f| %>
    <%= render 'shared/error_messages', object: f.object %>
    <div class="field">
      <%= f.text_area :keyword, placeholder: "iPhone 5 16gb" %>
    </div>

    <div class="field">


Trace of template inclusion: app/views/static_pages/home.html.erb

Rails.root: C:/Sites/rails_projects/sample_app

_micropost.html.erb code:

<li>
  <span class="content"><%= micropost.content %></span>
  <span class="timestamp">
    Posted <%= time_ago_in_words(micropost.created_at) %> ago.
  </span>
  <% if current_user?(micropost.user) %>
    <%= link_to "delete", micropost, method: :delete,
                                     data: { confirm: "You sure?" },
                                     title: micropost.content %>
  <% end %>
</li>

microposts_controller.rb code:

class MicropostsController < ApplicationController
  before_action :signed_in_user
  before_action :correct_user,   only: :destroy

  def create
    @micropost = current_user.microposts.build(micropost_params)
    if @micropost.save
      flash[:success] = "Micropost created!"
      redirect_to root_url
    else
      @feed_items = []
      render 'static_pages/home'
    end
  end

  def destroy
    @micropost.destroy
    redirect_to root_url
  end

  private

    def micropost_params
      params.require(:micropost).permit(:content)
    end

    def correct_user
      @micropost = current_user.microposts.find_by(id: params[:id])
      redirect_to root_url if @micropost.nil?
    end

end

factories.rb code:

FactoryGirl.define do
  factory :user do
    sequence(:name)  { |n| "Person #{n}" }
    sequence(:email) { |n| "person_#{n}@example.com"}
    password "foobar"
    password_confirmation "foobar"

    factory :admin do
      admin true
    end
  end

  factory :micropost do
    keyword "iPhone 5"
    price "500"
    condition "used"
    user
  end
end

[timestamp]_create_microposts.rb code:

class CreateMicroposts < ActiveRecord::Migration
  def change
    create_table :microposts do |t|
      t.string :keyword
      t.integer :price
      t.string :condition
      t.integer :user_id

      t.timestamps
    end
    add_index :microposts, [:user_id, :created_at]
  end
end

micropost.rb code:

class Micropost < ActiveRecord::Base
  belongs_to :user
  default_scope -> { order('created_at DESC') }
  validates :keyword, presence: true, length: { maximum: 140 }
  validates :price, presence: true, length: { maximum: 140 }
  validates :condition, presence: true, length: { maximum: 140 }
  validates :user_id, presence: true
end

_micropost_form.html.erb code:

<%= form_for(@micropost) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div class="field">
    <%= f.text_area :keyword, placeholder: "iPhone 5 16gb" %>
  </div>

  <div class="field">
    <%= f.text_area :price, placeholder: "$350-400" %>
  </div>

   <div class="field">
    <%= f.text_area :condition, placeholder: "Used" %>
  </div>


  <%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>

How can I correctly define these new methods, and make it so that the three attributes are saved in the db under one post every time they're submitted?

尝试运行迁移(如果尚未运行),然后重新启动服务器

http://sourceforge.net/projects/sqlitebrowser/

download that, run that application. open your db... it'll be wherever your app is... then db/development.sqlite3

click on the browse data tab. switch to your microposts. are your new columns in there? probably not...

my guess is you just went into your migration files and started tinkering. no no.

once you run a db:migrate, your database is built. any changes that you want to make have to be added in the form of a new migration or rollback.

so in your case... you'll probably want to to run rails g migration add_price_to_microposts , which will create a new file under db/migrate.

class AddPriceToMicroposts < ActiveRecord::Migration
  def change
    add_column :microposts, :keyword, :string
    add_column :microposts, :price, :integer
    add_column :microposts, :condition, :string
  end
end

your other option is to rollback. rake db:migrate:down VERSION=20131130180735 . this will kill your table... but that's probably ok in your case. now you can go back into that migration file... make the changes that you want in the form of t.sting :whatever , then when you're content, rake db:migrate to rebuild the table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM