I have been following this tutorial to upload multiple images with carrier wave.
It works as expected but it is displaying the following below the image:
[#<ImageUploader:0xaeb3490 #model=#<Post id: 19, created_at: "2017-07-07 09:33:50", updated_at: "2017-07-07 09:33:50", lat: 54.635, long: -5.84582, images: ["87a8c63a9be6af171244299fc0b0a27e--stunning-art-street-art-illusions.jpg"], artist: "Vemeer", year: nil>, #mounted_as=:images, #storage=#<CarrierWave::Storage::File:0xaeb3430 #uploader=#<ImageUploader:0xaeb3490 ...>>, #file=#<CarrierWave::SanitizedFile:0xaeb3100 #file="C:/path/public/uploads/post/images/19/87a8c63a9be6af171244299fc0b0a27e--stunning-art-street-art-illusions.jpg", #original_filename=nil, #content_type=nil>, #versions={}>]
As explained in the tutorial to get the multiple uploads I did the following:
Rails Migration to create array of images:
class AddImagesToGallery < ActiveRecord::Migration
def change
add_column :posts, :images, :string, array: true, default: []
end
end
Edited posts/_form.html.haml:
= f.file_field :images, multiple: true
Edited post_params
def post_params
post_params.require(:post).permit(:artist, :year, :long, :lat, {images: []})
end
Display the images in posts/show.html.haml
=#mural.images.each do |image|
= image_tag(image.url)
Any help is appreciated!
It works as expected but it is displaying the following below the image:
[#<ImageUploader:0xaeb3490 #model=#<Post id: 19, created_at: "2017-07-07 09:33:50", updated_at: "2017-07-07 09:33:50", lat: 54.635, long: -5.84582, images: ["87a8c63a9be6af171244299fc0b0a27e--stunning-art-street-art-illusions.jpg"], artist: "Vemeer", year: nil>, #mounted_as=:images, #storage=#<CarrierWave::Storage::File:0xaeb3430 #uploader=#<ImageUploader:0xaeb3490 ...>>, #file=#<CarrierWave::SanitizedFile:0xaeb3100 #file="C:/path/public/uploads/post/images/19/87a8c63a9be6af171244299fc0b0a27e--stunning-art-street-art-illusions.jpg", #original_filename=nil, #content_type=nil>, #versions={}>]
This line
=#mural.images.each do |image|
= image_tag(image.url)
should be
- #mural.images.each do |image|
= image_tag(image.url)
Notice the difference between = and -. = is used to display the output. - is used to iterate over the object.
Related
I have an object (Institution) and I want to get the 2 arrays (marks and attachments) that are relationed with this object using JSON.
To be clear: For 1 institution, I have 3 marks and for every mark I have an attachment.
Here's my code of JSON file:
if #data['admin_institution']
json.extract! #data['admin_institution'], :id, :name, :phone, :address, :site, :created_at, :updated_at
if #data['admin_institution'].marks
json.marks #data['admin_institution'].marks
json.array!(#data['admin_institution'].marks) do | admin_mark|
json.attachment admin_mark.attachment
end
end
else
json.set! :response do
json.set! :error, 'Not Found!'
end
end
I want to reproduce something like this:
{
id: 14,
name: "Ins3",
phone: "793215-2555",
address: "lreewrwklkr",
site: "lkerlke.com",
created_at: "2016-03-01T14:00:37.000-03:00",
updated_at: "2016-03-01T14:00:37.000-03:00",
- marks: [
- {
id: 17,
admin_attachment_id: 927,
admin_bookmark_id: 3,
admin_institution_id: 14,
created_at: "2016-03-01T14:00:37.000-03:00",
updated_at: "2016-03-01T14:00:37.000-03:00"
},
{
id: 18,
admin_attachment_id: 945,
admin_bookmark_id: 1,
admin_institution_id: 14,
created_at: "2016-03-01T14:00:37.000-03:00",
updated_at: "2016-03-01T14:00:37.000-03:00"
}
],
- attachment: {
id: 927,
name: "nature-16",
title: "Nature-16",
description: null,
mime_type: "image/jpeg",
url: "/uploads/nature-16.jpg",
created_at: "2016-02-29T09:21:09.000-03:00",
updated_at: "2016-02-29T09:21:09.000-03:00"
}
}
Instead, I'm getting only the values of the last array (attachment). Thanks in advance.
UPDATE:
I used through-association on my institution model then I could get the attachments "directly" through the marks, without do a loop of marks. The following code is giving me almost all that I want.
if #data['admin_institution']
json.extract! #data['admin_institution'], :id, :name, :phone, :address, :site, :created_at, :updated_at, :marks, :attachments
else
json.set! :response do
json.set! :error, 'Not Found!'
end
end
It's returning the Institution, the marks and the attachments, BUT not nested. I want marks inside the institution and attachments inside the marks. How can I make it work?
Try this:
if #data['admin_institution']
...
if #data['admin_institution'].marks
json.marks #data['admin_institution'].marks do | admin_mark|
json.attachment admin_mark.attachment
end
end
else
...
end
I've got an ActiveModel::Serializer question for the experts. Lets say I have the following JSON output where the root element is a SurveyInvite object. Currently the question_answers hash key is just an array of QuestionAnswer objects. How can I make it so that question_answers is a hash of QuestionAnswer objects where the keys are QuestionAnswer.question.id?
{
id: 1,
email: "foo#example.com",
status: "Submitted",
created_at: "10:57AM Sep 1, 2015",
date_submitted: "10:58AM Sep 1, 2015",
survey_response: {
id: 1,
survey_invite_id: 1,
name: "Foo Bar",
title: "Ninja",
published: true,
created_at: "10:58AM Sep 1, 2015",
updated_at: " 3:42PM Sep 2, 2015",
question_answers: [
{
id: 1,
survey_response_id: 1,
mini_post_question_id: 20,
answer: "What is the answer?",
created_at: "2015-09-14T14:59:39.599Z",
updated_at: "2015-09-14T14:59:39.599Z"
},
{
id: 2,
survey_response_id: 1,
mini_post_question_id: 27,
answer: "What is the answer?",
created_at: "2015-09-15T20:58:32.030Z",
updated_at: "2015-09-15T20:58:32.030Z"
}
]
}
}
Here is my SurveyResponseSerializer:
class SurveyResponseSerializer < ActiveModel::Serializer
attributes :id, :survey_invite_id, :name, :title, :published, :created_at, :updated_at
has_many :question_answers
def created_at
object.created_at.in_time_zone("Eastern Time (US & Canada)").strftime("%l:%M%p %b %w, %Y")
end
def updated_at
object.updated_at.in_time_zone("Eastern Time (US & Canada)").strftime("%l:%M%p %b %w, %Y")
end
end
Basically, I want the question_answers key value to be a hash of QuestionAnswer objects where the keys are the question id QuestionAnswer.question_id. I've looked through the docs and haven't turned up any examples of what I'm trying to do.
Update with solution:
So I came up with a solution that works for what I need, but I'd still like to know if there is a better way to do what I need. I wrote a method to generate the structure I need.
def question_answers
hash = {}
object.question_answers.each do |answer|
hash[answer.mini_post_question_id] = answer
end
hash
end
That yields the following:
question_answers: {
20: {
id: 1,
survey_response_id: 1,
mini_post_question_id: 20,
answer: "Test?",
created_at: "2015-09-14T14:59:39.599Z",
updated_at: "2015-09-14T14:59:39.599Z"
},
27: {
id: 2,
survey_response_id: 1,
mini_post_question_id: 27,
answer: "Blarg!",
created_at: "2015-09-15T20:58:32.030Z",
updated_at: "2015-09-15T20:58:32.030Z"
}
}
I don't think ActiveModelSerializers has an idiomatic way to present a has_many association as a hash, but you can do it with a one-liner:
def question_answers
object.question_answers.index_by(&:id)
end
I am a beginner, so this question maybe very elementary. I appreciate any help. I have three models - one Metal that does a query of a database to get a price and another QuoteMetal which is nested through has_many and accepts_nested_attributes_for in Lead. I need the results of the query conducted through the Metal model to be available in the lead collection so I can display the results in the view.
My question: how do I get those query results (specifically the price attribute) to be in the Lead instance variable. Of if not the lead instance variable - what is the best way to display the results. Below is my code.
class LeadsController < ApplicationController
def index
#lead = Lead.new
#quote_metal = #lead.quote_metals.build
#quote_melee = #lead.quote_melees.build
#quote_diamond = #lead.quote_diamonds.build
end
def create
#raise params.inspect
#lead = Lead.new(lead_params)
#qm = #lead.quote_metals.map { |f| Metal.calculate_metal(f).first}
##lead.quote_metals.each do |f|
# f[:price] = #qm[:price].to_i
#end
#lead = Lead.create!(lead_params)
end
def show
end
private
def lead_params
params.require(:lead).permit([:name, :email, :phone, :zip, :note, :method,
quote_metals_attributes: [:id, :metal, :weight, :unit, :price],
quote_melees_attributes: [:shape, :quality, :quantity, :totalweight, :size],
quote_diamonds_attributes: [:shape, :size, :color, :clarity]
])
end
end
Metal Model:
class Metal < ActiveRecord::Base
enum metal: {platinum: 1, palladium: 2, "10_karat_gold": 3, "14_karat_gold": 4,
"18_karat_gold": 5, "22_karat_gold": 6, silver: 7}
enum unit: {pennyweight: 1, grams: 2, ounce: 3, pound: 4}
attr_accessor :weight
#Validations
validates :metal, :unit, :weight, presence: true
scope :calculate_metal, ->(quote_metal) {
where(metal: QuoteMetal.metals[quote_metal.metal],
unit: QuoteMetal.units[quote_metal.unit])
}
scope :multiple, ->(quote_metal){
}
end
Create.html.erb
<pre>
<%= #qm.inspect %>
<br>
<%= #lead.quote_metals.inspect %>
<br>
<%= #qm.inspect %>
<br>
<%= #qm2.inspect %>
</pre>
Output:
[#<Metal id: 11, metal: 2, unit: 2, price: #<BigDecimal:7ff01dac4be8,'0.1367E2',18(18)>, created_at: "2015-05-26 10:36:38", updated_at: nil, weight: nil>, #<Metal id: 11, metal: 2, unit: 2, price: #<BigDecimal:7ff01da96450,'0.1367E2',18(18)>, created_at: "2015-05-26 10:36:38", updated_at: nil, weight: nil>]
#<ActiveRecord::Associations::CollectionProxy [#<QuoteMetal id: 231, lead_id: 176, metal: 2, unit: 2, price: nil, weight: #<BigDecimal:7ff01cc71320,'0.1E1',9(18)>, quote: nil, created_at: "2015-07-14 18:26:46", updated_at: "2015-07-14 18:26:46">, #<QuoteMetal id: 232, lead_id: 176, metal: 2, unit: 2, price: nil, weight: #<BigDecimal:7ff01ca49d90,'0.2E1',9(18)>, quote: nil, created_at: "2015-07-14 18:26:46", updated_at: "2015-07-14 18:26:46">]>
[#<Metal id: 11, metal: 2, unit: 2, price: #<BigDecimal:7ff01dac4be8,'0.1367E2',18(18)>, created_at: "2015-05-26 10:36:38", updated_at: nil, weight: nil>, #<Metal id: 11, metal: 2, unit: 2, price: #<BigDecimal:7ff01da96450,'0.1367E2',18(18)>, created_at: "2015-05-26 10:36:38", updated_at: nil, weight: nil>]
[[#<Lead id: nil, name:..., note: "asdf", created_at: nil, updated_at: nil>, #<Metal id: 11, metal: 2, unit: 2, price: #<BigDecimal:7ff01dac4be8,'0.1367E2',18(18)>, created_at: "2015-05-26 10:36:38", updated_at: nil, weight: nil>]]
Thank you.
Code
In my image model:
has_attached_file :pic
before_post_process :rename_pic
before_save ->{ p 'before_save ----------------' }
after_post_process ->{ p 'after_post_process --------------' }
def rename_pic
p 'en imagen'
p self
p 'en imagen'
end
In service that has many images:
# don't use accepts_nested_attributes_for
before_save :create_images
attr_accessor :images_attributes
def create_images
# images_attributes example value: { "0"=> {img_attrs}, "1" => {img_attrs1} }
images_attributes.all? do |k, image_attrs|
if image_attrs.delete(:_destroy) == "false"
p 'asd'
image = Image.new image_attrs.merge(service_id: id)
p image.service
p image.service_id
image.save
end
end
end
This is the output I get:
"asd"
"en imagen"
#<Image id: nil, service_id: nil, pic_file_name: "Screen_Shot_2013-04-07_at_5.18.03_PM.png", pic_content_type: "image/png", pic_file_size: 16041, pic_updated_at: "2013-07-30 22:58:46", created_at: nil, updated_at: nil, user_id: nil>
"en imagen"
G"after_post_process --------------"
#<Service id: 427, event_id: nil, min_capacity: nil, max_capacity: nil, price: #<BigDecimal:7fb6e9d73d48,'0.0',9(18)>, image_path: nil, name: "Super Franks", desc: "zxc", created_at: "2013-05-12 19:01:54", updated_at: "2013-07-30 19:32:48", address: "pasadena", longitude: 77.225, latitude: 28.6353, gmaps: true, city: "san francisco", state: "california", country_id: "472", tags: "Banquet", created_by: 22, avg_rating: #<BigDecimal:7fb6efdbcf10,'0.0',9(18)>, views: 27, zip_code: "", address2: "", price_unit: "", category_id: 3, featured: true, publish: true, slug: "banquet-super-franks", discount: nil, currency_code: "USD", video_url: "http://www.youtube.com/watch?v=A3pIrBZQJvE", short_description: "">
427
"before_save ----------------"
Problem
When calling
image = Image.new image_attrs.merge(service_id: id)
Paperclips seems to start processing, and then set service_id.
So when I try to use service inside rename_pic service is nil.
Any ideas on how to handle this?
This solved my problem, I changed:
before_post_process :rename_pic
to:
before_create :rename_pic
and this is rename_pic, for the record:
def rename_pic
extension = File.extname(pic_file_name).downcase
self.pic.instance_write :file_name,
"#{service.hyphenated_for_seo}#{extension}"
end
where service has_many images, and image belongs_to service.
Be carefull with the fix of #juanpastas, because if you change before_post_process to before_create, it will only run when you create your image, and not when you update it. To have the callback still run on update, do this:
class YourImage
has_attached_file :pic
# use both callbacks
before_create :rename_pic
before_post_process :rename_pic
def rename_pic
# assotiated_object is the association used to get pic_file_name
return if self.assotiated_object.nil?
extension = File.extname(pic_file_name).downcase
self.pic.instance_write :file_name,
"#{service.hyphenated_for_seo}#{extension}"
end
end
I'm trying to use Rails(2)'s to_json model serializing mechanism to emit some data from associated models. As my guide I'm referencing the following essentially identical documentation URLs:
http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html
http://apidock.com/rails/ActiveRecord/Serialization/to_json
Here is some of the relevant model code:
class WorkEffortAssignment < ActiveRecord::Base
belongs_to :work_effort
belongs_to :assigned_to, :polymorphic => true
belongs_to :assigned_by, :polymorphic => true
Here is the controller code, I'm just trying to dump some JSON for initial testing purposes:
def dump_work_effort_assignments
WorkEffort.include_root_in_json = false
all_assignments = WorkEffortAssignment.all
options = {:include => [:work_effort, :assigned_to, :assigned_by], :only => [:work_effort_id, :assigned_to_id, :assigned_by_id]}
ext_json = "{data:#{WorkEffortAssignment.all.to_json(options)}}"
render :inline => ext_json
end
Here's the first record of Json data with empty hashes for work_effort, assigned_to and assigned_by:
{data:[{"assigned_to":{},"work_effort_id":"9","assigned_to_id":3,"assigned_by":{},"work_effort":{},"assigned_by_id":3}, //etcetera
But below is my console session showing the associations that I'd like to represent in my Json. So what am I doing wrong in my controller when trying to specify the include option for to_json, such that I can easily send associated model data back to the browser. Thanks in advance
>> assignment = WorkEffortAssignment.first
=> #<WorkEffortAssignment id: 1, assigned_at: nil, assigned_from: nil, assigned_
thru: nil, unassigned_at: nil, assigned_to_id: 3, assigned_to_type: "Party", ass
igned_by_id: 3, assigned_by_type: "Party", created_at: nil, updated_at: nil, wor
k_effort_id: "9">
>> assignment.work_effort
=> #<WorkEffort id: 9, description: "Software Architecture Document", type: nil,
started_at: nil, finished_at: nil, projected_completion_time: nil, actual_compl
etion_time: nil, created_at: "2011-08-18 13:39:30", updated_at: "2011-08-25 13:3
9:30", facility_id: nil, facility_type: nil, work_effort_record_id: nil, work_ef
fort_record_type: nil, projected_cost_id: nil, actual_cost_id: nil, parent_id: n
il, lft: 1, rgt: 2>
>> assignment.assigned_to
=> #<Party id: 3, description: "George Jempty", business_party_id: 2, business_p
arty_type: "Individual", list_view_image_id: nil, enterprise_identifier: nil, cr
eated_at: "2011-08-29 14:21:41", updated_at: "2011-08-29 14:21:41">
>> assignment.assigned_by
=> #<Party id: 3, description: "George Jempty", business_party_id: 2, business_p
arty_type: "Individual", list_view_image_id: nil, enterprise_identifier: nil, cr
eated_at: "2011-08-29 14:21:41", updated_at: "2011-08-29 14:21:41">
The :only specifier you have there is throwing it off. The following will include the child-objects:
def dump_work_effort_assignments
WorkEffort.include_root_in_json = false
all_assignments = WorkEffortAssignment.all
options = {:include => [:work_effort, :assigned_to, :assigned_by]}
ext_json = "{data:#{WorkEffortAssignment.all.to_json(options)}}"
render :inline => ext_json
end
...but will not filter out the attributes of the parent. If you want to do that, it may be simpler to just build a hash and convert it to json:
def dump_work_effort_assignments
data = WorkEffortAssignment.all.map {|wea| {
:work_effort => wea.work_effort,
:assigned_to => wea.assigned_to,
:assigned_by => wea.assigned_by
}}
ext_json = "{data:#{data.to_json}}"
render :inline => ext_json
end