In my app I want to add feature to create several objects in one action:
on localhost:3000/bank_accounts/new I have a form for creating one object of #bank_account
= simple_form_for #bank_account do |f|
= f.input :bank_name
= f.input :account_number
= f.button :submit
controller:
def new
#bank_account = BankAccount.new
end
def create
#bank_account = BankAccount.create(bank_params)
if #bank_account.save
redirect_to root_url
else
render 'new'
end
end
Is there a method to create several objects of BankAccount on localhost:3000/bank_accounts/new?
In my opinion you should follow a 'standard' way,
probably bank account belongs to a user,
so you have a BankAccount that belongs to a User and a User has many BankAccounts.
In that case, in the controller you should have something like:
#user = User.find 1234 # get a user
10.times do
#user.bank_accounts.build
end
and in the view you should use a loop to create the fields for all the user's bank accounts (you can user fields_for)
Finally, to create those bank accounts you can even use mass assignment with:
accepts_nested_attributes_for :bank_accounts
I hope this can help :)
Related
I have two models, User, and Product. Product belongs to User, User has many Products.
When a Product is created I also want to update multiple fields in the User model. I've been developing with Ruby for like 2 years now and still don't understand forms fully when it comes to this stuff. I'm still getting permitted: false. Now I know that for instance if I was creating a user while also creating a product I would just do #product.user.build but in this case I just want to update an already existing record.
I also realize that I probably can't call f.fields_for :user as #product doesn't know about user yet. In my head I believe I should be able to just pass additional params to the form, grab the current_user in the product#create action and then update the attributes manually by calling update_attributes on user.
product.rb
accepts_nested_attributes_for :user
product controller
def new
#product = Product.new
end
params.require(:product).permit(:product_name, user_attributes: [:phone_number, :email_address])
product view
form_for #product do |f|
f.fields_for :user do |c|
c.text_field :phone_number
c.text_field :email_address
f.text_field :product_name
end
I also realize that I probably can't call f.fields_for :user as #product doesn't know about user yet.
You can assign attributes to #product without saving it.
def new
#product = Product.new(
user: current_user
)
end
Now #product.user works.
I have a template, a user and user_templates. user has many templates through user_templates.
Currently, whenever a new template is created a user_template record is created as well. This works perfectly with creating 1 record.
Template Create Controller:
def create
#template = Template.new(template_params.merge(user: current_user))
if #template.save
save_user_templates(current_user.id, #template.id)
redirect_to dashboard_url
else
render(:new)
end
end
Save User Template function
def save_user_templates(user, template)
UserTemplate.create(user_id: user, template_id: template)
end
Now I want to implement a 'Multiple Select' so I can select multiple users, click save, which would then create a record for each user in the user_template table at once.
My idea is to pass an array from the view to the controller and then loop through that array and save each record before redirecting. Question is: How do I do that?
Figured out a solution after trying various things. Unfortunately, I did not see the reply in time. Here is what I did.
View
.form-group.has-feedback
.text-muted
= f.label 'Which users should see this?'
= f.collection_select :user_templates, User.all, :id, :name, { include_hidden: false }, multiple: 'true'
Controller
def create
#template = Template.new(template_params.merge(user: current_user))
if #template.save
save_user_templates(params[:template][:user_templates], #template.id)
redirect_to dashboard_url
else
render(:new)
end
end
def save_user_templates(users, template)
users.each do |user|
puts user
UserTemplate.create!(user_id: user, template_id: template)
end
end
You could iterate over the array of users and perform the same action on each of them.
def save_user_templates(user_id_array, template)
user_id_array.each { |user_id| UserTemplate.create(user_id: user_id, template_id: template) }
end
I have a User model, and two models that inherit from that: Teacher and Student. They also have their own controllers that inherit from the User controller.
I also have a Group model.
group belongs to teacher, teacher has many groups. group has and belongs to many students. student has and belongs to many groups.
There is a join table for the HABTM relationships, called 'groups_students'.
I have managed to create a form element that allows me to set the 'type' of User to 'Student' or 'Teacher'.
The difficulty I have now is assigning students to groups in the view. I can do this in the console no problem, as outlined here: Rails 4 HABTM how to set multiple ids in console?
I'm stumped as to how to do this in a view. I want to do it in the Student's show view.
Can someone at least give me some guidance? I have a pretty good book on Rails, but I need to know roughly what I have to do.
In the end I actually paid someone to solve this for me, because I couldn't find any free help for this on the internet. Thankfully, it wasn't too easy for him to solve, but solve it he did:
views/users/show.html.erb:
<%= form_tag assign_to_group_path do %>
<%= hidden_field_tag :user_id, #user.id %>
<%= select_tag :group_id, options_from_collection_for_select(Group.all, "id", "title") %>
<%= submit_tag "Assign to Class" %>
<% end %>
users_controller.rb:
private
def user_params
params[:user].permit(:type) if params[:user]
end
students_controller.rb (inherits from users_controller.rb):
def assign_to_group
#user = User.find(params[:user_id])
#group = Group.find(params[:group_id])
#user.groups << #group unless #user.groups.include? #group
#user.save!
redirect_to user_path #user
end
routes.rb:
post 'assign_to_group' => 'students#assign_to_group'
I'm new to rails , and I have a problem with the nested forms and all of that.
I have a User model, and an Organization model.
When I want to create a user, I want to specify from which organization does he comes from.
Either the organization name is already in the database or if it's not, I want to create a new record and associate that record the User model.
I have hard time understanding all the relations (many-to-many etc) implications in the rails framework, but so far I've got this.
model/organization.rb
class Organization < ActiveRecord::Base
has_many :user
validates_presence_of :name
end
model/user.rb (short)
class User < ActiveRecord::Base
belongs_to :organization
accepts_nested_attributes_for :organization
#####
end
From this, in the console, I can create user and specify and organization name , and it will create a new record for the user and a new record for the organization.
The problem is that it creates a new organization each time.
I want to be able to associate an already existing organization to a new user.
I can get the list of organization with things like typeahead.js for the form, so the name will be the same when the user selects one. But I don't know how to relate the two (the newly created user and already existing organization).
I thought of putting a hidden field with the id of the organization, and check in the controller if this id exists. If it does, put this id, if it doesn't create a new one. But I don't even know how to do this. In the console, when I update the attributes of a user, for example , with an organization_id = 3 which exists :
u.update_attributes( :organization_attributes => { id: 3 } )
It rejects saying he didn't find a user with ID=... with Organization.id = 3 ...
I don't understand.
I suppose since this is a common case, that this should be easy , but it's messing with my head.
If someone is willing to explain to me, I'd be very grateful.
Thank you.
EDIT
i've just tried something in my controller but that doesn't work either.
def create
#user = User.new(user_params) # :user object built from user inputform
org = Organization.find_by(name:user_params[:organization_attributes][:name])
if org
#user.organization.id = org.id
end
if #user.save
# signin the user (token etc)
sign_in #user
flash[:success] = "Registration sucessfull !"
redirect_to #user
else
render 'new'
end
end
+user_controller (strong params)
def user_params
params.require(:user).permit(:lname,:email,:fname,:password,:password_confirmation,
:gender,:role,:display_private,:link_li,:country,:city,:phone,:hobbies,
:avatar,:org_name, :organization_attributes => [ :id, :name])
end
+form.html.erb
<%= u.fields_for :organization do |o| %>
<%= o.label "Organization" %>
<!-- PUT ORGA -->
<%= o.text_field :name, class:"form-control" %>
<% end %>
I would write a custom method for this:
#in User
def organization_name
(org = self.organization) && org.name
end
def organization_name=(name)
if org = Organization.find_by_name(name)
self.organization = org
else
self.organization = Organization.create(:name => name)
end
end
Now, because you've got a getter and setter method (ie two methods with the same name, apart from the = sign), you can treat organization_name like an attribute of User and put it in a form field like
f.input :organization_name
The input will get the current value from #user.organization_name and will call #user.organization_name= with the new value.
First take away the accepts_nested_attributes from the model.
Then in your controller you should do something like:
def create
#user = User.new(user_params) # :user object built from user inputform
org = Organization.where(name: user_params[:organization_attributes][:name]).first || Organization.create(name: user_params[:organization_attributes][:name])
#user.organization = org
if #user.save
# signin the user (token etc)
sign_in #user
flash[:success] = "Registration sucessfull !"
redirect_to #user
else
render 'new'
end
end
In your app/model/user.rb
def self.create(name, attribute1, ... ,organization)
user = User.new(:name => name, :atr_1 => attribute_1, ....:atr_n => attribute_n)
user.organization = organization
raise "user not created" if !user.save
user
end
In users_controller.rb
def create
org = Organization.find params['organization'] #expecting the param to be Organization#id
user = User.create(params['name'], ..., org)
render :json => {:message => "user created"}
end
I have a classified model that is hook up to the student model in a way that it looks like this
classified.rb
belongs_to :student
in my student model it
has_many :classifieds
The classifieds table contain a column for student_id
when I head to the rails console
I can create a new classified for that particular student record by doing
Student.find(19).classifieds.create(:ad_title => "blah", :ad_content => "blah", :location => "blah")
The record automatically gets a student_id generated because it was created in the student standpoint.
Now the problem is I have a classifieds controller with a new and a create method and a new form in the view
I am creating a new ad in the classifieds standpoint here is the form
<div>
新广告: <br><br>
<%= simple_form_for #advertisement do |f| %>
<%= f.input :ad_title, label: "Title" %><br>
<%= f.input :ad_content, label: "Content"%><br>
<%= f.input :location, label: "Location"%><br>
<%= f.input :student_id, label: "Your Student ID"%><br>
<%= f.button :submit, "Add an Advertisement" %>
<% end %>
</div>
The problem is the student_id must exist in order for that particular record to show up in index and my users don't know their id.
How do I create a classified in the student standpoint using forms
I consider going to my students controller and adding a method like this
def create_classified_ad
#student = Student.find(params[:id])
#classified = #student.classified.create(params[:classified])
end
I am using devise so there is user session? I don't know how sessions work entirely I want that particular student to be found after logged in and have that student create a classified ad with the inputs from the form so the record will be created correctly?
The question is more like how do you insert data using forms to a hooked up table correctly? (and not merely inserting data into a simple no relationship table)
You should not be passing the student_id from the form. If you have a devise session, you should have access to current_user:
def new
#classified = current_user.classifieds.build
end
def create
#classified = current_user.classifieds.build(params[:classified])
if #classified.save
# do something
else
# handle failure
end
end
In the index, you can do this:
def index
#classifieds = current_user.classifieds.all
end
All of this assumes you have a devise session. If not, just fetch the student like so:
#student = Student.find(params[:student_id])
#classified = #student.classifieds.build
Set up a nested route for the classifieds under the user:
resources :users do
resources :classifieds
end
This allows you to fetch the student from a student_id param. Your route would like this: new_student_classified_path(#student).