Rails: Spaces in string used for name causes validation error - ruby-on-rails

I have a User Group table with a group_name value that is entered when the group is created. If there is a space in the group name, for example "Team Lol", the group name is still created, but it is not assigned to the current user, and it throws the error message in my if/else statement in the controller. Code is as follows:
Controller:
def create
#group = current_user.create_user_group(group_params)
current_user.user_group = #group
current_user.save
if #group.valid?
redirect_to '/user_groups/'+#group.group_name, :notice => "Your group has been created"
else
redirect_to '/user_groups/', :error => "Error: group name may already be taken. Search, or try a new name."
end
end
Model
class UserGroup < ActiveRecord::Base
has_many :users
has_secure_password
validates :password, :presence => true
validates :group_name, :presence => true, :uniqueness => true
before_validation :strip_blanks
def strip_blanks
self.group_name = self.group_name.strip
end
Create form:
<div class="form-group">
<label for="Group Name">Enter group name</label>
<%= f.input :group_name, :required => true, :autofocus => true, :maxlength => 40, :input_html => { :class => "form-control" }, :label => false, :placeholder => "Group name" %>
</div>
<div class="form-group">
<label for="Password">Password</label>
<%= f.input :password, :required => true, :autofocus => true, :maxlength => 40, :input_html => { :class => "form-control" }, :label => false, :placeholder => "Group password" %>
</div>
<%= f.button :submit, :class => "btn btn-md btn-warning" %>
</div>

I think it's because you are already creating the group in this line:
#group = current_user.create_user_group(group_params)
then, you're assigning (and Rails tries to create it again) here:
current_user.user_group = #group
current_user.save
I think you should remove the last two calls, given that if
#group = current_user.create_user_group(group_params)
succeeded, then the group is valid. The action that will follow is to redirect there.
Disclaimer: this is off the top of my head.

I just got it - it was a URI issue.
When a name with a space was created, the user was routed to /user_groups/The A Team.
It my routes I have /user_groups/:group_name routing to that group's home page.
However, since those spaces don't register correctly, the app seems to run another POST request to create a group instead.
I simply changed my redirect to redirect_to '/user_groups/'+#group.group_name.gsub(/\s/,'%20'), :notice => "Your group has been created"
Let me know if you think there's any problems with the way I handled this.
Thanks for everyones help,
Daniel

Related

form validation with simple_form and html5

The easy way from our page is
welcome-controller add an email -> second_controller create an new object with the E-Mailadddress.
we have a welcome-controller that shows our welcome-page. At this page you can type an e-mailaddress which will give to an other controller. We work with simple_form
If we that this config.browser_validations = false and enter an "normal" text we get an error on the create action. In the older version, without simple_form we get an validation-error.
If we enable this we get the html5 validation. but when the browser doesn't support html5?
Our model is here
validates :owner_email,
:presence => true,
:format => { :with => /\A[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]+\z/ },
:on => :create
Our welcome-view is here
<p>
<h2>Create a list without registration.</h2>
<%= simple_form_for([#list], :html => {:class => 'well' }) do |f| %>
<%= f.input :owner_email, :label => false, :placeholder => 'Your Email.' %>
<%= f.button :submit, "Create", :class => "btn-primary" %>
<% end %>
</p>
Our create-action from the second controller is this
def create
# create a new list and fill it up
# with some default values
#list = List.new(
:title => "List",
:description => "Beschreibung",
:owner_email => "test#domain.com",
:admin_key => generate_admin_key)
#list.update_attributes(params[:list])
respond_with(#list) do |format|
format.html {#
redirect_to :action => "admin", :id => #list.access_key, :status => 301}
end
end
What have we to change that we get errormessages in the html4 version? can everyone help us please?
Just add a :message parameter. Unless you changed simple_form configuration, message errors should be shown on the right side of the field with errors.
validates :owner_email,
:presence => true,
:format => { :with => /\A[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]+\z/ ,
:message => 'Invalid e-mail! Please provide a valid e-mail address'},
:on => :create

How to create a parent model through a child controller in rails 3? (belongs_to association)

I have two resources: Topics and Posts.
I am trying to figure out how I can create a Topic through the Post controller.
The models look like this:
class Topic < ActiveRecord::Base
has_many :posts, :dependent => :destroy
validates :name, :presence => true,
:length => { :maximum => 32 }
attr_accessible :name
end
class Post < ActiveRecord::Base
belongs_to :topic, :touch => true
has_many :comments, :dependent => :destroy
accepts_nested_attributes_for :topic
attr_accessible :name, :title, :content, :topic
end
posts/_form.html.erb:
<%= simple_form_for #post do |f| %>
<h1>Create a Post</h1>
<%= f.input :name, :label => false, :placeholder => "Name" %>
<%= f.input :title, :label => false, :placeholder => "Title" %>
<%= f.input :content, :label => false, :placeholder => "Content" %>
<%= f.input :topic, :label => false, :placeholder => "Topic" %>
<%= f.button :submit, "Post" %>
<% end %>
posts_controller.rb#create:
def create
#post = Post.new(params[:topic])
respond_to do |format|
if #post.save
format.html { redirect_to(#post, :notice => 'Post was successfully created.') }
else
format.html { render :action => "new" }
end
end
end
With posts/_form.html.erb I can create posts, but an associated topic is not created along with it. Can anyone tell me why I get this behavior and possibly how to correct it? I'm using Ruby 1.9.2, Rails 3.0.7 and the simple_form gem.
Railscasts has several episodes about this problem.
episode 16(subscription needed)
Source code:
https://github.com/railscasts/016-virtual-attributes-revised
And this episode
http://railscasts.com/episodes/57-create-model-through-text-field
views/products/_form.rhtml
<p>
<label for="product_category_id">Category:</label><br />
<%= f.collection_select :category_id, Category.find(:all), :id, :name, :prompt => "Select a Category" %>
or create one:
<%= f.text_field :new_category_name %>
</p>
models/product.rb
belongs_to :category
attr_accessor :new_category_name
before_save :create_category_from_name
def create_category_from_name
create_category(:name => new_category_name) unless new_category_name.blank?
end
I think Ryan's solution on category is more elegant than #nathanvda 's option 1. As it deal the data in Model instead of Controller. If you need to do same work in different controllers/actions, you will see the benefits.
Depending on what you want to do, i can see two options.
Option 1: Use a text-box to create or find an existing topic (as you had). In your controller you would write something like:
def create
topic_name = params[:post].delete(:topic)
#topic = Topic.find_or_create_by_name(topic_name)
#post = Post.new(params[:post])
#post.topic = #topic
if #post.save
format.html { redirect_to(#post, :notice => 'Post was successfully created.') }
else
format.html { render :action => "new" }
end
end
That is the quick and dirty way. It will, for each topic you type, try to find that topic, by name, or create it and assign it. But, this is error-prone. If your sets of topics is limited, there is a much easier way.
Option 2: use a select-box, a list of available topics. In your view write:
<%= simple_form_for #post do |f| %>
<h1>Create a Post</h1>
<%= f.input :name, :label => false, :placeholder => "Name" %>
<%= f.input :title, :label => false, :placeholder => "Title" %>
<%= f.input :content, :label => false, :placeholder => "Content" %>
<%= f.association :topic %>
<%= f.button :submit, "Post" %>
<% end %>
That will render a select-box with the possible topics. And in your controller you just have to write:
def create
#post = Post.new(params[:post])
if #post.save
format.html { redirect_to(#post, :notice => 'Post was successfully created.') }
else
format.html { render :action => "new" }
end
end
While this second option is really easy, it is less easy to add topics on the fly. You could do something in between, using an autocomplete field, that will either allow looking up values if they exist, or add new values if they don exist.
Hope this helps.
Are you getting mass assignment errors in the server log? You may need to add :topic_attributes to your attr_accessible list.

How to Validate the value of a form in Rails 3

I'm trying to validate the value of a form (a checkbox actually) in a model, but am having a lot of trouble finding what to pass validates:
validates :agreement, :agreement => true
I've gotten other things to work like:
validates :password, :presence => true, :length => {:minimum => 6, :maximum => 25}, :confirmation => true
My view looks like this:
<% form_for :signup_form, :url => {:controller => "user", :action => "post_signup"} do |f| %>
...
<%= f.check_box( :agreement ) %> I agree to the <%= link_to("Terms of Service", :controller=> "about", :action => "terms") %> and <%= link_to("Privacy Policy", :controller=> "about", :action => "privacy") %>
...
Which then goes to my controller:
agreement = params[:signup_form][:agreement]
new_user = User.create(:login_name => login_name, :first_name => first_name, :last_name => last_name, :email => email, :password => password, :agreement => agreement, :created_at => DateTime.now())
And then my model.
Thanks for any help you can offer in advance.
You might be looking for :acceptance => true or validates_acceptance_of
You'll want to display your errors on the page, and ensure your validation is working at all. I would re-implement your validation as:
# app/models/user.rb
class User < ActiveRecord::Base
validates :agreement do |ag|
ag.errors.add "Must agree to the terms" unless self.agreement
end
end
see http://asciicasts.com/episodes/211-validations-in-rails-3 for a comprehensive treatment, including a nice way to display the errors.

Return Model and Associated Polymorphic Models

I am working with polymorphic associations and having some trouble. My models are setup like so:
class User < ActiveRecord::Base
has_one :phone, :as => :callable, :dependent => :destroy
end
class Client < ActiveRecord::Base
has_one :phone, :as => :callable, :dependent => :destroy
end
class Phone < ActiveRecord::Base
belongs_to :callable, :polymorphic => true
end
In my Users Controller
def create
#user = User.new(params[:user])
if #user.save
#user.phone.create(:area_code => params[:user][:area_code], :phone => params[:user][:phone])
redirect_to #user, :notice => "Account created successfully!"
else
render 'new'
end
end
In the development log I see where the phone and user are being inserted correctly, but when I go to edit the user, the fields for phone in the form are blank. Here is my edit method:
def edit_employee
#user = User.find(params[:id])
#title = "Edit #{#user.name}"
end
My edit user form looks like this.
- form_for #user do |f|
- if #user.errors.any?
.error_messages
%h2 Please correct the following errors
%ul
- for message in #user.errors.full_messages
%li= message
%p
= f.label :name, "Name"
= f.text_field :name
%p
= f.label :email, "Email Address"
= f.text_field :email
%p
= f.label :phone, "Phone"
= f.text_field :area_code, :style => "width: 50px;"
= f.text_field :phone, :style => "width: 100px;"
= f.label :ext, "Ext."
= f.text_field :extension, :style => "width: 60px;"
%p
= f.label :password, "Password"
= f.password_field :password
%p
= f.label :password_confirmation, "Confirm Password"
= f.password_field :password_confirmation
%p.button= f.submit
I know I should be adding something to this edit method, perhaps
#phone = #user.phone
But that didn't work either. This is the first go round with polymorphic associations so any help and and pointers are much appreciated. I watched the Railscasts on this topic but it didn't seem to follow my underlying functionality. Once again, thanks in advance for any help and let me know if any more information is needed!
you should look into using fields_for and nested_attributes. http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
Do you have attr_accessible set in the user.rb model? If not I would add it because that is a security issue.
Ok I added the
accepts_nested_attributes_for :phone
in the user model. I also added the fields for phone in the new user form like so
%p
- fields_for #user.phone do |phone|
= phone.label :phone, "Phone"
= phone.text_field :area_code, :style => "width: 50px;"
= phone.text_field :phone, :style => "width: 100px;"
= phone.label :ext, "Ext."
= phone.text_field :extension, :style => "width: 60px;"
but now I am getting the ActionView::Template::Error (undefined method `model_name' for NilClass:Class) exception.
And yes I have attr_accessible in my model. I just placed a very watered down version in here.

An AuthLogic form is giving me incorrect validation errors -- why?

I set up AuthLogic for Rails according to the AuthLogic example: http://github.com/binarylogic/authlogic_example.
I can log on successfully to the system, but when accessing users/new.html.erb to register a new user, the form returns the following validation errors:
Email is too short (minimum is 6 characters)
Email should look like an email address.
Login is too short (minimum is 3 characters)
Login should use only letters, numbers, spaces, and .-_# please.
Password is too short (minimum is 4 characters)
Password confirmation is too short (minimum is 4 characters)
None of these errors exist in the data I am entering.
# new.html.erb
<%= form.label :login, nil, :class => "label" %><br />
<%= form.text_field :login, :class => "inputBox",
:name => "login", :type => "text" %><br />
<%= form.label :password, form.object.new_record? ? nil : "Change password", :class => "label" %><br />
<%= form.password_field :password, :class => "inputBox",
:name => "password", :type => "text" %><br />
<%= form.label "Confirm password", nil, :class => "label" %><br />
<%= form.password_field :password_confirmation, :class => "inputBox",
:name => "password_confirmation", :type => "text" %><br />
<%= form.label :email, nil, :class => "label" %><br />
<%= form.text_field :email, :class => "inputBox",
:name => "email", :type => "text" %><br />
# Users controller
def new
#user = User.new
render :layout => "forms"
end
I think the problem is that the data isn't being transferred somehow and therefore AuthLogic doesn't think the inputs are sufficient. Do you have any idea why AuthLogic is telling me the data doesn't satisfy its validation?
------MORE INFO------
# User model
class User < ActiveRecord::Base
acts_as_authentic
belongs_to :authenticable, :polymorphic => true
end
# Users controller, def create:
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = "Account registered!"
redirect_back_or_default account_url
else
render :action => :new
end
end
Check params[:user] and see if it's sending the correct values
You can also remove the validation in the model that acts_as_authentic adding the following fields:
acts_as_authentic do |c|
c.validate_login_field = false
c.validate_email_field = false
c.validate_password_field = false
end
Just a thought, do you have mass assignment disabled somewhere higher up than your model class?
I have had this happen before where I disabled mass assignment of attributes in my initializers, then forgot to set my model's attributes as accessible using attr_accessible for all required attributes inside the model class.
One thing that is not clear in the documentation and in the videos, is that :password is still required in the attr_accessible line even though you may have crypted_password in the model (i.e. attr_accessible :password).
I'm not certain, but i'm assuming that authlogic uses this password variable to hold the clear text version before it encrypts it.
I don't recommend setting c.validate_password_field = false because this turns off encryption as well.

Resources