I am displaying an invoice, to which I want to add 'fly' products. I want to do this using a drop down box for the products along with an add button. Once a product has been added to the invoice I want to be able to click a delete button to remove it.
I currently have this working through the console, but am not sure how to do this on the front end.
How it is set up::
User Model:
class User < ActiveRecord::Base
....
has_many :invoices
....
end
Invoice Model:
class Invoice < ActiveRecord::Base
attr_accessible :active
validates :user_id, presence: true
belongs_to :user
has_many :categorizations
has_many :flies, through: :categorizations
end
Invoice migration:
class CreateInvoices < ActiveRecord::Migration
def change
create_table :invoices do |t|
t.boolean :active
t.integer :user_id
t.timestamps
end
add_index :invoices, :user_id
end
end
Categorization Model:
class Categorization < ActiveRecord::Base
attr_accessible :fly_id, :user_id
belongs_to :invoice
belongs_to :fly
end
Categorization migration:
class CreateCategorizations < ActiveRecord::Migration
def change
create_table :categorizations do |t|
t.integer :user_id
t.integer :fly_id
t.timestamps
add_index :categorizations, :user_id
add_index :categorizations, :fly_id
end
end
end
Fly Model:
class Fly < ActiveRecord::Base
attr_accessible :description, :name
validates :description, :name, presence: true
has_many :categorizations
has_many :invoices, through: :categorizations
end
Fly migration:
class CreateFlies < ActiveRecord::Migration
def change
create_table :flies do |t|
t.string :name
t.string :description
t.timestamps
end
end
end
Show invoice view:
<h3>Invoice</h3>
<p>User Name:
<%= #invoice.user.name %></p>
<p>
Invoice ID:
<%= #invoice.id %></p>
<p>
Invoice Active?:
<%= check_box_tag 'admin', '1', #invoice.active, :disabled => true %></p>
<p>Email:
<%= #invoice.user.email if #invoice.user.email %></p>
<table class="table table-condensed">
<thead>
<tr>
<th>Invoice Flies</th>
</thead>
<tbody>
<% #invoice.flies.each do |fly| %>
<tr>
<td><%= fly.name %></td>
</tr>
<% end %>
</tbody>
</table>
<%= simple_form_for(#categorization) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
#this is where I want to add my 'add product to invoice' functionality
<%= f.submit "Add Fly to Invoice", class: "btn btn-large btn-primary" %>
<% end %>
<%= button_to "Mark as Sent", {:controller => :invoices, :action => :activate, :id => #invoice.id }, {:method => :post } %>
<%= button_to "Mark as not sent", {:controller => :invoices, :action => :deactivate, :id => #invoice.id }, {:method => :post } %>
<br><br>
<%= link_to "Back to list of invoices", invoices_path %>
There's two good gems for the purpose:
https://github.com/nathanvda/cocoon
https://github.com/ryanb/nested_form
Related
Hi I have a polymorphic association with for a Document model for storing document uploads. I'm trying to submit the document attributes as a nested attribute via the associated model.
However, when I load the form, the nested field does not show. What am I missing?
Schema:
create_table "documents", force: :cascade do |t|
t.json "links"
t.integer "linkable_id"
t.string "linkable_type"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "documents", ["linkable_type", "linkable_id"], name: "index_documents_on_linkable_type_and_linkable_id", using: :btree
Models:
class Document < ActiveRecord::Base
belongs_to :linkable, polymorphic: true
belongs_to :user
belongs_to :company
mount_uploaders :links, DocUploader
end
class CustomerPlan < ActiveRecord::Base
has_many :documents, as: :linkable
accepts_nested_attributes_for :documents
end
Controller:
class CustomerPlanController < ApplicationController
def new
#customer_plan = current_company.customer_plans.build
end
def create
#customer_plan = current_company.customer_plans.build(customer_plan_params)
if #customer_plan.save
redirect_to #customer_plan, notice: 'Customer plan was successfully created.'
else
render :new
end
end
private
def cusomter_plan_params
params.require(:cusomter_plan_params).permit(:date, :name, :plan_type,
documents_attributes: [:id, links: []])
end
end
Form:
<%= simple_nested_form_for #stock_plan, :html => { :multipart => true } do |f| %>
<%= f.error_notification %>
<%= f.input :date %>
<%= f.input :name %>
<%= f.input :plan_type %>
<%= f.simple_fields_for :documents do |d| %>
<p><b>Upload here:</b></p>
<%= d.file_field :links, multiple: true %>
<br>
<% end %>
<%= f.button :submit%>
<% end %>
I have the following models and their associations:
#models
class Order < ActiveRecord::Base
has_many :order_items
has_many :items, :through => :order_items
accepts_nested_attributes_for :items, :order_items, :allow_destroy => true
end
class Item < ActiveRecord::Base
has_many :order_items
has_many :orders, :through => :order_items
end
class OrderItem < ActiveRecord::Base
belongs_to :item
belongs_to :order
end
I want to display the item.name, order_item.quantity and order_item.price in one table as attempted below:
<tbody>
<% #order.items.each do |item| %> <<<<<<<< need this to call item.name
<% #order.order_items.each do |order_item| %> <<<<<<< need this to call the other fields
<tr>
<td><%= item.name %></td>
<td><%= order_item.quantity %></td>
<td><%= order_item.price %></td>
</tr>
<% end %>
<% end %>
</tbody>
the above works in calling the specific field but how it is written will not do because inner loop needs to finish before outer and hence we don't get what we need.
#Tables snippets
create_table "items", force: true do |t|
t.string "name"
t.decimal "price"
t.integer "stock"
t.string "location"
t.decimal "discount"
t.boolean "status"
end
create_table "order_items", force: true do |t|
t.integer "item_id"
t.integer "order_id"
t.integer "quantity"
t.decimal "price"
end
create_table "orders", force: true do |t|
t.string "code"
t.integer "user_id"
t.text "memo"
t.boolean "status"
t.integer "client_id"
t.decimal "sub_total"
end
#orders form
<%= compact_form_for(#order) do |f| %>
<%= f.association :client, collection: Client.all, label_method: :name, value_method: :id, prompt: "Client Name", required: true %>
<%= f.simple_fields_for :items do |o| %>
<%= o.input :name, collection: Product.all, label_method: :name, value_method: :id %>
<%= o.input :quantity %>
<% end %>
<%= f.button :submit %>
<% end %>
You may wish to use the .delegate method with the OrderItem model, like this:
#app/models/order_item.rb
class OrderItem < ActiveRecord::Base
belongs_to :item
belongs_to :order
delegate :name, to: :item #-> allows you to call #order_item.name
end
This will allow you to call:
<tbody>
<% #order.order_items.each do |item| %>
<tr>
<td><%= item.name %></td>
<td><%= item.quantity %></td>
<td><%= item.price %></td>
</tr>
<% end %>
</tbody>
Fix
A much better way to make this work will be to use the following model names:
#app/models/product.rb
class Product < ActiveRecord::Base
has_many :items
has_many :orders, :through => :items
end
#app/models/order.rb
class Order < ActiveRecord::Base
has_many :items
has_many :products, :through => :items
accepts_nested_attributes_for :products, :allow_destroy => true
end
#app/models/item.rb
class Item < ActiveRecord::Base
belongs_to :product
belongs_to :order
delegate :name, to: :product #-> allows you to call #item.name
end
This will allow you to call:
<tbody>
<% #order.items.each do |item| %>
<tr>
<td><%= item.name %></td>
<td><%= item.quantity %></td>
<td><%= item.price %></td>
</tr>
<% end %>
</tbody>
i am a newbie to rails
i am stuck at a point
i have related models Book and Subject
where
Book related_to:Subject
and
Subject has_many:books
now what can i do to store subject field while saving the book instance
book model file :book.rb
class Book < ActiveRecord::Base
attr_accessible :title, :price,:description , :created_at ,:subject
belongs_to :subject
validates_presence_of :title
validates_numericality_of :price, :message=>"Error Message"
end
subject model file :subject.rb
class Subject < ActiveRecord::Base
attr_accessible :name
has_many :books
end
my migration files are
book migration
class Books < ActiveRecord::Migration
def self.up
create_table :books do |t|
t.column :title, :string, :limit => 32, :null => false
t.column :price, :float
t.column :subject_id, :integer
t.column :description, :text
t.column :created_at, :string
end
Book.create :title =>"book1",:price =>500 , :description=>"book 1 created" , :created_at=>"12/12/12"
Book.create :title =>"book2",:price =>111 , :description=>"book 2 created" , :created_at=>"12/12/12"
Book.create :title =>"book3",:price =>222 , :description=>"book 3 created" , :created_at=>"12/12/12"
Book.create :title =>"book4",:price =>333 , :description=>"book 4 created" , :created_at=>"12/12/12"
Book.create :title =>"book5",:price =>444 , :description=>"book 5 created" , :created_at=>"12/12/12"
end
def self.down
drop_table :books
end
end
subjects migration
class Subjects < ActiveRecord::Migration
def self.up
create_table :subjects do |t|
t.column :name, :string
end
Subject.create :name => "Physics"
Subject.create :name => "Mathematics"
Subject.create :name => "Chemistry"
Subject.create :name => "Psychology"
Subject.create :name => "Geography"
end
def self.down
drop_table :subjects
end
end
my newBook html.erb
<html>
<head>
<title> new Book </title>
</head>
<body>
<h1><%= #hello_message %></h1>
<h1>Add new book</h1>
<%= form_tag :action => 'create' %>
<p>
<label for="book_title">Title</label>:
<%= text_field 'book', 'title' %>
</p>
<p>
<label for="book_price">Price</label>:
<%= text_field 'book', 'price' %>
</p>
<p>
<label for="book_subject">Subject</label>:
<%= collection_select(:book,:subject_id,#subjects,:id,:name) %>
</p>
<p>
<label for="book_description">Description</label>
<br/>
<%= text_area 'book', 'description' %>
</p>
<%= submit_tag "Create" %>
<%= form_tag %>
<%= link_to 'Back', {:action => 'list'} %>
</body>
</html>
when i try to save by my create action it says
Can't mass-assign protected attributes: subject_id
In Book model, you should have:
attr_accessible :title, :price, :description, :created_at, :subject_id
Add accepts_nested_attributes_for :books in your subject model
class Subject < ActiveRecord::Base
attr_accessible :name
has_many :books
accepts_nested_attributes_for :books, :allow_destroy => true
end
I am trying to display an image that is in my public/image folder and I
don't know how to.
What I want to do is to be able to assign a photo to an artist so you
can navigate through different artist's photo.
This is my image model
class Image < ActiveRecord::Base
has_many :publishings
has_many :artists, :through => :publishings
has_many :comments,:through => :friends
has_many :comments, :as => :resource, :class_name => "Commentable"
end
This is my image show.html
<p id="notice"><%= notice %></p>
<p>
<b>Title:</b>
<%= #image.title %>
</p>
<p>
<b>Filename:</b>
<%= #image.filename %>
</p>
<p>
<b>Likes:</b>
<%= #image.likes %>
</p>
<%= link_to 'Edit', edit_image_path(#image) %> |
<%= link_to 'Back', images_path %>
This is the database for the images
class CreateImages < ActiveRecord::Migration
def self.up
create_table :images do |t|
t.string :title :null => false
t.string :filename :null =>false
t.integer :likes :default =>0
t.timestamps
end
end
def self.down
drop_table :images
end
end
Thanks in advance
<%= image_tag #image.filename %>
i have two identical collection_selects on one page (one message belonging to 2 groups)
<%=
collection_select(:message,:group_ids, Group.find(:all),:id, :title, {}, {:name=>'message[group_ids][]'} )
%>
<%=
collection_select(:message,:group_ids, Group.find(:all),:id, :title, {}, {:name=>'message[group_ids][]'} )
%>
is it possible to set two different selected values for them using collection_select?
edit:
i guess i'd have to do something like
<%
#message.group_id=5
%>
<%=
collection_select(:message,:group_id, Group.find(:all),:id, :title, {}, {:name=>'message[group_ids][]'} )
%>
<%
#message.group_id=6
%>
<%=
collection_select(:message,:group_id, Group.find(:all),:id, :title, {}, {:name=>'message[group_ids][]'} )
%>
but of course it doesn't work and gives method missing error
edit2:
guess there is no way to do it with collection_select. unless group has a method, returning single group_id each time.
what i ended up with is
select_tag 'message[group_ids][]', "<option></option>"+options_from_collection_for_select(Group.find(:all), 'id', 'title',group1.id)
select_tag 'message[group_ids][]', "<option></option>"+options_from_collection_for_select(Group.find(:all), 'id', 'title',group2.id)
You need to set up your models and relationships like so:
class Message < ActiveRecord::Base
has_many :message_groups
has_many :groups, :through => :message_groups
accepts_nested_attributes_for :message_groups #Note this here!
end
class Group < ActiveRecord::Base
has_many :message_groups
has_many :messages, :through => :message_groups
end
class MessageGroup < ActiveRecord::Base
belongs_to :group
belongs_to :message
end
Then in your form...
<% form_for(#message) do |f| %>
<%= f.error_messages %>
<% f.fields_for :message_groups do |g| %>
<p>
<%= g.label :group_id, "Group" %>
<%= g.select :group_id, Group.find(:all).collect {|g| [ g.title, g.id ] } %>
</p>
<% end %>
<p>
<%= f.submit 'Update' %>
</p>
<% end %>
And here's my migrations for completeness
class CreateGroups < ActiveRecord::Migration
def self.up
create_table :groups do |t|
t.string :title
t.timestamps
end
end
def self.down
drop_table :groups
end
end
class CreateMessages < ActiveRecord::Migration
def self.up
create_table :messages do |t|
t.text :body
t.timestamps
end
end
def self.down
drop_table :messages
end
end
class CreateMessageGroups < ActiveRecord::Migration
def self.up
create_table :message_groups do |t|
t.integer :message_id
t.integer :group_id
t.timestamps
end
end
def self.down
drop_table :message_groups
end
end
Hope this helps...!