ActionView::Template::Error (undefined method `image_url' for #<ActionView::Helpers::FormBuilder:0x00007f921c2ac9b0>)

安稳与你 提交于 2021-02-11 15:45:06

问题


I'm using the shrine gem in form object, I want to clip images, so, I followed https://github.com/shrinerb/shrine/wiki/Image-Cropping, but, happed above error, I think that it seems to be don't recognize photos models

views

<%= form_with model: @blog_form , url: user_blogs_path ,local: true do |f| %>

 <div class="field">
  <%  f.label :title %>
  <%= f.text_field :title %>
 </div>

 <div class="field">
   <%  f.label :content %>
   <%= f.text_area :content %>
 </div>

<div class="field">
  <%  f.label :user_id %>
  <%= f.hidden_field :user_id, value: current_user.id %>
</div>

<div class ="field">
  <%= f.fields_for  :photos, @blog_form do |photos_fileds|  %>

  <%= photos_fileds.label :image %>
  <%= photos_fileds.hidden_field :image, value: photos_fileds.cached_image_data  if defined? 
  (photos_filed.cached_image_data) %>
   %= photos_fileds.file_field  :image %><br/>
<div>
  <img id="image" src="<%= photos_fileds.image_url %>"
</div>

<% end %>

</div>

image_uploader

require "vips"
require "image_processing/vips"


class ImageUploader < Shrine
   plugin :derivatives
   THUMBNAILS = {
    large:  [800, 800],
    medium: [600, 600],
    small:  [300, 300],
    }

   Attacher.derivatives do |original|
    vips = ImageProcessing::Vips.source(original)
    vips = vips.crop(*file.crop_points) # apply cropping

    THUMBNAILS.transform_values do |(width, height)|
    vips.resize_to_limit!(width, height)
    end
   end

   plugin :derivation_endpoint, prefix: "derivations/image"

   # Default URLs of missing derivatives to on-the-fly processing.
   Attacher.default_url do |derivative: nil, **|
   next unless derivative && file

   file.derivation_url :transform, shrine_class.urlsafe_serialize(
     crop:            file.crop_points,
      resize_to_limit: THUMBNAILS.fetch(derivative),
    )
   end

  # Generic derivation that applies a given sequence of transformations.
  derivation :transform do |file, transformations|
  transformations = shrine_class.urlsafe_deserialize(transformations)

  vips = ImageProcessing::Vips.source(file)
  vips.apply!(transformations)
 end

end

class UploadedFile
 # convenience method for fetching crop points from metadata
 def crop_points
 metadata.fetch("crop").fetch_values("x", "y", "width", "height")
 end
end

shrine.rb

require "shrine"
require "shrine/storage/file_system"

Shrine.storages = {
  cache: Shrine::Storage::FileSystem.new("app/assets/images", prefix: "uploads/cache"), # temporary
  store: Shrine::Storage::FileSystem.new("app/assets/images", prefix: "uploads"),       # permanent
 }

 Shrine.plugin :activerecord           # loads Active Record integration
 Shrine.plugin :cached_attachment_data # enables retaining cached file across form redisplays
 Shrine.plugin :restore_cached_data    # extracts metadata for assigned cached files
 Shrine.plugin :determine_mime_type

 Shrine.plugin :derivatives

 Shrine.plugin :backgrounding
 Shrine::Attacher.promote_block { PromoteJob.perform_later(record, name, file_data) }
 Shrine::Attacher.destroy_block { DestroyJob.perform_later(data) }

 Shrine.plugin :derivation_endpoint, secret_key: Rails.application.secret_key_base
 Shrine.plugin :default_url

cropbox.js

  import 'cropperjs/dist/cropper.css'

  import Cropper from 'cropperjs'

  function cropbox(image, url, { onCrop }) {
  image.src = url

  new Cropper(image, {
   aspectRatio: 1,
   viewMode: 1,
   guides: false,
   autoCropArea: 1.0,
   background: false,
   zoomable: false,
   crop: event => onCrop(event.detail)
   })
  }

  export default cropbox

fileUpload.js

import cropbox from 'cropbox'
// ...
uppy.on('upload-success', (file, response) => {
// retrieve uploaded file data
const uploadedFileData = response.body['data']

// set hidden field value to the uploaded file data so that it's submitted
// with the form as the attachment
hiddenInput.value = JSON.stringify(uploadedFileData)

cropbox(imagePreview, response.uploadURL, {
  onCrop(detail) {
    let fileData = JSON.parse(hiddenInput.value)
    fileData['metadata']['crop'] = detail
    hiddenInput.value = JSON.stringify(fileData)
   }
 })
})

promote_job.rb

class PromoteJob < ApplicationJob
 def perform(record, name, file_data)
  attacher = Shrine::Attacher.retrieve(model: record, name: name, file: file_data)
  attacher.create_derivatives
  attacher.atomic_promote
 end
end

destroy_job.rb

class DestroyJob < ApplicationJob
 def perform(data)
 attacher = Shrine::Attacher.from_data(data)
 attacher.destroy
 end
end

route.rb

Rails.application.routes.draw do
 mount ImageUploader.derivation_endpoint => "/derivations/image"

  get 'sessions/new'

  devise_for :users

  resources :users do
   resources :blogs
 end
 # For details on the DSL available within this file, see 
https://guides.rubyonrails.org/routing.html
end

blog_form.rb

class BlogForm
include ActiveModel::Model

 attr_accessor :title, :content, :user_id , :photos, :tag_list

 def blog_builder


  @user = User.find(user_id)

  @blogs = @user.blogs.create(title: title , content: content )



 end


 concerning :PhotosBuilder do

 attr_reader :photos_attributes


  def photos

   @photos ||= Photo.new

  end

def photos_attributes=(attributes)
  debugger

  @photos ||= Photo.new(attributes)

  end

end

 def build_association

  @blogs.photos <<  @photos if photos?
  @user.photos << @photos if photos

 end


 def save
  return false if invalid?
  blog_builder
  @blogs.save
  @photos.save if @photos != nil
  build_association

 end

def photos?
   return true if @photos != nil
  end
end

controller

  def new
   @user = params[:user_id]
   @blog_form = BlogForm.new

  end

 def create
   debugger
   @blog_form = BlogForm.new(add_params) if has_a_tags? == true
   @blog_form = BlogForm.new(blog_form_params)

  if @blog_form.save
    redirect_to user_blogs_path
  else
     #False action
   end

  end

I appreciate you, janko-m, arieljuod I rewrite views, then happened new error

before

  ActionView::Template::Error (undefined method `image_url' for # 
  <ActionView::Helpers::FormBuilder:0x00007f9228150380>):
  <%= photos_fileds.hidden_field :image, value: photos.cached_image_data  if 
   defined?(photos.cached_image_data) %>
   <%= photos_fileds.file_field  :image %><br/>
   <div>
   <img id="image" src="<%= photos_fileds.image_url %>"
   </div>
 <% end %>

after

  ActionView::Template::Error (undefined method `image_url' for # 
 <BlogForm:0x00007f9228090a58>):
 <%= photos_fileds.hidden_field :image, value: 
  photos_fileds.cached_image_data  if defined? 
  (photos_filed.cached_image_data) %>
   <%= photos_fileds.file_field  :image %><br/>
   <div>
  <img id="image" src="<%= photos_fileds.object.image_url %>" />
  </div>

<% end %>

environment rails 6.0.2 ruby 2.5.3


回答1:


This line is trying to call #image_url on the form object:

<img id="image" src="<%= photos_fileds.image_url %>" />

Instead it needs to be calling #image_url on the ActiveRecord model:

<img id="image" src="<%= photos_fileds.object.image_url %>" />


来源:https://stackoverflow.com/questions/61523727/actionviewtemplateerror-undefined-method-image-url-for-actionviewhelp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!