Rails 3 Mass-Assignment Errors with fields_for - ruby-on-rails-3

I have the following model relationships:
OrderModel:
has_one :credit_card
accepts_nested_attributes_for :credit_card
attr_accessible :user_id, :date_updated, :date_finished, :amount, :payment_method, :status, :billing_cycle, :auth_net_subscription_id, :billing_start_date, :credit_card_attributes, :billing_address_id, :cc_id
CreditCardModel:
belongs_to :order
Here is my Order Controller (orders#checkout)
def checkout
#order = current_order
#cc = CreditCard.new
#order.build_credit_card
respond_with #order
end
Here is the form for entering in a CC on the order:
<%= form_for(#order, :url => finish_checkout_path, :html => { :class => 'validate' }) do |f| %>
<%= f.fields_for #cc do |cc| %>
<%= cc.text_field :cc_number, :placeholder => "Credit Card Number", :class => "full-width validate[required, creditCard] cc" %>
<%= cc.text_field :name, :placeholder => "Name as it appears on card", :class => "full-width validate[required]" %>
<%= select_month(Date.today, {:field_name => 'exp_month', :prefix => "order[credit_card]", :prompt => "EXP. MONTH"}, { :class => "dk half-width validate[required,past] marginRight10" }) %>
<%= select_year(Date.today, {:field_name => 'exp_year', :prefix => "order[credit_card]", :prompt => "EXP. YEAR", :start_year => Date.today.year, :end_year => Date.today.year + 10}, { :class => "dk half-width validate[required]" }) %>
<%= link_to "What's this?", "#", :class => 'cvv-help' %>
<%= cc.text_field :cvv, :class => 'half-width validate[required] marginRight10', :placeholder => "CVV" %>
<%= cc.text_field :zip_code, :class => 'half-width validate[required]', :placeholder => "Zip Code" %>
<% end %>
<%= f.hidden_field :amount, :value => #order.products.collect(&:price).reduce(&:+) %>
<p class="tos">By clicking the button below you agree to our terms of service.</p>
<p class="align-center"><%= f.submit "Submit", :class => 'btn submit' %></p>
<% end %>
And here is where I update the order (orders#finish):
current_order.update_attributes(params[:order])
When I do this, I get the following error: Can't mass-assign protected attributes: credit_card
I clearly have the credit_card_attributes in my attr_accessibleso I am not sure why this is erroring out.

Not sure, but it might be because of your controller code:
def checkout
#order = current_order
#cc = CreditCard.new
#order.build_credit_card
respond_with #order
end
With this, the credit card that you use in your fields_for is not linked to your order. That might be the problem.
Try doing that:
def checkout
#order = current_order
#order.build_credit_card
respond_with #order
end
and
<%= f.fields_for :credit_card do |cc| %>

Related

a new page, nested form using devise's registration path

I'm trying to build a nested form in a custom page using devise.
The error that comes out is: undefined method `build_profile' for nil:NilClass
<%= form_for("user", :url => user_registration_path) do |f| %>
<%= f.email_field :email, :autofocus => true, :placeholder => 'E-mail Address' %>
<%= f.password_field :password, :placeholder => 'Password' %>
<%= f.password_field :password_confirmation, :placeholder => 'Password Confirmation' %>
<% #user.build_profile %>
<%= f.fields_for :profile do |profile_form| %>
<%= profile_form.text_field :name, :placeholder => 'Name' %>
<%= profile_form.text_field :address, :placeholder => 'Address' %>
<%= profile_form.phone_field :phone, :placeholder => 'Phone (example: 0193284647)' %>
<% end %>
<p><%= f.submit "Sign up", :class=>'btn btn-primary' %> </p>
<% end %>
Edit (Extra information):
should i add #user = #user.build_profile by creating a users_controller.rb instead?
Would it cause problems with devise?
yes you have to do
#user = #user.build_profile
in registrations_controller.rb . And,mention the customize controller in routes.rb in devise method.
You should so something like
class Registrations < Devise::RegistrationsController
def new
#user = User.new
#user = #user.build_profile
super
end
end

rails post parameters show but not inserted

I'm creating a small app in Rails 3.2.13, using bootstrap-sass gem.
I have the following situation:
My 'sign_up' controller has and 'index' action that creates a user like this:
#sign_up controller
def index
#user = User.new
end
Now, in my index.html.erb i have the form:
# sign_up controller => index.html.erb
<%= form_for #user, :html => {:class => 'form-horizontal'} do |f| %>
<div class = 'control-group'>
<%= f.label :username, :html => {:class => 'control-label'} %>
<%= text_field_tag :username, nil, :placeholder => 'Username' %>
</div>
<div class = 'control-group'>
<%= f.label :email, :html => {:class => 'control-label'} %>
<%= email_field_tag :email, nil, :placeholder => 'Email' %>
</div>
<div class = 'control-group'>
<%= f.label :password, :html => {:class => 'control-label'} %>
<%= password_field_tag :password, nil, :placeholder => 'Password' %>
</div>
<div class = 'control-group'>
<%= f.label :confirm_password, :html => {:class => 'control-label'} %>
<%= password_field_tag :confirm_password, nil, :placeholder => 'Confirm' %>
</div>
<%= f.submit 'Create', :class => 'btn btn-primary'%>
This will POST to users_controller, calling the create action:
# users controller
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
The problem is: the #user is saved, but the parameters are lost!
In the console log:
Started POST "/users" for 127.0.0.1 at 2013-05-29 12:14:47 -0300
Processing by UsersController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"wI5sNQV/lkn8GtYv5YkRLZ6HzxPg5MtoVXuarLulv30=", "username"=>"nonickname", "email"=>"no#bar.com", "password"=>"[FILTERED]", "confirm_password"=>"[FILTERED]", "commit"=>"Create"}
(0.1ms) begin transaction
SQL (0.9ms) INSERT INTO "users" ("admin", "created_at", "email", "password_hash", "password_salt", "updated_at", "username") VALUES (?, ?, ?, ?, ?, ?, ?) [["admin", nil], ["created_at", Wed, 29 May 2013 15:14:47 UTC +00:00], ["email", nil], ["password_hash", nil], ["password_salt", nil], ["updated_at", Wed, 29 May 2013 15:14:47 UTC +00:00], ["username", nil]]
(148.9ms) commit transaction...
Why that happens, and how can i fix this? I know the form should be a users_controller domain(i plan to fix that), but it doesn't seem to be the problem!
Thanks for any help!
I'll try to help you here as much as I can. Have a look at the console when I create a comment:
Started POST "/companies/1/comments" for 127.0.0.1 at 2013-05-29 20:06:02 +0300
Processing by CommentsController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"+J+ewToARuBybidK79V/3cFdX6=", "comment"=>{"content"=>"Lorem ipsum..."}, "commit"=>"Add Comments", "company_id"=>"1"}
(0.1ms) BEGIN
SQL (0.2ms) INSERT INTO `comments` (`commentable_id`, `commentable_type`, `content`, `created_at`, `updated_at`, `user_id`) VALUES (1, 'Company', 'Lorem ipsum...', '2013-05-29 17:06:02', '2013-05-29 17:06:02', 2)
(42.7ms) COMMIT
now when I say on conrtoller #comment = Comment.new(params[:comment]) means it will look for this line "comment"=>{"content"=>"Lorem ipsum dolor sit amet, ..."}
that means params[:comment] in my case is content, parameters are being sent as a hash and in your case you must have something like:
"user"=>{authenticity_token"=>"wI5sNQV/lkn8GtYv5YkRLZ6Hzx=", "username"=>"nonickname", "email"=>"no#bar.com", "password"=>"[FILTERED]", "confirm_password"=>"[FILTERED]"}`
in your console logs. I've looked a few times in your console logs and didn't see the user there and you can't call #user = User.new(params[:user]) as long as it is missing.
about the form, if you are using:
<%= form_for #user, :html => {:class => 'form-horizontal'} do |f| %>
you could use f to build your fields and write less this way
<%= form_for #user, :html => {:class => 'form-horizontal'} do |f| %>
<div class = 'control-group'>
<%= f.label :username, :html => {:class => 'control-label'} %>
<%= f.text_field :username, :placeholder => 'Username' %>
</div>
<div class = 'control-group'>
<%= f.label :email, :html => {:class => 'control-label'} %>
<%= f.email_field :email, :placeholder => 'Email' %>
</div>
<div class = 'control-group'>
<%= f.label :password, :html => {:class => 'control-label'} %>
<%= f.password_field :passwor, :placeholder => 'Password' %>
</div>
<div class = 'control-group'>
<%= f.label :confirm_password, :html => {:class => 'control-label'} %>
<%= f.password_field :confirm_password, :placeholder => 'Confirm' %>
</div>
<%= f.submit 'Create', :class => 'btn btn-primary'%>
Ok, it's solved!
The problem was the bootstrap form, i need to set the name attribute:
...
<div class = 'control-group'>
<%= f.label :email, :html => {:class => 'control-label'} %>
<%= email_field_tag :email, nil, :name => 'user[email]', :placeholder => 'Email' %>
</div>
...
Thanks!

Simple Form: Non object related attribute. How to?

I have a simple form that looks like this:
<%= simple_form_for #study,:url => studies_path, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.input :category, :collection => #categories, :label => "Category", :selected => #categories.first %>
<%= f.button :submit, t('add_form'),:class => 'btn-primary' %>
I want to add a new field in that form that will be merely visual sugar. It will be a helper to dynamically change the :category field.
How do I do that?
Use text_field_tag or whichever other _tag helper to generate a form element without attaching it to any specific attribute of the model:
<%= simple_form_for #study,:url => studies_path, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.input :category, :collection => #categories, :label => "Category", :selected => #categories.first %>
<%= text_field_tag :blah %>
<%= f.button :submit, t('add_form'),:class => 'btn-primary' %>
<% end %>

Rails 3: how to pull change password out to be its own separate form from devise

I'm using devise for my user registrations and I'd like to have a separate edit path for user's to change/update their passwords. I've pulled the devise registrations views out and created a separate registrations controller like described in Railscast 236
I've tried creating a new action called change_password in the registrations controller but when I try to set the route with match '/change_password', to => 'registrations#change_password' I get an AbstractController::Actions Not Found
registrations controller
class RegistrationsController < Devise::RegistrationsController
def create
super
session[:omniauth] = nil unless #user.new_record?
end
def destroy
resource.destroy
set_flash_message :notice, :destroyed
sign_out_and_redirect(self.resource)
end
def change_password
render_with_scope :edit
end
private
def build_resource(*args)
super
if session[:omniauth]
#user.apply_omniauth(session[:omniauth])
#user.valid?
end
end
routes.rb
match 'auth/:provider/callback' => 'authentications#create'
resources :authentications
devise_for :users, :controllers => {:registrations => 'registrations'}
resources :posts do
member do
get :likers
end
collection do
get :search
end
end
resources :relationships, :only => [:create, :destroy]
resources :appreciations, :only => [:create, :destroy]
root :to => "pages#home"
match '/contact', :to => 'pages#contact'
match '/about', :to => 'pages#about'
match '/help', :to => 'pages#help'
match '/blog', :to => 'pages#blog'
resources :users do
member do
get :following, :followers, :likes
end
resources :collections
end
end
views/registrations/change_password.html.erb
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :validate => true,
:html => { :method => :put }, :html => {:multipart => true}) do |f| %>
<%= devise_error_messages! %>
<p><strong>To change password, otherwise leave blank.</strong></p>
<p><%= f.label :current_password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :current_password %></p>
<p><%= f.label :password, "New password" %> <br />
<%= f.password_field :password %></p>
<p><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></p>
</div><br />
<p><%= f.submit "Update" %></p>
<% end %>
Try to pass match .. in the block of devise_for helper:
devise_for :users, :controllers => {:registrations => 'registrations'} do
match '/change_password', to => 'registrations#change_password'
end
I found this to be the easiest way to split the user edit form into edit & account
Originally I had
:name,
:email,
:avatar,
:location,
:website,
:bio,
:password (all in one form)
ROUTES (this provides route:
account_user GET /users/:id/account(.:format) users#account)
resources :users do
member do
get :following, :followers, :account
end
end
USERS_CONTROLLER.RB
before_filter :signed_in_user, only: [:index, :edit, :update, :destroy, :following, :followers, :account]
before_filter :correct_user, only: [:edit, :update, :account]
def edit
#user = User.find(params[:id])
end
def account
#title = "Account"
#user = User.find(params[:id])
end
def update
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated"
sign_in #user
redirect_to #user
elsif #title = "Account"
render 'account'
else
render 'edit'
end
end
(split form views)
EDIT.HTML.ERB
<%= form_for #user, :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :avatar %><br />
<%= f.file_field :avatar %>
<%= f.label :location %>
<%= f.text_field :location %>
<%= f.label :website %>
<%= f.text_field :website %>
<%= f.label :bio %>
<%= f.text_area :bio, placeholder: "About yourself in 160 characters or less..." %>
<%= f.submit "Update Profile", class: "btn btn-medium btn-primary" %>
<% end %>
ACCOUNT.HTML.ERB
<%= form_for #user, :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirm Password" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Update Account", class: "btn btn-medium btn-primary" %>
<% end %>
SIDE NAV BAR INSIDE OF EDIT AND ACCOUNT VIEWS, SO THE USER HAS ACCESS TO EDIT AND ACCOUNT FORM
<ol class="nav nav-tabs nav-stacked">
<% #user ||= current_user %>
<li>
<a href="<%= edit_user_path(#user) %>">
Profile
<i class="icon-chevron-right"></i>
</a>
</li>
<li>
<a href="<%= account_user_path(#user) %>">
Account
<i class="icon-chevron-right"></i>
</a>
</li>
</ol>

haml to html.erb

Can anyone please convert these haml code snippets to the equivalent html.erb?
1.
%h1
Edit Project Form
.edit_project
= semantic_form_for [:admin, #project], :url => admin_organization_project_path(#organization), :html => { :multipart => true } do |f|
= f.inputs do
= f.input :name
= f.input :status, :as => :select, :collection => Project.statuses
= f.input :overview
= f.input :funds_purpose
= f.input :goal
.files
= render :partial => 'admin/edit_photo', :collection => #project.project_photos, :locals => { :field_name => 'project[project_photos_attributes][][file]' }
= f.submit 'Save Project'
2.
%li.file.optional#project_project_photo_file_input
= label_tag 'File'
= image_tag edit_photo.file.url(:thumb) if edit_photo.file?
= file_field_tag field_name
For the second:
<li class="file optional" id="project_project_photo_file_input">
<%= label_tag 'File' %>
<%= image_tag edit_photo.file.url(:thumb) if edit_photo.file? %>
<%= file_field_tag field_name %>
</li>
for first:
<h1> Edit Project Form </h1>
<div class='edit_project'>
<%= semantic_form_for [:admin, #project], :url => admin_organization_project_path(#organization), :html => { :multipart => true } do |f| %>
<%= f.inputs do %>
<%= f.input :name %>
<%= f.input :status, :as => :select, :collection => Project.statuses%>
<%= f.input :overview %>
<%= f.input :funds_purpose %>
<%= f.input :goal %>
<div class='files' >
<%= render :partial => 'admin/edit_photo', :collection => #project.project_photos, :locals => { :field_name => 'project[project_photos_attributes][][file]' } %>
</div>
<% end %>
<%= f.submit 'Save Project' %>
<% end %>
</div>