I dont know what I did or what's changed because this was working before.
I have a Model Entry and I use Paperclip to attach a file document to it. Now, for some weird reason I keep getting a
Errno::ENOENT in EntriesController#create
No such file or directory - /var/www/capsf-web/public/assets/entries/test.pdf
I'm guessing that before Paperclip has saved the file to the directory I'm already trying to encode the file. Here's what Entry looks like. I'm using ElasticSearch's attachment mapper which is why I Encode it.
class Entry < ActiveRecord::Base
include Tire::Model::Search
include Tire::Model::Callbacks
has_and_belongs_to_many :categories
has_and_belongs_to_many :subcategories
belongs_to :entry_type
has_attached_file :document,
:url => "/assets/entries/:basename.:extension",
:path => ":rails_root/public/assets/entries/:basename.:extension"
before_post_process :image?
validates_presence_of :entry_type
attr_accessible :description, :title, :url, :category_ids, :subcategory_ids, :entry_type_id, :document
mapping do
indexes :title
indexes :description
indexes :categories do
indexes :name
end
indexes :subcategories do
indexes :name
end
indexes :entry_type
indexes :document, :type => 'attachment'
end
def to_indexed_json
#to_json( methods: [:category_name, :subcategory_name, :entry_type_name])
{
:title => title,
:description => description,
:categories => categories.map { |c| { :name => c.name}},
:subcategories => subcategories.map { |s| { :name => s.name}},
:entry_type => entry_type_name,
:document => attachment
}.to_json
end
def image?
!(document_content_type =~ /^image.*/).nil?
end
def attachment
if document.present?
path_to_document = Rails.public_path+"/assets/entries/#{document_file_name}"
Base64.encode64(open(path_to_document) { |pdf| pdf.read})
#If I comment out the line above everything works just fine.
end
end
end
Related
My models are as follows:
class Project < ActiveRecord::Base
has_many :project_images
accepts_nested_attributes_for :project_images
end
class ProjectImage < ActiveRecord::Base
belongs_to :project
mount_uploader :image, ImageUploader
end
Here's the activeadmin file:
ActiveAdmin.register Project do
remove_filter :projects_sectors
permit_params :title, :info, :case_study, project_images_attributes: [:image, :cover]
index do
column :title
actions
end
form :html => { :enctype => "multipart/form-data" } do |f|
f.inputs "Project" do
f.input :title
f.input :info
f.input :case_study, :as => :file
end
f.inputs "Images" do
f.has_many :project_images, :allow_destroy => true, :heading => false, :new_record => true do |img_f|
img_f.input :image, :as => :file , :hint => f.template.image_tag(img_f.object.image)
img_f.input :cover
end
end
f.actions
end
end
The problem is that when i simply edit a project and click on update project, it simply duplicates all the records that exist for relationship at that point. Eg. if i have 2 images under 1 project, after changing say, the project title, i will end up with 4 images.
Hope it's clear what the issue is. Would appreciate greatly if anybody could give me a litle help.
Thanks a lot in advance.
You have to permit the id of the images: project_images_attributes: [:id, :image, :cover]
If you don't permit the id, it will be null in the action, and rails thinks it's a new record and save it.
I think this is the same problem as this one discussed on the CarrierWave wiki. Instead of generating input fields for existing images, generate an image tag and a 'remove?' option. If you generate an input field for them, then you'll end up with duplicate results.
ActiveAdmin.register Project do
controller do
def apply_filtering(chain)
super(chain).distinct
end
end
# your code
end
i have two models :
class Article < ActiveRecord::Base
belongs_to :league
has_many :photos, :dependent => :destroy
attr_accessible :content, :lead, :title, :title_slug,
:created_at, :updated_at,
:league_id, :photos_attributes
accepts_nested_attributes_for :photos
validates :content, :league, :presence => true
validates :lead , :length => {maximum: 1000}, :presence => true
validates :title ,:length => {maximum: 200}, :presence => true
validates_associated :photos
and
class Photo < ActiveRecord::Base
belongs_to :article
attr_accessible :photo
validates :photo, presence: true
has_attached_file :photo , :styles => { :medium => '440x312#', :small => '209x105!'}
end
My ArticlesController is
...
def new
#article = Article.new
#article.photos.build
end
def create
#article = Article.new(params[:article])
if #article.save
redirect_to([:admin,#article])
else
render 'new'
end
end
...
form view is :
= form_for([:admin,#article] , :html => {:multipart => true}) do |f|
- if #article.errors.any?
= render 'errors'
= f.fields_for :photos do |builder|
= builder.label :photo
= builder.file_field :photo
...
i have some question about it :
1) I dont want to save an article without empty photo but now when i dont choose a file my article saves.
2) When i have some errors on article's fields and render 'new' ,my photo field dissapear , what is the rails way to resolve it.
3) in the future i want to add another model: photo_type and assosciate it with photo. Each article will have two photo fields , each with own type (for example: small , big) . I wonder how to render that fields and what can i do to save article with two photos with different types.
Answer for 1: Use validates_associated :photos. Documentation
Answer for 2: I guess that is an file attachment field. For that, this is generally done by setting up a hidden cache field and by using some callbacks. MountUploader uses the same principle.
Answer for 3: Little skeptical, but I guess something will work along this way:
In your Article model, have two associations with Photo as:
has_one :small_photo, :class_name => "Photo"
has_one :big_photo, :class_name => "Photo"
This will enable you to have two sub-form fields present for both types while opening up the form for Article.
Hope it helps. Do comment if last one can work for you in this way. It looks like the good deal to me :)
I wrote many simple rake files to import txt files to my mysql.
Everything work perfectly except one model.
I have no errors so I don't know what happening.
The rake imports the first line only. Everything else don't!
The txt is on UTF8 encoding, by the way.
Could be the counter_cache of recipe's associations?
RAILS 3.1
Model:
class Recipe < ActiveRecord::Base
belongs_to :chef, :counter_cache => true
belongs_to :category, :counter_cache => true
belongs_to :cuisine, :counter_cache => true
belongs_to :festivity, :counter_cache => true
belongs_to :daily, :counter_cache => true
after_update :update_counter
# Setup accessible (or protected) attributes for your model
attr_accessible :name,
:slug,
:description,
:ingredients,
:steps,
:...
:status_id,
:created_at,
:updated_at
STATUS = { 'Não publicada' => 0, 'Publicada' => 1, 'Invisível' => 4 }
def status
STATUS.invert[status_id]
end
private
def update_counter
if category_id_changed?
Category.increment_counter(:recipes_count, category_id)
Category.decrement_counter(:recipes_count, category_id_was)
end
if cuisine_id_changed?
Cuisine.increment_counter(:recipes_count, cuisine_id)
Cuisine.decrement_counter(:recipes_count, cuisine_id_was)
end
if festivity_id_changed?
Festivity.increment_counter(:recipes_count, festivity_id)
Festivity.decrement_counter(:recipes_count, festivity_id_was)
end
if daily_id_changed?
Daily.increment_counter(:recipes_count, daily_id)
Daily.decrement_counter(:recipes_count, daily_id_was)
end
end
end
RAKE file:
namespace :db do
desc "import data from files to database"
task :import_recipe => :environment do
puts "Importing Recipe..."
# recipe.txt
File.open("lib/tasks/data/recipe.txt", "r").each do |line|
id, name, slug, description, ingredients, steps, other_tips, cook_time, recipe_yield, diet, light, lactose_intolerance, vegetarian, microwave, video_url, chef_id, category_id, cuisine_id, festivity_id, daily_id, likes_count, rating, ratings_count, views_count, comments_count, status_id, created_at, updated_at = line.strip.split("\t")
d = Recipe.new(
:id => id,
:name => name,
:slug => slug,
:description => description,
:ingredients => ingredients,
:steps => steps,
:...
:status_id => status_id,
:created_at => created_at,
:updated_at => updated_at
)
d.save!
end
puts "=========== > FINISHED!"
end
end
In reference to the Query DSL Explained Tutorial Slides 14-15
How do I flatten Nested Objects?
I have a Model named Entry and another named Category and they share a HABTM association.
Everything is currently working and the search results seem to be correct, but I don't know if my mapping is correct. The tutorial says that when you flatten objects the Document will look like this :
{
tweet => "Perl is GREAT!",
posted => "2011-08-15",
user.name => "Clinton Gormley",
user.email => "drtech#cpan.org",
tags => ["perl","opinion"],
posts => 2,
}
with the Object user being flattened. When I look at the source of my JSON document it looks like this:
{
"title":"First",
"description":"first test",
"categories":
{"categories_name":"CAP and Using the CAP website"},
"attachment":"VEVTVCE=\n",
"published":true
}
So, I'm assuming that its supposed to say categories.categories_name but I don't know how to specify that or if that's even necessary. Here's some Model code:
class Entry < ActiveRecord::Base
include Tire::Model::Search
include Tire::Model::Callbacks
has_and_belongs_to_many :categories
mount_uploader :doc, EntryDocUploader
tire.mapping do
indexes :title
indexes :description
indexes :categories do
indexes :categories_name, type: 'string', index: 'not_analyzed'
end
indexes :attachment, :type => 'attachment',
:fields => {
:title => { :store => 'yes' },
:attachment => { :term_vector => 'with_positions_offsets', :store => 'yes' }
}
end
def to_indexed_json
{
:title => title,
:description => description,
:categories => {:categories_name => cats}, #categories.map { |c| { :categories_name => c.name}}.to_sentence,
:attachment => attachment,
}.to_json
end
def self.search(params)
tire.search(load: true) do
query { string params[:query], default_operator: "AND" } if params[:query].present?
filter :term, :published => "true"
end
end
def cats
categories.map(&:name).to_sentence
end
end
Having a tough time wrapping my head around Tire's syntax, that of Elasticsearch and how they map together.
I have successfully indexed PDFs in a Rails app via Tire. But I need to break the full reports down into individual pages so queries can be more granular. It's easy enough to split the PDFs into individual pages and add them to a Page model that belongs_to the full Report model. What I'm struggling with is how to set up the mapping and where?!? I'd like to take advantage of Elasticsearch's Parent Field mapping so I can realize this ultimate goal.
Hoping someone can set me straight.
Report model (this is working for me if I index an entire PDF as the :attachment):
class Report < ActiveRecord::Base
include Tire::Model::Search
include Tire::Model::Callbacks
has_many :pages, :dependent => :destroy
attr_accessible :filename, :title
tire.mapping do
indexes :id, :type =>'integer'
indexes :title
indexes :attachment, :type => 'attachment',
:fields => {
:content_type => { :store => 'yes' },
:author => { :store => 'yes' },
:title => { :store => 'yes' },
:attachment => { :term_vector => 'with_positions_offsets', :store => 'yes' },
:date => { :store => 'yes' }
}
end
...
end
Page model:
class Page < ActiveRecord::Base
include Tire::Model::Search
include Tire::Model::Callbacks
belongs_to :report
attr_accessible :filename, :page_num,
tire.mapping do
indexes :id, :type => 'integer'
indexes :page_num, :type => 'integer'
indexes :report_id, :type => 'integer' ###<== how is this associated with _parent?
indexes :attachment, :type => 'attachment',
:fields => {
...
...
end
end