I have created a new migration:
class AddSignatureToUser < ActiveRecord::Migration
def self.up
add_column :users, :signature, :text
end
def self.down
remove_column :users, :signature
end
end
Now my usertable has a new column called signature.
On my edit page I wrote:
<h1>Editing user</h1>
<% form_for(#user) do |f| %>
<%= f.error_messages %>
<div class="form-wrapper">
<p>
<label for="email">Email</label>
<%= f.text_field :email %>
</p>
<p>
<label for="user_signature">Signature</label>
<%= f.text_area(:signature, :value => #user.signature) %>
</p>
<div class="form-submit">
<%= f.submit 'Update', :class => "form-submit-button" %>
</div>
</div>
<% end %>
But this won't work.
In my controller I always get nil as value for signature. Any ideas why?
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
puts #user.signature #always nil
flash[:notice] = 'User was successfully updated.'
format.html { redirect_to(#user) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
Check to make sure you ran the migration for the proper environment (development, production)
RAILS_ENV=development rake db:migrate
This is the default, but you may be setting the environment somewhere. I think you'd get a method not found error if you hadn't, but just be sure, I've been hot by this before.
Next, if you're using the mongrel/webrick, try using the debugger, by starting the server with:
./script/server --debugger --environment=development
And then in your controller:
respond_to do |format|
debugger
if #user.update_attributes(params[:user])
puts #user.signature #always nil
...
And check what params is here, specifically params[:user][:signature], make sure it's getting passed correctly.
Lastly, in the view, all you need is:
<%= f.label :signature %>
<%= f.text_area :signature %>
The value will already be the current value since you're calling the form on #user in the form_for. The explicit setting of :value might be interfering somewhere
Two quick questions-
Why are we looking at edit.html.erb and update here? Did you already create this record with new.html.erb and create?
Why do you have <%= f.text_area(:signature, :value => #user.signature) %> instead of just <%= f.text_area :signature %>
Okay, I found my error!
In my user model, I had
attr_accessible :login, :email, :password, :password_confirmation
I added :signature and now it's working!
attr_accessible :login, :email, :password, :password_confirmation, :signature
Just to be sure, you have run rake db:migrate to run the migration, yes?
Related
So, I'm running into a fairly simple problem, where I cannot enter some simple form values into my SQLite DB (Rails).
Interestingly, the code doesn't fail - I submit the form, and am redirected successfully to the correct URL - and a record IS inserted into the DB, but the columns "name, type and user_id" are not filled with anything. To clarify, the columns are blank, for that new record.
If I comment out the code in the "create" and simply spit out the params (render plain: params[:plan].inspect) I do see all the correct parameters filled out, so I have a feeling there must be something wrong in the line:
#plan = Plan.new(params[:plan])
I'm really stuck here, any guidance would be much appreciated!
The create form
<h1> Create a new plan </h1>
<%= form_for :plan, url: plans_path do |f| %>
<p>
<%= f.label :name %><br>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :type %><br>
<%= f.text_field :type %>
</p>
<%= f.hidden_field :user_id, :value => current_user.id %>
<p>
<%= f.submit %>
</p>
<% end %>
plans_controller.rb
class PlansController < ApplicationController
def index
#plans = Plan.all
end
def show
#plan = Plan.find(params[:id])
end
def new
#plan = Plan.new
end
def create
#render plain: params[:plan].inspect
params.permit!
#plan = Plan.new(params[:plan])
if #plan.save
redirect_to #plan
else
redirect_to dashboard_path, :notice => "Plan NOT Created!"
end
end
end
The Model
class Plan < ActiveRecord::Base
end
Edit the plans_controller.rb:-
def create
#render plain: params[:plan].inspect
#plan = Plan.new(plan_params)
if #plan.save
redirect_to #plan
else
redirect_to dashboard_path, :notice => "Plan NOT Created!"
end
end
private
def plan_params
params.require(:plan).permit(:name,:type,:user_id)
end
Change the field name type as :-
rails g migration rename_fields_in_plans
class RenameFieldsInPlans < ActiveRecord::Migration
def change
rename_column :plans, :type, :plan_type
end
end
Then run the command:-
rake db:migrate
I'm using Mongoid, awesome_nested_fields gem and rails 3.2.8.
I have the functionality working on the client (adding multiple fields), but when I try to save I get a "undefined method `update_attributes' for nil:NilClass" error.
Here is all the relevant info:
profile.rb
class Profile
include Mongoid::Document
include Mongoid::Timestamps
has_many :skills, :autosave => true
accepts_nested_attributes_for :skills, allow_destroy: true
attr_accessible :skills_attributes
end
skill.rb
class Skill
include Mongoid::Document
belongs_to :profile
field :skill_tag, :type => String
end
View
<%= simple_form_for(#profile) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<div class="items">
<%= f.nested_fields_for :skills do |f| %>
<fieldset class="item">
<%= f.input :skill_tag, :label => 'Skills:' %>
Remove Skill
<%= f.hidden_field :id %>
<%= f.hidden_field :_destroy %>
</fieldset>
<% end %>
</div>
Add Skill
</div>
<div class="form-actions">
<%= f.button :submit, :class => 'btn' %>
</div>
<% end %>
profiles_controller.rb
# PUT /profiles/1
# PUT /profiles/1.json
def update
#profile = Profile.find(params[:id])
respond_to do |format|
if #profile.update_attributes(params[:profile])
format.html { redirect_to #profile, notice: 'Profile was successfully updated.' } # Notice
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
*********** UPDATE ************
I ended up switching to Ryan's nested_form gem and it works like a charm.
Your message directly points to the line of execution where it failed, ergo the line:
if #profile.update_attributes(params[:profile])
The problem is that the #profile instance variable is nil and rails can not find the update_attributes method for a nil object.
You could easly check your server log for the params hash, to see what params[:id] (probably it isn't defined at all) by going in the terminal where you started your app.
Or you can check your development log when being in your app folder:
tail -n 1000 development.log | egrep params
Hey guys, this has been plaguing me all week long. I am new to Rails, so please be gentle :)
My root problem is I'm trying to write a form_for Post that will use autocompletion on an input to tie the post to a Client. The database is looking for a client_id, not a text name.
So I have tried a custom validation that will lookup the text value and replace it with an id.
My Post.rb file has this:
class Post < ActiveRecord::Base
belongs_to :client
attr_accessor :client_name
attr_accessible :client_name
before_validation_on_create :validate_client
def validate_client
self.client_id = 1 # just a test
end
def client_exists(passed_name)
return Client.where(:full_name => passed_name).first.blank?
end
end
But when I do this, none of the form variables get passed. The database gets all blank entries except for the client_id. How can I accomplish this? Why aren't my form variables being passed in? Many thanks in advance.
Edit 1: added create definition from posts_controller.rb
def create
#post = Post.new(params[:post])
respond_to do |format|
if #post.save
format.html {
redirect_to(posts_url) # redirect_to(#post, :notice => 'Post was successfully created.')
}
format.xml { render :xml => #post, :status => :created, :location => #post }
format.js
else
format.html { render :action => "new" }
format.xml { render :xml => #post.errors, :status => :unprocessable_entity }
end
end
end
Edit 2: Thanks to #apneadiving, I changed the attr_accesible to include the other attributes, and that passes the POST entries into the db.
attr_accessible :client_id, :time, :content, :client_name
But when I change the validate_client function to search for the client_id,
def validate_client
passed_name = self.client_name
if client_exists(passed_name)
c = Client.where(:full_name => passed_name).first
self.client_id = c.id
else
errors.add_to_base "Error"
end
end
It always gives me this error:
Called id for nil, which would
mistakenly be 4 -- if you really
wanted the id of nil, use object_id
Edit 3: Here's my post form. I can't get the value of :client_name properly.
<%= form_for(#post) do |f| %>
<%= render 'common/error_messages', :object => f.object %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_area :content, :size => "50x6" %>
</div>
<div class="field">
<div class="sub-field">
<%= f.label :client_name %><br />
<%= f.text_field :client_name, :size => "26" %>
</div>
<div class="sub-field">
<%= f.label :date %><br />
<%= f.text_field(:time, :class => 'date', :size => "10", :value => Date.today.strftime('%m/%d/%Y')) %>
</div>
<div class="sub-field">
<%= f.label :time %><br />
<%= f.time_select :time %>
</div>
</div>
<div class="actions clear">
<%= f.submit %>
</div>
<% end %>
Edit 4: The solution. I was struggling to get the :client_name due to my text being too far tabbed in (I was originally privatizing the function and then took the word "private" out). A modified version of #apneadiving's answer solved it for me!
class Post < ActiveRecord::Base
belongs_to :client
attr_accessor :client_name
validate :validate_client
def validate_client
passed_name = self.client_name
unless client = Client.find_by_full_name(passed_name).blank?
self.client_id = Client.find_by_full_name(passed_name).id
else
errors.add(:client_name, "'#{passed_name}' cannot be found.")
end
end
end
Beware of your attr_acessible:
if you set one, you have to set all the variables that can be set through params. Otherwise they are protected against mass assignment
EDIT 1:
seems c.id is nil which means your client_exists function doesn't work as expected. Try the following (not tested):
def validate_client
unless client = Client.find_by_full_name(client_name).nil?
client_id = client.id
else
errors.add_to_base "Error"
end
end
Your client_exists code is wrong, it returns true if it doesn't exist.
Also, since your client_exists and the validation reuse the same query i would rewrite that a bit.
def validate_client
passed_name = self.client_name
existing_client = Client.where(:full_name => passed_name).first
if existing_client
self.client_id = existing_client.id
else
errors.add_to_base "Error"
end
end
I've get a little problem.
My controller:
def new
#company = Company.new
#title = "Create company"
end
def create
#company = Company.new(params[:company])
#company.admin_id = current_user.id
if #company.save
flash[:success] = "Company created!"
redirect_to admin_path
else
#title = "New company"
render 'new'
end
end
new.html.erb
<%= debug params[:company] %>
<% form_for #company, :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<%= render 'fields', :f => f %>
<div class="actions">
<%= f.submit "Submit company!" %>
</div>
<% end %>
Company.rb model
validates :name,
:presence => true,
:length => { :maximum => 20 }
validates_attachment_presence :logo
But after submitting form I've get anyway only one error:
Name can't be blank
Of course I'm filling name and logo fields.
Any ideas? Thanks.
You didn't include your _fields partial, and that's probably where your problem is.
Make sure your inputs have appropriate name attributes.
Try to instantiate your model in console and see if validations really work.
You can try something like this: c = Company.new; c.valid?; c.errors and you'll see your errors hash in console.
Sorry for this question but I can't find my error!
In my Project I have my model called "team".
A User can create a "team" or a "contest". The difference between this both is, that contest requires more data than a normal team.
So I created the columns in my team table.
Well... I also created a new view called create_contest.html.erb :
<h1>New team content</h1>
<% form_for #team, :url => { :action => 'create_content' } do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description %>
</p>
<p>
<%= f.label :url %><br />
<%= f.text_fiels :url %>
</p>
<p>
<%= f.label :contact_name %><br />
<%= f.text_fiels :contact_name %>
</p>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
In my teams_controller, I created following functions:
def new_contest
end
def create_contest
if #can_create
#team = Team.new(params[:team])
#team.user_id = current_user.id
respond_to do |format|
if #team.save
format.html { redirect_to(#team, :notice => 'Contest was successfully created.') }
format.xml { render :xml => #team, :status => :created, :location => #team }
else
format.html { render :action => "new" }
format.xml { render :xml => #team.errors, :status => :unprocessable_entity }
end
end
else
redirect_back_or_default('/')
end
end
Now, I want on my teams/new.html.erb a link to "new_contest.html.erb".
So I did:
<%= link_to 'click here for new contest!', new_contest_team_path %>
When I go to the /teams/new.html.erb page, I get following error:
undefined local variable or method `new_contest_team_path' for #<ActionView::Base:0x16fc4f7>
So I changed in my routes.rb, map.resources :teams to map.resources :teams, :member=>{:new_contest => :get}
Now I get following error: new_contest_team_url failed to generate from {:controller=>"teams", :action=>"new_contest"} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: ["teams", :id, "new_contest"] - are they all satisfied?
I don't think adding :member => {...} is the right way doing this. So, can you tell me what to do? I want to have an URL like /teams/new-contest or something.
My next question: what to do (after fixing the first problem), to validate presentence of all fields for new_contest.html.erb? In my normal new.html.erb, a user does not need all the data. But in new_contest.html.erb he does. Is there a way to make a validates_presence_of only for one action (in this case new_contest)?
UPDATE:
Now, I removed my :member part from my routes.rb and wrote:
map.new_contest '/teams/contest/new', :controller => 'teams', :action => 'new_contest'
Now, clicking on my link, it redirects me to /teams/contest/new - like I wanted - but I get another error called:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
I think this error is cause of #team at <% form_for #team, :url => { :action => 'create_content_team' } do |f| %>
What to do for solving this error?
I'm not sure about how your models work, but in my code I've always written;
#team.user_id = #current_user.id
instead of
#team.user_id = current_user.id
That would mean the id wasn't being passed to the controller giving you the error, wouldn't it?
Okay, I found my errors.
For the record:
First of all, I forgot to write the code inside my def new_contest. Here it is:
def new_contest
if #can_create
#team = Team.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #team }
end
else
redirect_back_or_default('/')
end
end
There were several typos, too, in my .erb file like text_fiels instead of text_field or create_content instead of create_contest.
current_user is working fine for me.