Multiple File Uploads With Paperclip - ruby-on-rails-3

I watched http://www.emersonlackey.com/article/rails-paperclip-multiple-file-uploads and tried to apply it to my project. This is what I have:
property.rb
class Property < ActiveRecord::Base
attr_accessible :avatar, :agent_id, :address, :neighborhood, :price, :photos
belongs_to :agent
has_attached_file :avatar, :styles => { :large => "1500x1500>", :thumb => "100x100>" }
has_many :photos
accepts_nested_attributes_for :photos, :allow_destroy => true
end
photo.rb
class Photo < ActiveRecord::Base
attr_accessible :avatar, :property_id
belongs_to :property
has_attached_file :avatar, :styles => { :large => "1500x1500>"}
end
properties_controller.rb
def new
#property = Property.new
5.times { #property.photos.build }
end
def edit
#property = Property.find(params[:id])
5.times { #property.photos.build }
end
new.html.erb
<h1>Create New Listing</h1>
<%= form_for(:property, :url => {:action => 'create'}, :html => {:multipart => true})
do|f| %>
<%= f.file_field :avatar %>
<% f.fields_for :photo do |f| %>
<%= f.file_field :avatar, {:multiple => true} %>
<% end %>
<table>
<tr>
<th>Agent_ID</th>
<td><%= f.text_field(:agent_id) %></td>
</tr>
<tr>
<th>Address</th>
<td><%= f.text_field(:address) %></td>
</tr>
<tr>
<th>Neighborhood</th>
<td><%= f.text_field(:neighborhood) %></td>
</tr>
<tr>
<th>Price</th>
<td><%= f.text_field(:price) %></td>
</tr>
</table>
<%= submit_tag("Create Listing") %>
<%= link_to 'Return to list', 'list' %>
I was unable to get 5 different file fields as emerson does in his video. Does anyone know what is wrong with my code? I'm guessing that the problem is in the form page.
Any help on how to make it work is greatly appreciated.
Thanks

should:
<% f.fields_for :photo do |f| %>
not be:
<% f.fields_for :photos do |f| %>
Also I don't know if rails and paperclip support multiple on a file field out of the box: http://initializd.com/blog/2013/3/upload-multiple-files-with-html5-rails-mongoid-paperclip-and-google-cloud-storage

Related

Validation error reset my values why

I have a modal "A" and it has a line_item model "B" with has_many association. That means B is associated with A. I have validation for B in A's model that
validates_presence_f :B
validates_associated :B
now in my form i have used "fields_for" to save values of B, if i submit a blank form than
validation fails and displays an error message for presence of line item B, but the fields of B's disabled, i have to reshow their fields. Can any one predict why this is happening.
here is my model :
Model A:
class Purchase < ActiveRecord::Base
has_many :purchase_line_items
accepts_nested_attributes_for :purchase_line_items, :reject_if => lambda {|a| a[:account_id].blank? }, :allow_destroy =>true
validates_presence_of :purchase_line_items
validates_associated :purchase_line_items
end
and Model B:
class PurchaseLineItem < ActiveRecord::Base
belongs_to :purchase
end
in my controller:
class PurchasesController < ApplicationController
def new
#purchase = Purchase.new
#purchase.purchase_line_items.build
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #purchase }
end
end
end
and in last my views :
<%= form_for #purchase, :html => {:multipart => true} do |f| %>
<%= render 'shared/form_error', :object => #purchase %>
<% #purchase.purchase_line_items.each_with_index do |purchase_line_item, index| %>
<%= render "purchase_line_items", :purchase_line_item => purchase_line_item, :index => index %>
<% end %>
<%= f.submit %>
<% end %>
And in line item partial i have:
<tr id="row<%= index %>" valign="top" >
<%= hidden_field_tag "purchase[purchase_line_items_attributes][#{index}][id]",purchase_line_item.id%>
<td valign="top">
<%= select_tag "purchase[purchase_line_items_attributes][#{index}][account_id]", options_from_collection_for_select(#to_accounts, :id, :name,:selected => purchase_line_item.account_id ), :include_blank => true, :class=>"full" %>
</td>
<td><%= text_field_tag "purchase[purchase_line_items_attributes][#{index}][amount]", purchase_line_item.amount, :class => 'full', :id => 'total', :readonly => 'readonly', :size => 5%></td>
<td><%= link_to image_tag("/images/black_icon/ic_cancel.png"),{:action => :remove_line_item, :index => index}, :remote => true unless index == 0 %></td>
</tr>
If I have correctly understood you, you have problems with nested form.
For what reason do you have readonly property for :amount field?
I do not know, why have you used approach without fields_for, but In this case you can not validate nested fields without it. So your code has to be something like this:
<%= form_for #purchase, :html => {:multipart => true} do |f| %>
<%= render 'shared/form_error', :object => #purchase %>
<%= f.fields_for :purchase_line_items do |pl| %>
<tr id="row<%= pl.object.id %>" valign="top" >
<%= pl.hidden_field :id %>
<td valign="top">
<%= pl.select :account_id, options_from_collection_for_select(#to_accounts, :id, :name, :selected => pl.object.account_id), :include_blank => true, :class=>"full" %>
</td>
<td><%= pl.text_field :amount, :class => 'full', :id => 'total', :readonly => 'readonly', :size => 5 %></td>
<td><%= link_to image_tag("/images/black_icon/ic_cancel.png"), {:action => :remove_line_item, :index => pl.object.id }, :remote => true unless index == 0 %></td>
</tr>
<% end %>
<%= f.submit %>
<% end %>
Add validation to your PurchaseLineItem model to prevent saving record without :account_id.
class PurchaseLineItem < ActiveRecord::Base
belongs_to :purchase
validates_presence_of :account_id
end
Actually if you will validate :account_id you do not have to use :reject_if.
class Purchase < ActiveRecord::Base
has_many :purchase_line_items
accepts_nested_attributes_for :purchase_line_items, :allow_destroy =>true
validates_presence_of :purchase_line_items
validates_associated :purchase_line_items
end
To be more clear, please, edit your question and add code of createaction.

Rails 3.2.x Undefined Method 'join'

I have a basketball app with a many-to-many relationship where a Coach could have coached multiple teams, and a team can have many Coaches.
Coaches_Controller.rb
def index
#coaches = Coach.joins(:teams).select("coaches.first_name, coaches.last_name, teams.team_level")
respond_to do |format|
format.html # index.html.erb
format.json { render json: #coaches }
end
end
Index.html.erb
<% #coaches.each do |coach| %>
<tr>
<td><%= link_to coach.first_name, coach_path(coach) %></td>
<td><%= coach.last_name %></td>
<td><%= coach.team_level %></td>
<td>
<%= link_to t('.edit', :default => t("helpers.links.edit")),
edit_coach_path(coach), :class => 'btn btn-mini' %>
<%= link_to t('.destroy', :default => t("helpers.links.destroy")),
coach_path(coach),
:method => :delete,
:confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')),
:class => 'btn btn-mini btn-danger' %>
</td>
</tr>
<% end %>
I am getting this error, and I'm not quite sure why...
http://i.stack.imgur.com/5a6oB.png
Ideas? I feel like it is something small I'm not seeing... Thanks!
One thing I can see that is wrong is that you don't have coaches.id in your select. You need the id for coach_path(coach) to work. Try this:
#coaches = Coach.joins(:teams).select("coaches.id, coaches.first_name, coaches.last_name, teams.team_level")
Not sure if this solves the join error you are getting.

Nested table formatting with simple_form, nested_form and twitter-bootstrap

Update: I updated this after doing some digging and realizing that this might be twitter-bootstrap causing the problem.
Here is a rough version of my nested form:
<%= simple_nested_form_for #user, :html => { :class => 'form-horizontal' } do |f| %>
<fieldset>
<%= f.input :email %>
<%= f.input :name_first %>
<%= f.input :name_last %>
<table class="table table-striped">
<thead>
<tr>
<th>Active</th>
<th>Company</th>
<th>Role</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<%= f.simple_fields_for :roles, :wrapper_tag => :tr do |role_form| %>
<td><%= role_form.hidden_field :id %><%= role_form.input :active, :label => false, :wrapper => false %></td>
<td><%= role_form.association :company, :label => false, :wrapper => false %></td>
<td><%= role_form.input :role, :label => false, :collection => [ "Guest", "User", "Inspector", "Owner"], :wrapper => false %></td>
<td><%= role_form.link_to_remove "Delete", :class => 'btn btn-mini btn-danger' %>
</td>
<% end %>
</tbody>
</table>
<p><%= f.link_to_add "Add a Role", :roles %></p>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to 'Cancel', users_path, :class => 'btn' %>
</div>
</fieldset>
<% end %>
When it's rendered the fields in the table rows are indented the same as the parent form via the { :class => 'form-horizontal' }. I just want the fields with no wrapper divs etc. and can't seem to figure it out. I thought the :wrapper => false was the ticket but no luck so far.
Dan
I ended up figuring it out on my own. You have to move the form style (form-horizontal) into a div just around the non-nested fields:
<%= simple_nested_form_for #user do |f| %>
<fieldset>
<div class="form-horizontal">
<%= f.input :email %>
<%= f.input :name_first %>
<%= f.input :name_last %>
<%= f.input :phone %>
<%= f.input :mobile %>
<%= f.input :password %>
<%= f.input :password_confirmation %>
</div>
<div class="tubbable">...
If you want to use a table (as in your initial example) to do the layout, I've patched the nested_form gem here https://github.com/ritchiey/nested_form to allow that.
To specify that you want the new fields appended at the bottom of the tbody and wrapped in a tr, replace your current link_to_add call with:
<%= f.link_to_add "Add a Role", :roles, :container =>'tbody', :fields_element=>'tr'%>
Note: the :container param is a CSS selector.
Not sure if this is what you want, but if you want to remove the div wrapper from an input field, use f.input_field instead of f.input:
= f.input_field :email, label: false, placeholder: 'email'
Add :wrapper => false to the simple_nested_form_for call.
The problem is, that :wrapper => false in simple_fields_for gets overwritten by the default :wrapper => nil in the simple_form_for configuration.
See this link for a setup:
How To: Render nested fields inside a table

Active record has_many association for one model having two types of values

i am facing a new situation. I know someone definitely had faced these type of situation:
I have an invoices table and an invoice_line_items table. Till now every thing is going well with has_many and belongs to association. Now i want to add tax accounts in invoice items, for that i don't want to create a separate table, hence i make below changes in my invoice model :
invoice.rb:
class Invoice < ActiveRecord::Base
has_many :invoice_line_items
has_many :tax_line_items, :class_name => "InvoiceLineItem", :dependent => :destroy
accepts_nested_attributes_for :invoice_line_items, :reject_if => lambda {|a|a[:account_id].blank? } , :allow_destroy => true
#validations
validates_presence_of :invoice_line_items
validates_associated :invoice_line_items
end
invoice_line_item.rb:
class InvoiceLineItem < ActiveRecord::Base
belongs_to :invoice
end
and in my controller i did:
class InvoicesController < ApplicationController
def new
#invoice = Invoice.new
#invoice.invoice_line_items.build
#invoice.tax_line_items.create
#from_accounts = TransactionType.fetch_from_accounts(current_company.id,'sales')
#to_accounts = TransactionType.fetch_to_accounts(current_company.id, 'sales')
#tax_accounts = TransactionType.fetch_from_accounts(current_company.id, 'tax')
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #invoice }
end
end
end
in my form i did:
for tax accounts
<% #invoice.invoice_line_items.each_with_index do |invoice_line_item, tax_index| %>
<%= render "tax_line_items", :invoice_line_item => invoice_line_item, :index => tax_index %>
<% end %>
and for invoice items:
<% #invoice.invoice_line_items.each_with_index do |invoice_line_item, index| %>
<%= render "invoice_line_items", :invoice_line_item => invoice_line_item, :index => index %>
<% end %>
and here are my partials:
1)_invoice_line_items.html.erb:
<tr id="row<%= index %>" valign="top" >
<%= hidden_field_tag "invoice[invoice_line_items_attributes][#{index}][id]",invoice_line_item.id%>
<td valign="top">
<%= select_tag "invoice[invoice_line_items_attributes][#{index}][account_id]", options_from_collection_for_select(#from_accounts, :id, :name,:selected => invoice_line_item.account_id ), :include_blank => true, :class=>"full" %>
<!-- <a href="/accounts/new?account_head_id=10" > New item</a> -->
</td>
<td><%= text_area_tag "invoice[invoice_line_items_attributes][#{index}][description]",invoice_line_item.description, :class => "full",:rows =>2 %></td>
<td><%= text_field_tag "invoice[invoice_line_items_attributes][#{index}][quantity]",invoice_line_item.quantity, :class => 'amount', :id => 'quantity', :onkeydown => "return numbersOnly(event);", :size => 8, :maxlength => 25 %></td>
<td><%= text_field_tag "invoice[invoice_line_items_attributes][#{index}][unit_rate]",invoice_line_item.unit_rate, :class => 'amount', :id => 'unit_cost', :onkeydown => "return numbersOnly(event);", :size => 8, :maxlength => 20 %></td><!--Jquery code is in application.js-->
<td><%= text_field_tag "invoice[invoice_line_items_attributes][#{index}][discount_percent]", invoice_line_item.discount_percent, :class => 'amount', :id => 'discount', :onkeydown => "return numbersOnly(event);", :maxlength => 5, :size => 8%></td>
<td><%= text_field_tag "invoice[invoice_line_items_attributes][#{index}][amount]", invoice_line_item.amount, :class => 'full', :id => 'total', :readonly => 'readonly', :size => 5%></td>
<td><%= link_to 'Remove',{:action => :remove_line_item, :index => index}, :remote => true unless index == 0 %></td>
</tr>
2) _tax_line_items.html.erb:
<tr id="tax_row<%= tax_index %>" valign="top" >
<%= hidden_field_tag "invoice[tax_line_items_attributes][#{tax_index}][id]",invoice_line_item.id%>
<td></td>
<td colspan="2" class="ta-right"><label>Add Tax:</label></td>
<td class="ta-right" colspan="2" style="background:#EDF4FF">
<%= select_tag "invoice[invoice_line_items_attributes][#{tax_index}][account_id]", options_from_collection_for_select(#tax_accounts, :id, :name,:selected => invoice_line_item.account_id ), :include_blank => true, :class=>"full" %>
<!-- <a href="/accounts/new?account_head_id=10" > New item</a> -->
</td>
<td style="background:#EDF4FF"><%= text_field_tag "invoice[invoice_line_items_attributes][#{tax_index}][amount]", invoice_line_item.amount, :class => 'full', :id => 'tax', :onkeydown => "return numbersOnly(event);", :size => 5%></td>
<td><%= link_to 'Remove',{:action => :remove_tax_item, :index => tax_index}, :remote => true %></td>
</tr>
My motto is to save both items accounts and tax accounts in invoice_line_items table's account_id column, i hope some buddy has the answer, thanks in advance
The issue you have is #invoice.invoice_line_items and #invoice.tax_line_items will return the same values since they both are using the same id to join.
Seems like you could use Single Table Inheritance (you will have to scroll down to find the section in the API). Using a type column in the invoice_line_items table, you can have model inheritance.
class InvoiceLineItem < ActiveRecord::Base
belongs_to :invoice
end
class TaxLineItem < InvoiceLineItem
belongs_to :invoice
end
then you can cleanup you associations in Invoice
class Invoice < ActiveRecord::Base
has_many :invoice_line_items
has_many :tax_line_items, :dependent => :destroy
end
i got the solution any how i did this:
<% #invoice.tax_line_items.each_with_index do |tax_line_item, tax_index| %>
<%= render "tax_line_items", :tax_line_item => tax_line_item, :index => tax_index %>
<% end %>
and in the partial of _tax_line_items :
<tr id="tax_row<%= tax_index %>" valign="top" >
<%= hidden_field_tag "invoice[tax_line_items_attributes][#{tax_index}][id]",invoice_line_item.id%>
<td></td>
<td colspan="2" class="ta-right"><label>Add Tax:</label></td>
<td class="ta-right" colspan="2" style="background:#EDF4FF">
<%= select_tag "invoice[tax_line_items_attributes][#{tax_index}][account_id]", options_from_collection_for_select(#tax_accounts, :id, :name,:selected => invoice_line_item.account_id ), :include_blank => true, :class=>"full" %>
</td>
<td style="background:#EDF4FF"><%= text_field_tag "invoice[tax_line_items_attributes][#{tax_index}][amount]", tax_line_item.amount, :class => 'full', :id => 'tax', :onkeydown => "return numbersOnly(event);", :size => 5%></td>
<td><%= link_to 'Remove',{:action => :remove_tax_item, :index => tax_index}, :remote => true %></td>
</tr>
and this is working for me....

Nested forms fields_for :prices, repeat forms few time

i have many to many throught asociation and then i do this
fields_for :device
this displaying in good way, but i cannot save it i get unknown attribute :price
And fields_for :devices
And so on, one device makes one more repeat, if i write f.fields_for :price it gives good text field count, but it write
unknown attribute: price
Rails.root: C:/Users/Ignas/mildai/baze4
Application Trace | Framework Trace | Full Trace
app/controllers/commercial_offers_controller.rb:74:in `block in update'
app/controllers/commercial_offers_controller.rb:73:in `update'
thank you
additional information:
controller
def edit_prices
#commercial_offer = CommercialOffer.find(params[:id])
end
link to edit prices
<%= link_to "Edit prices", :controller => "CommercialOffers", :action => "edit_prices", :id => #commercial_offer %>
_edit_price.html.erb
<%= form_for #commercial_offer do |f| %>
<% CommercialOffer.find(params[:id]).devices.each do |device| %>
<%= check_box_tag "commercial_offer[device_ids][]", device.id, #commercial_offer.devices.include?(device) %>
<%= device.name %>
<%= f.fields_for :prices do |builder| %>
<%= render 'prices/new_price', :f => builder, :commercial_offer => #commercial_offer, :device => device %>
<% end %>
<% end %>
<div class="actions">
<%= f.submit "Save"%>
</div>
<% end %>
for one device it have render only one time, but it rendering for one device such times how many devices is with same commercial_offer_id
_new_price.html.erb
Price:
<%= f.text_field :price %></br>
Quantity:
<%= f.text_field :quantity %></br>
Device id:
<%= f.text_field :device_id, :value => device.id %></br>
class CommercialOffer < ActiveRecord::Base
has_many :prices
has_many :devices, :through => :prices
accepts_nested_attributes_for :prices
accepts_nested_attributes_for :devices
end
class Device < ActiveRecord::Base
has_many :prices
accepts_nested_attributes_for :prices
has_many :commercial_offer, :through => :prices
class Price < ActiveRecord::Base
belongs_to :device
belongs_to :commercial_offer
end
There is no any field_for method.
Also your question isn't clear. What actually you want to do? Show only one device? Wich one? First, last?
UPD
commercial_offer.rb:
class CommercialOffer < ActiveRecord::Base
has_many :prices
has_many :devices, :through => :prices
accepts_nested_attributes_for :prices
accepts_nested_attributes_for :devices, :allow_destroy => true
end
Your view
<%= form_for #commercial_offer do |f| %>
<%= f.fields_for :devices do |device| %>
<p>
<%= device.check_box :_destroy %>
<%= device.label "Destroy?" %>
</p>
<p>
<%= device.text_field :name %>
</p>
<%= device.fields_for :prices do |builder| %>
<%= render 'prices/new_price', :f => device %>
<% end %>
<% end %>
<% end %>
<div class="actions">
<%= f.submit "Save"%>
</div>
<% end %>
_new_price partial
<%= f.text_field :price %></br>
Quantity:
<%= f.text_field :quantity %></br>
Device id:
<%= f.text_field :device_id %></br>