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...!
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 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
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 have set up a HABTM relationship between two table creating a many to many relationship between items and categories. I want to add an item connected with one or more categories via the add item form. when I submit the form I am getting the error "Can't mass-assign protected attributes: categories".
Here are my models:
class Item < ActiveRecord::Base
attr_accessible :description, :image, :name
has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }
belongs_to :user
has_and_belongs_to_many :categories
validates :name, presence: true, length: {maximum: 50}
accepts_nested_attributes_for :categories
end
class Category < ActiveRecord::Base
attr_accessible :description, :name
has_and_belongs_to_many :items
validates :name, presence: true, length: {maximum: 50}
end
And my migrations:
class CreateItems < ActiveRecord::Migration
def change
create_table :items do |t|
t.string :name
t.text :description
t.has_attached_file :image
t.timestamps
end
end
end
class CreateCategories < ActiveRecord::Migration
def change
create_table :categories do |t|
t.string :name
t.string :description
t.timestamps
end
end
end
class CreateCategoriesItems < ActiveRecord::Migration
def up
create_table :categories_items, :id => false do |t|
t.integer :category_id
t.integer :item_id
end
end
def down
drop_table :categories_items
end
end
And my form looks like this:
<%= form_for(#item, :html => { :multipart => true }) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_field :description %>
<%= f.file_field :image %>
<%= f.collection_select(:categories, #categories,:id,:name)%>
<%= f.submit "Add Item", :class => "btn btn-large btn-primary" %>
<% end %>
and here's my Items Controller:
class ItemsController < ApplicationController
def new
#item = Item.new
#categories = Category.all
end
def create
#item = Item.new(params[:item])
if #item.save
#sign_in #user
flash[:success] = "You've created an item!"
redirect_to root_path
else
render 'new'
end
end
def show
end
def index
#items = Item.paginate(page: params[:page], per_page: 3)
end
end
Thanks for all of your help :)
-Rebekah
Mass Assignment usually means passing attributes into the call that creates an object as part of an attributes hash.
Try this:
#item = Item.new(name: 'item1', description: 'description1')
#item.save
#category = Category.find_by_name('category1')
#item.categories << #category
Also see:
http://guides.rubyonrails.org/association_basics.html#the-has_and_belongs_to_many-association
http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html
I hope this helps.
IAmNaN posted the comment above that was the missing link in my code working properly. I have since written a blog post that details the process of getting the HABTM set-up. Thanks IAmNaN!
Good day.
Has somebody working solution for deleting asset in nested form in Carrierwave?
MODEL
has_many :article_images, :dependent => :destroy
accepts_nested_attributes_for :article_images
mount_uploader :image, ImageUploader
belongs_to :article, :polymorphic => true
schema.rb
create_table "article_images", :force => true do |t|
t.string "image"
t.string "article_id"
end
create_table "articles", :force => true do |t|
t.string "title"
end
CONTROLLER
def edit
#article = Article.find(params[:id])
#article.article_images.build
end
VIEW
_form.html.erb
<%= f.fields_for :article_images do |article_image| %>
<% if article_image.object.new_record? %>
<%= article_image.file_field :image %>
<% else %>
<%= image_tag(article_image.object.image.url(:thumb)) %>
<%= article_image.check_box :remove_image %> #DON'T WORK
<% end %>
<% end %>
I think it's better if you do this:
class ArticleImage < ActiveRecord::Base
# ...
attr_accessible :remove_image
after_save :clean_remove_image
def changed?
!!(super || remove_image)
end
def clean_remove_image
self.remove_image = nil
end
end
It worked for me.
What happens if you add this to your accepts_nested_attributes_for in your model:
accepts_nested_attributes_for :article_images, :allow_destroy => true
and change this in your view code:
<%= article_image.check_box :remove_image %> #DON'T WORK
To this:
<%= article_image.check_box :_destroy %> #MIGHT WORK?