lets say I have 2 models like News, Clients.
Using paperclip's default options, I need to create for each of them additional columns like (photo_file_name .....)
but I just want to create different model, let's say Asset
asset.rb
belongs_to :client
has_attached_file :photo, :styles => {:small => "300x300>"}
client.rb
has_one :asset, :dependent => :destroy
accepts_nested_attributes_for :asset
clients_controller.rb
def new
#client = Client.new
#client.build_asset
end
_form.html.erb
<%= form_for #client, :html => {:multipart => true} do |f| %>
<%= f.fields_for :asset do |asset| %>
<%= asset.label :photo %><br/>
<%= asset.file_field :photo %>
<% end %>
<% end %>
For now this is working, but how to show it in show view ? i'm doing this:
<%= image_tag #client.url(:small) %>
I know this is not correct, because #client.asset does not have url column,
how to do it ?
Just like Mikhail Nikalyukin said, you should call
<%= image_tag #client.photo.url(:small) %>
instead of
<%= image_tag #client.url(:small) %>
Related
I'm using Dragonfly to upload images to model Photo which is associeted to others models. For example:
MODEL: Post
class Post < ActiveRecord::Base
has_many :photos, dependent: :destroy
accepts_nested_attributes_for :photos, allow_destroy: true,
reject_if: lambda {|attributes| attributes['image'].blank?}
MODEL Photo
class Photo < ActiveRecord::Base
extend Dragonfly::Model::Validations
dragonfly_accessor :image
dragonfly_accessor :image do
after_assign { |img| img.encode!('jpg', '-quality 80') }
end
It works fine, even when I change the input to upload multiple files at the same time
FORM VIEW:
works:
<%= f.fields_for :photos do |photo| %>
<%= photo.file_field :image, class: "form-control" %>
<% end%>
doesn't works:
<%= f.fields_for :photos do |photo| %>
<%= photo.file_field :image, class: "form-control", multiple: true, name: 'photo[image]' %>
<% end%>
How can I upload multiple files at the same time to associeted model?
Thanks!
UPDATE:
I tried:
controller. Create action
#post = Post.new(seminovo_params)
params[:photos]['image'].each do |a|
#photo = #post.photos.create!(:image => a)
end
View
<%= f.fields_for :photos, #post.photos.new do |photo| %>
<%= photo.file_field :image, :multiple => true, name: "photos[image][]" %>
Yo need to define params and get those params this way
Your new method should contain
def new
# Your new form object
#photo = #post.photos.build
end
In controller method use this
params[:photos]['avatar'].each do |a|
#photo = #post.photos.create!(:image => a)
end
Your form should look like,
<%= form_for(#post, :html => { :multipart => true }) do |f| %>
<%= f.fields_for :photos do |p| %>
<div class="field">
<%= p.label :image %><br>
<%= p.file_field :image, :multiple => true, name: "photos[image][]" %>
</div>
<% end %>
I have a project model that has_many :tasks. I added a nested resource in rails 3.1 and try now with the nested_form gem to be able to add/delete tasks when editing a project.
I used nested_form before in another Rails3 application and it worked fine, but now my fields_for part does not render anything.
Here is my code:
#project.rb
class Project < ActiveRecord::Base
attr_accessible :nr, :name, :client_id, :project_status_id, :hidden, :active, :description, :tasks_attributes
has_many :tasks, :dependent => :destroy
accepts_nested_attributes_for :tasks, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
#task.rb
class Task < ActiveRecord::Base
belongs_to :project
end
#views/projects/_form.html.erb
<%= simple_nested_form_for #project do |form| %>
<%= form.input :nr, :label => 'Nr' %>
<%= form.input :name, :label => 'Name' %>
<%= form.association :client, :collection => Client.all(:order => 'name'), :prompt => "Choose a Client" %>
<%= form.input :description, :label => 'Description' %>
<%= form.input :active, :label => 'Active' %>
<%= form.input :hidden, :label => 'Hidden' %>
<div class="task_fields">
<%= form.fields_for :tasks do |task_form| %>
<%= task_form.input :name %>
<%= task_form.input :description %>
<%= task_form.input :deadline %>
<%= task_form.link_to_remove "Remove this task" %>
<p><%= form.link_to_add "Add a task", :tasks %></p>
<% end %>
</div>
<div class="actions">
<%= form.button :submit %>
</div>
<% end %>
and in my routes:
resources :posts do
resources :comments
end
but when I visit the page in my browser the
<div class="task_fields"></div>
is rendered empty. no fields_for and whatsoever. the nested_form.js is loaded and I point in my GEMFILE to gem "nested_form", :git => 'https://github.com/fxposter/nested_form.git', as I read somewhere I need to do this in order to get simple_form support. I tried also to change simple_nested_form_for to only nested_form_for with no effect.
Any help higly appreciated
In projects#new, you have to initialize at least one task otherwise your fields_for part won't display anything.
# projects_controller.rb
def new
#project = Project.new
#project.tasks.new
end
If you want more than one task:
n.times { #project.tasks.new } # replace n with the number of tasks needed
I am using the nested form gem and i add products dynamically to the form. When i do click "add", another product resource appears but on creation it ERASES the former ones from being created entirely. This is how the scenario goes:
Fill in Location
Choose Date
Fill in Product ( one is already on form)
Add 5 more products (Products 2, 3, 4, 5)
Fill in All Products
"click" Create
Created Product 5
This is how my nested form looks:
<%= nested_form_for #location, :url => products_path(#product) do |f| %>
<%= f.label :business %>
<%= f.text_field :business %>
<%= f.label :address %>
<%= f.text_field :address %>
<%= f.fields_for :product_dates, :url => products_path(#product) do |d| %>
<%= d.label :date %>
<%= d.date_select :date %>
<%= d.fields_for :products, :url => products_path(#product) do |p| %>
<%= p.text_field :name %>
<%= p.text_field :price %>
<%= p.text_field :tag_list %>
<%= p.link_to_remove "Remove Product" %>
<% end %>
<%= d.link_to_add "Add", :products %>
<% end %>
<%= f.submit "Finish" %>
<% end %>
Controller:
class ProductsController < ApplicationController
def new
#location = Location.new
#product = Product.new
product_date = #location.product_dates.build
product_date.products.build
end
def create
#location = Location.create(params[:location])
if #location.save
flash[:notice] = "Products Created."
redirect_to :action => 'index'
else
render :action => 'new'
end
end
Models:
class User < ActiveRecord::Base
devise
attr_accessible :email, :password, :password_confirmation, :remember_me
has_many :products, :dependent => :destroy
end
class Location < ActiveRecord::Base
attr_accessible :address, :business, :product_dates_attributes
has_many :products
has_many :product_dates
accepts_nested_attributes_for :product_dates
end
class ProductDate < ActiveRecord::Base
attr_accessible :date, :products_attributes
belongs_to :location
belongs_to :user
has_many :products
accepts_nested_attributes_for :products
end
class Product < ActiveRecord::Base
attr_accessible :name, :price, :tag_list
belongs_to :user
belongs_to :location
belongs_to :product_date
end
Any Suggestions?
First of all remove the url_for declarations on the fields_for declarations so you get
<%= nested_form_for #location, :url => products_path(#product) do |f| %>
<%= f.label :business %>
<%= f.text_field :business %>
<%= f.label :address %>
<%= f.text_field :address %>
<%= f.fields_for :product_dates do |d| %>
<%= d.label :date %>
<%= d.date_select :date %>
<%= d.fields_for :products do |p| %>
<%= p.text_field :name %>
<%= p.text_field :price %>
<%= p.text_field :tag_list %>
<%= p.link_to_remove "Remove Product" %>
<% end %>
<%= d.link_to_add "Add", :products %>
<% end %>
<%= f.submit "Finish" %>
<% end %>
What is really confusing is your whole routing and params approach. It's just not right. You have a form_for #location with a :url products_path(#product) This will right royally cause issues with the params that are sent back and there in lies the problem.
Stick with routing to location controller not the products controller by removing the products_path(#product) form your nested_form_for declaration and you will find that you will have all the necessary records saved but you will most likely need to change the redirect_to declaration in the locations_controller create action and the same for the update_action.
But why use the products controller at all when you are dealing with a location? Again this just isn't natural or intuitive.
One last thing. Your remove links won't work as you have not added the necessary :dependent => :destroy declaration to the has_many declarations and you are also missing the :reject_if procs and the :allow_destroy => true declarations on the accepts_nested_attributes declarations.
Can I strongly suggest that you
1) Use either the locations controller or the products controller not both
I mean link to get to this form link_to the locations controller and set everything up there or use form_for #product rather than #location and handle everything in the products controller
2) watch the railscasts that this gem is based on very closely
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2
3) Spend some time learning about how rails form view helpers arrange for the params hash to be organised in the controllers actions. In your case, have a close look at your log file for the parameters that come into the create action as things currently stand.
You will most likely see that the params are not nested as you would exect them to be which is why the nested attributes declaration is not behaving as expected
I am trying to create a nested form using formtastic. I've included my code below but am running into some problems that I've also listed below. Any suggestions? Thanks.
# Home model
class Home < ActiveRecord::Base
has_many :home_members
accepts_nested_attributes_for :home_members, :reject_if => :all_blank, :update_only => true, :allow_destroy => true
end
# Form builder in members/new.html.erb
<%= semantic_form_for #home, :url => home_members_path(#home), :html => { :method => :post }, :remote => true do |f| %>
<%= f.inputs do %>
<%= f.semantic_fields_for :home_members do |h| %>
<%= h.input :name %>
<%= h.input :email %>
<%= h.input :birthday, :as => :string %>
<% end %>
<% end %>
# members_controller's new method; #home is set in a before filter
def new
2.times{ #home.home_members.build }
end
A default user is created when a Home is saved. How do I have the form display only the newly created records and not the existing one?
If #1 isn't possible, how do I make the existing record update? I have update_only set on the accepts_nested_attributes_for, but a new record is still created.
I am doing 2.times{ #home.home_members.build } in the controller action. When I print the size of #home.home_members I get 3 (one already exists) as expected. Why is the form only displaying 2 sets of inputs, one being populated with the existing home_member data?
well to answer question 1) show only the newly created objects
# Form builder in members/new.html.erb
<%= semantic_form_for #home, :url => home_members_path(#home), :html => { :method => :post }, :remote => true do |f| %>
<%= f.inputs do %>
<%= f.semantic_fields_for :home_members do |h| %>
<% if h.object.new_record? %>
<%= h.input :name %>
<%= h.input :email %>
<%= h.input :birthday, :as => :string %>
<% end %>
<% end %>
<% end %>
I've used cocoon with success in the past. https://github.com/nathanvda/formtastic-cocoon
I used paper clip in my web application, I use this to make a new product:
<% semantic_form_for #product do |f| %>
<% f.inputs do %>
<%= f.input :title %>
<%= f.input :price %>
<%= f.file_field :photo %>
<%= f.input :category , :include_blank => false %>
<% end %>
<%= f.buttons %>
<% end %>
And this to show product:
<% semantic_form_for #product do |f| %>
<%= image_tag #product.photo.url%>
<% f.inputs do %>
<%= f.input :title %>
<%= f.input :price %>
<%= f.file_field :photo %>
<%= f.input :category , :include_blank => false %>
<% end %>
<%= f.buttons %>
<% end %>
And his is my product.rb:
class Product < ActiveRecord::Base
validates_presence_of :title, :price
validates_numericality_of :price
validates_uniqueness_of :title
has_attached_file :photo
attr_accessible :name, :category_id, :price, :title, :photo
belongs_to :category
has_many :order_items
end
But after I upload the photo, it show my image path like this :
http://localhost:3000/photos/original/missing.png
It seems that it can't upload the photo with this error:
No route matches "/photos/original/missing.png" with
{:method=>:get}
I am not sure what semantic_form_for is, but with regular form_for, you have to explicitly say it's a multipart form.
<% form_for(#thing, :html => {:multipart => true}) do |f| %>
....
If you don't do this, the contents of your file upload fields won't be transmitted to the server. It's a HTML thing ;)
I think you paste the image into public/images folder in your rails application.And give the path like in your browser "/images/missing.png".
And your index will be