Reputation:
QUESTION - is there a way to pass/use params
hash data to the associated model?
Essentials of my app:
Image
model belongs_to
User
model, User
model has_many
Image
instances. Image
schema:
create_table "images", force: :cascade do |t| t.string "filename" t.string "mime_type" t.binary "content" t.integer "user_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false end
add_index "images", ["user_id"], name: "index_images_on_user_id"
In root_url (which is StaticPagesController#home
) I have image upload form:
in Image
model I do:
def uploaded_file=(initial_data)
self.filename = initial_data.original_filename
self.mime_type = initial_data.content_type
self.content = initial_data.read
initial_data.rewind
end
Also a custom validation:
validate :mime_type
with
def mime_type
correct_mime = ["image/jpeg", "image/png", "image/gif"]
unless correct_mime.include? params[:image][:uploaded_file].content_type.chomp
errors.add(:base, 'must be .jpeg, .png or .gif')
end
end
6. Is it possible to pass params[:image][:uploaded_file] to Image
model as a hash with original hash structure?
What I have tried and none of them works:
Image
model - NO GOcreate
action (separately or from inside the custom class method) - NO GOcontroller#action
- NO GOWHAT works??
Global variable - $variable
Is it a rails way to do that? -> query data to model
Upvotes: 3
Views: 812
Reputation: 101811
In a good MVC app your models should not be aware of the parameters, the request or any direct user input. The model just takes data from the controller and enforces the business logic and persists the data.
class Image < ActiveRecord::Base
belongs_to :user
validates_inclusion_of :mime_type,
in: ["image/jpeg", "image/png", "image/gif"],
message: 'must be .jpeg, .png or .gif'
end
class ImagesController < ApplicationController
def new
@image = Image.new
end
def create
@image = Image.new(
filename: image_params.original_filename
mime_type: image_params.content_type,
content: image_params.read
)
if @image.save
redirect_to root_path
else
render :new
end
end
private
def image_params
params.require(:image).require(:uploaded_image)
end
end
Upvotes: 4
Reputation: 3248
The model code seems to be correct, it's just the way you're attempting to get the image data to the model that is against convention. Usually you would create a new Image
instance in your controller and then set the image data, like so:
image = user.images.new # If "user" is set to the correct user for the image
image.uploaded_file = params[:image][:uploaded_image]
# ...whatever else you need to do with the image here
image.save
That's a barebones controller action, so you're going to want to make sure the Image
validates and handle validation errors and whatnot, but hopefully that will get you started.
Upvotes: 2
Reputation: 10406
Given you have
def uploaded_file=(initial_data)
self.filename = initial_data.original_filename
self.mime_type = initial_data.content_type
self.content = initial_data.read
initial_data.rewind
end
So you're setting the mime_type to the content_type of the file.
Why can't you do
def mime_type
correct_mime = ["image/jpeg", "image/png", "image/gif"]
unless correct_mime.include? mime_type.chomp
errors.add(:base, 'must be .jpeg, .png or .gif')
end
end
Upvotes: 1