How to save to two tables from one form in Rails - ruby-on-rails-3

I have a regular form for User information which starts like so:
<%= form_for(#user, :html => { :class => "form-horizontal" }) do |f| %>
<%= f.text_field :last_name %>
...
<%= f.submit "Submit", class: "btn btn-primary", :name => "submit_button" if #user.last_step? %>
<% end %>
I also have some non User fields in the form. Here's an example:
<%= f.label "When is your birthday?" %>
<%= select_tag "month" %>
<%= select_tag "day" %>
<%= select_tag "year" %>
How would I save this to a different table than User?

If you want to update a model other than User, you should probably use accepts_nested_attributes_for and fields_for. The alternative is to just do the work in your create action of your UsersController, ie:
def create
#user = User.create params[:user]
#foo = Foo.find params[:foo_id]
#foo.date = Date.new(params[:foo_year], params[:foo_month], params[:foo_day])
...
end

Related

Rails 4 - comment.create saves :text but not :commenter

When I create a new comment the text saves fine but the commenter is not being saved. I have verified that the column for commenter exists and that the parameter is being passed. The field just isn't inserting into the table and I have no clue why.
Form:
<%= form_for #comment do |f| %>
<p>
<%= f.label :new_comment %>
<%= f.text_field :text %>
<%= hidden_field_tag :user_id, params[:user_id] %>
<%= hidden_field_tag :post_id, params[:id] %>
<%= f.submit "Comment" %>
</p>
<% end %>
Action:
def create
#user = User.find(params[:user_id])
#post = #user.posts.find(params[:post_id])
#comment = #post.comments.create(params[:comment].permit(:text, :commenter))
redirect_to show_post_path(#user, #post)
end
Add one more field in form which will pass commenter for comment
<%= form_for #comment do |f| %>
<p>
<%= f.label :new_comment %>
<%= f.text_field :text %>
<%= hidden_field_tag :user_id, params[:user_id] %>
<%= hidden_field_tag :post_id, params[:id] %>
<%= hidden_field_tag 'comment[commenter]', params[:user_id] %>
<%= f.submit "Comment" %>
</p>
<% end %>
OR
Change controller code to
def create
#user = User.find(params[:user_id])
#post = #user.posts.find(params[:post_id])
#comment = #post.comments.new(params[:comment].permit(:text, :commenter))
#comment.commenter = #user.id
#comment.save
redirect_to show_post_path(#user, #post)
end
I'm guessing you want your commenter_id in your form instead of user_id. Change your user_id line in your form to:
<%= hidden_field_tag :commenter_id, params[:commenter_id] %>
And then change the third line in your create function:
#comment = #post.comments.create(params[:comment].permit(:text, :commenter_id))
Have you check your association between User model and Comment Model?
in User model it should be has_many :comments and in Comment Model belongs_to :user

Update form in rails - No route matches [PUT]

I have a form to create adverts.
Controllers:
def edit
#engines = Engine.all
#car = Car.find(params[:id])
end
def update
#car = Car.find(params[:id])
if #car.save
redirect_to root_path
end
end
My routes:
resources :adverts
Create.html.erb
<%= form_for #car, :url => adverts_path do |f| %>
<div><%= f.label :name %><br />
<%= f.text_field :name %></div>
<%= hidden_field_tag :model_id, params[:model_id] %>
<%= select_tag :engine_id, options_from_collection_for_select(#engines, "id", "name",:selected=>#car.engine_id) %>
<div><%= f.submit "Create car!" %></div>
<% end %>
I can create advert, but I can't to update it.
edit.html.erb
<%= form_for #car, :url => adverts_path do |f| %>
<div><%= f.label :name %><br />
<%= f.text_field :name %></div>
<%= hidden_field_tag :model_id, params[:model_id] %>
<%= select_tag :engine_id, options_from_collection_for_select(#engines, "id", "name",:selected=>#car.engine_id) %>
<div><%= f.submit "Update car!" %></div>
<% end %>
when I submited my form, I have an error - No route matches [PUT] "/adverts"
$ rake routes:
adverts GET /adverts(.:format) adverts#index
POST /adverts(.:format) adverts#create
new_advert GET /adverts/new(.:format) adverts#new
edit_advert GET /adverts/:id/edit(.:format) adverts#edit
advert GET /adverts/:id(.:format) adverts#show
PUT /adverts/:id(.:format) adverts#update
DELETE /adverts/:id(.:format) adverts#destroy
I need help.
When you are updating you have to let Rails know which object you want to update by passing an id.
In edit.html.erb change:
<%= form_for #car, :url => adverts_path do |f| %>
to:
<%= form_for #car, :url => advert_path(#car) do |f| %>
By the way, I find your code very strange. Why don't your model names match your controllers and routes? I mean you are creating an advert but your model is called car. That doesn't make any sense. Either call it car or advert, but don't mix them.
If you used RESTful routing, you don't need to specify a url, just need:
<%= form_for #car do |f| %>
The form can know #car is new record, or saved record, so it will send appropriate http method.
And in your update action:
def update
#car = Car.find(params[:id])
if #car.update_attributes(params[:car])
redirect_to root_path
end
end
I got myself in a similar situation today with a mismatched resource and model name. I agree the model and controller names need to correlate, but you can override the routes name to be whatever you want.
resources :cars, path: "adverts"
Along with RESTful routing
<%= form_for #car do |f| %>
You may also want to make sure your url: path is singular on the #form_form.

Passing Rails Parameters into Form

I'm trying to pass in two variables for a Nested Model form to use, but I'm getting an error. It's probably an easy syntax error that someone experienced could see right away, but I don't see it.
I have a template showing users, if you click one, it should take the user_id and community _id for use in the form. Both community and user are properly declared in the controller.
link to form:
<%= link_to "award badge", award_badge_badges_path, :user_id => user.id, :community_id => #community.id %>
The form uses two models - badge and badge winners. The user_id and community_id are needed for badge_winners which is nested in badges. The error I'm getting is "undefined local variable or method 'user_id' for #<#<Class:0x77544c0>:0x7714230>" so I think that something is wrong with the 2nd and 3rd lines in the form. Here's the form:
<%= form_for(#badge) do |f| %>
<%= f.hidden_field :user_id ,:value => user_id %>
<%= f.hidden_field :community_id ,:value => community_id %>
<%= f.label :Description %>
<%= f.text_area :description %>
<%= f.fields_for :badge_winners do |builder| %>
<%= render "badge_winner", :f => builder, :locals => {:user_id => user_id, :community_id => community_id} %>
<% end %>
<%= f.submit "Give Badge" %>
<% end %>
the show template in the controller:
def award_badge
#badge = Badge.new
badge_winners = #badge.badge_winners.build
end
the badge winner partial
<%= f.hidden_field :user_id ,:value => user_id %>
<%= f.hidden_field :community_id ,:value => community_id %>

Hidden Field in Simple Nested Form Not Being Submitted

Environment: Rails 3.1.0, Ruby 1.9.2
I have Portfolio model which has_many Positions which has_one Asset.
This is the schema for the Position model:
create_table "positions", :force => true do |t|
t.integer "portfolio_id"
t.integer "asset_id"
t.decimal "holding_percentage"
end
When the user creates a portfolio he/she should enter the portfolio name and then add positions by adding stock tickers. Jquery does its stuff and shows the full name of the asset and also inserts the asset_id into the hidden field.
I am using both nested_form and simple_form as follows:
<%= simple_nested_form_for #portfolio do |f| %>
<%= f.input :name, :placeholder => 'Your portfolio name' %>
<%= f.fields_for :positions do |position_form| %>
<%= text_field_tag 'asset-ticker', nil, :class => 'asset-ticker' %>
<span class="asset-name"></span>
<%= position_form.text_field :holding_percentage, :class => 'asset-perc' %>
<%= position_form.hidden_field :asset_id, :class => 'asset-num', :as => :hidden %>
<%= position_form.link_to_remove "Remove this position", :class => 'asset-rem-link' %>
<% end %>
<p><%= f.link_to_add "Add a Position", :positions, :class => 'asset-add-link' %></p>
<%= f.button :submit %>
<% end %>
The problem is that the asset_id value in the hidden field is not being submitted. The parameters look as follows:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"hmvoGHF9GzpPsohQQ2MwhWk4FzhVVrf+IqoChHgftEs=",
"portfolio"=>{"name"=>"needhelpnow",
"positions_attributes"=>
{"new_1316730954406"=>{"holding_percentage"=>"11", "asset_id"=>"", "_destroy"=>"false"},
"new_1316730961085"=>{"holding_percentage"=>"22", "asset_id"=>"", "_destroy"=>"false"},
"new_1316730971587"=>{"holding_percentage"=>"33", "asset_id"=>"", "_destroy"=>"false"}}},
"commit"=>"Create Portfolio"}
It turns out that the problem was that I was writing in the value of the hidden field with:
('.asset-num').html(data.id)
Instead of:
('.asset-num').val(data.id)

How do you pass rails 3 forms params into an array?

I have a nested form (using accepts_nested_attributes_for in respective models):
<%= form_for(:technician, :url => {:controller => 'pos', :action => 'create_ticket'}) do |f| %>
<%= f.fields_for :service do |s| %>
<%= s.text_field :name %>
<%= s.text_field :name %>
<%= s.text_field :name %>
<%= s.text_field :name %>
<% end %>
<% end %>
This works fine if I only have one s.text_field. But once I add additional text_fields, it doesn't run properly. If you look at the source code, the id and name are the same for all six?
How do I put these params into an array? [so that I can isolate them like this:]
service1 = Service.named(params[:technician][:service][1][:name])
(I've tried the method described on railscasts episode 192, but it didn't work either).
After hours of trial and error, I've hacked something that works (but please let me know if you know a better, more eloquent way):
in view:
<%= form_for(:technician, :url => {:controller => 'pos', :action => 'create_ticket'}) do |f| %>
<% for #i in 1..6 do %>
<%= f.fields_for "services[#{#i}]" do |s| %>
<% end %>
<% end %>
<% end %>
in controller:
for i in 1..6 do
#service = Service.named(params[:technician][:services][i.to_s][:name]).first
end
make sure you turn i into string