Ruby on rails — вложенные формы, атрибуты не сохраняются (загрузка изображения со скрепкой)

Я следовал учебнику Харлта, чтобы начать с рубина. Теперь я хочу добавлять картинки в свои микропосты. Когда я использую простую форму только для загрузки изображения, она работает. Когда я хочу загрузить картинку в виде своего микропоста, картинка создается, но все атрибуты пусты.

Журнал сервера для простой загрузки изображения

Started POST "/photos" for 127.0.0.1 at 2013-11-28 17:50:33 +0100
Processing by PhotosController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"u7MWO+E9jM8/g+6RwquQ7XLA3PR+ohQFAx0tmwNOfuY=", "photo"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x007f77b93b2710 @tempfile=#<Tempfile:/tmp/RackMultipart20131128-19203-ypziwp>, @original_filename="photoiphone.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"photo[image]\"; filename=\"photoiphone.jpg\"\r\nContent-Type: image/jpeg\r\n">}, "commit"=>"Create Photo"}
  #[1m#[36mUser Load (0.3ms)#[0m  #[1mSELECT "users".* FROM "users" WHERE "users"."remember_token" = '4c0f0085d819eec94a9d0eba0175fb7642fe4976' LIMIT 1#[0m
  #[1m#[35m (0.1ms)#[0m  begin transaction
Binary data inserted for `string` type on column `image_content_type`
  #[1m#[36mSQL (0.6ms)#[0m  #[1mINSERT INTO "photos" ("created_at", "image_content_type", "image_file_name", "image_file_size", "updated_at") VALUES (?, ?, ?, ?, ?)#[0m  [["created_at", Thu, 28 Nov 2013 16:50:33 UTC +00:00], ["image_content_type", "image/jpeg"], ["image_file_name", "photoiphone.jpg"], ["image_file_size", 51874], ["updated_at", Thu, 28 Nov 2013 16:50:33 UTC +00:00]]
  #[1m#[35m (180.2ms)#[0m  commit transaction
Redirected to http://localhost:3000/photos/15
Completed 302 Found in 191ms (ActiveRecord: 181.2ms)

Журнал сервера для загрузки изображения в форму микросообщения

Started POST "/microposts" for 127.0.0.1 at 2013-11-28 17:49:02 +0100
Processing by MicropostsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"u7MWO+E9jM8/g+6RwquQ7XLA3PR+ohQFAx0tmwNOfuY=", "micropost"=>{"content"=>"test pour log", "photo_attributes"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x007f77b8871248 @tempfile=#<Tempfile:/tmp/RackMultipart20131128-19203-199w522>, @original_filename="paint.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"micropost[photo_attributes][image]\"; filename=\"paint.jpg\"\r\nContent-Type: image/jpeg\r\n">}}, "commit"=>"Post"}
  #[1m#[36mUser Load (0.2ms)#[0m  #[1mSELECT "users".* FROM "users" WHERE "users"."remember_token" = '4c0f0085d819eec94a9d0eba0175fb7642fe4976' LIMIT 1#[0m
  #[1m#[35m (0.1ms)#[0m  begin transaction
  #[1m#[36mSQL (0.9ms)#[0m  #[1mINSERT INTO "microposts" ("content", "created_at", "updated_at", "user_id") VALUES (?, ?, ?, ?)#[0m  [["content", "test pour log"], ["created_at", Thu, 28 Nov 2013 16:49:02 UTC +00:00], ["updated_at", Thu, 28 Nov 2013 16:49:02 UTC +00:00], ["user_id", 101]]
  #[1m#[35mSQL (0.3ms)#[0m  INSERT INTO "photos" ("created_at", "micropost_id", "updated_at") VALUES (?, ?, ?)  [["created_at", Thu, 28 Nov 2013 16:49:02 UTC +00:00], ["micropost_id", 21], ["updated_at", Thu, 28 Nov 2013 16:49:02 UTC +00:00]]
  #[1m#[36m (147.9ms)#[0m  #[1mcommit transaction#[0m
Redirected to http://localhost:3000/
Completed 302 Found in 161ms (ActiveRecord: 149.3ms)

Мы видим, что строка Binary data inserted for string type on column image_content_type присутствует только в первом логе.

контроллер пользователя

class UsersController < ApplicationController
  before_action :signed_in_user, only: [:index, :edit, :update]
  before_action :correct_user,   only: [:edit, :update]

  def new
    @user = User.new
  end

  def index
    #@users = User.all
    @users = User.paginate(page: params[:page])
  end

  def show
    @user = User.find(params[:id])
    @micropost = current_user.microposts.build
    @photo = @micropost.build_photo
    @microposts = @user.microposts.paginate(page: params[:page])
    @feed_items = current_user.feed.paginate(page: params[:page])
  end

  def create
    @user = User.new(user_params)
    if @user.save
      sign_in @user
      flash[:success] = "Welcome to the PYL!"
      redirect_to @user
    else
      render 'new'
    end
  end

  def edit
    @user = User.find(params[:id])
  end

  def update
    if @user.update_attributes(user_params)
      flash[:success] = "Profile updated"
      redirect_to @user
    else
      render 'edit'
    end
  end


  private

    def user_params
      params.require(:user).permit(:name, :email, :password, :password_confirmation)
    end

    def signed_in_user
      store_location
      redirect_to signin_url, notice: "Please sign in." unless signed_in?
    end

    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url) unless current_user?(@user)
    end

end

просмотреть, показать, чтобы пользователь отображал эту форму

<%= form_for @micropost, :html => { :multipart => true }  do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
    <%= f.text_area :content, placeholder: "Compose new micropost..." %>

</div>
<%= f.fields_for :photo do |builder| %>
<%= file_field :image, :f=>builder %>
<% end %>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>

база данных

  create_table "microposts", force: true do |t|
    t.string   "content"
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "photo_id"
  end

  add_index "microposts", ["user_id", "created_at"], name: "index_microposts_on_user_id_and_created_at"

  create_table "photos", force: true do |t|
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "image_file_name"
    t.string   "image_content_type"
    t.string   "image_file_size"
    t.string   "image_update_at"
    t.integer  "micropost_id"
  end

Для простой загрузки изображения я использую этот код:

фотоконтроллер

class PhotosController < ApplicationController
  before_action :signed_in_user, only: [:create, :index]
  before_action :set_photo, only: [:show, :edit]

  def index
    @photos = Photo.all
  end

  def show
  end

  def new
    @photo = Photo.new
  end

  def edit
  end

  def create
    @photo = Photo.new(photo_params)

    respond_to do |format|
      if @photo.save
        format.html { redirect_to @photo, notice: 'Photo was successfully created.' }
        format.json { render action: 'static_pages/home', status: :created, location: @photo }
      else
        format.html { render action: 'static_pages/home' }
        format.json { render json: @photo.errors, status: :unprocessable_entity }
      end
    end
  end

  private
    def set_photo
      @photo = Photo.find(params[:id])
    end

    def photo_params
      params.require(:photo).permit(:image)
    end
end

и создать новую форму

<%= form_for @photo, :html => { :multipart => true } do |f| %>
<%= f.file_field :image %>
<%= f.submit %>
<% end %>

Я использую SQLite Manager для просмотра моей базы данных. У меня также есть контроллер микросообщений, и я действительно не знаю, как он работает, потому что он хорошо работает для микросообщений без изображений, но я думаю, что мне нужно использовать micropost_params в моем пользовательском контроллере, но я не могу доступ к нему.

class MicropostsController < ApplicationController
  before_action :signed_in_user, only: [:create, :destroy]
  before_action :correct_user,   only: :destroy



  def create
    @micropost = current_user.microposts.build(micropost_params)
    @photo = @micropost.build_photo
    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, photo_attributes: [image:  
                [:image_file_name, :image_content_type, :image_file_size, :image_update_at]])
  end

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

конец

Спасибо за помощь :) !!


person 2ueenO    schedule 28.11.2013    source источник


Ответы (1)


Что, если вы вызовете builder.file_field :image вместо file_field :image, :f => : builder?

person davidfurber    schedule 29.11.2013
comment
Я пробовал это раньше. Я только что повторил попытку и все еще имею ту же проблему. Изображение создается в базе данных, но все атрибуты пусты.. :( - person 2ueenO; 29.11.2013
comment
А какие у вас ассоциации inverse_of? - person davidfurber; 29.11.2013