I am attempting to run a form destined for the app's home page, which uses simultaneously tableless and database-stored variables. I need to run validations on the form. I need to run validations, one in particular which compares two of the tableless values.
My eventual goal is to get the validations running client-side via the following gem:
https://github.com/bcardarella/client_side_validations
Initially though, I want to get the validations working upon form submission.
A first question that arises is which model should hold the mail validation logic. The homePage has to do many things, is not a model and, above all, the search results lead to a different controller.
Subsequently, although some validations are one-off and don't really need to be factored out, I would place the validation logic in app/validators/different_objects_validator.rb
class DifferentObjectsValidator < ActiveModel::Validator
def different_objects
errors.add(:different_objects, "cannot be less than quantity") unless
self.quantity >= self.different_objects
end
end
Form data is:
<%= form_tag result_quote_request_path, :method => :get do %>
Base <%= number_field :quote, :base, :size => 5 %>
Height <%= number_field :quote, :height, :size => 5 %>
Quantity <%= number_field :quote, :quantity, :size => 5, :value => 1 %>
Different source objects <%= number_field :quote, :different_objects, :size => 5, :value => 1 %>
<%= submit_tag "find", :name => nil %>
<% end -%>
Then
class Quote < ActiveRecord::Base
include ActiveModel::Validations
validates :different_objects, different_objects_valid => true
After restarting Thin web server, this results in:
ActionView::Template::Error (undefined method `name' for nil:NilClass):
But this is a bit of a red herring: without the validation, the form generates a search result
I realize many things may be wrong here. I am having trouble getting the proper focus of where the validations are invoked combined with tableless states.
Your error comes from the following:
<%= submit_tag "find", :name => nil %>
Simply do
<%= submit_tag "find" %>
Related
I'm trying to make an invoicing app. The form to create an invoice should include a collection of check boxes so the user can choose which lessons to invoice, but I'm getting this error: undefined method 'collection_check_boxes'.
Here are the models involved:
class Lesson < ActiveRecord::Base
attr_accessible :lesson_time, :lesson_date, :invoice_id
belongs_to :invoice
end
class Invoice < ActiveRecord::Base
attr_accessible :amount, :due_date
has_many :lessons
end
And the view:
<%= form_for(#invoice) do |f| %>
<fieldset>
<%= f.label :lessons %>
<%= f.collection_check_boxes(:lessons, Lesson.all, :id, :lesson_date) %>
<%= f.submit %>
</fieldset>
<% end %>
collection_check_boxes is not a method of form_builder. Either put:
<%= collection_check_boxes(:lessons, Lesson.all, :id, :lesson_date) %>
This will generate html which won't associate with your model (you won't be able to use MyModel.new(params[my_model]) and expect to get proper response. You would either have to manually call my_model.lessons = params[:lessons] or you can pass a html name parameter to conform your check box name to rails convention).
Or, if you are using formtastic as you tagged it, you can use this:
<%= f.input :lessons, :as => :check_boxes, :collection => Lesson.all %>
I suspect that since you tagged your post ruby-on-rails-3, you might be trying to use a rails 4 method inside a rails 3 project.
http://makandracards.com/makandra/32147-rails-4-introduced-collection_check_boxes
You'll likely need to use good old check_box_tag instead.
I have seen RailsCasts#302 which describes about the in-place editing using the best_in_place gem. Over there in for gender option Ryan uses the array inside the show.html.erb and makes it a dropdown box(see the gender section where he explicitly defines an array).
<p>
<b>Gender:</b>
<%= best_in_place #user, :gender, type: :select, collection: [["Male", "Male"], ["Female", "Female"], ["", "Unspecified"]] %>
</p>
But what I want is I have defined an array inside the Model itself like: (because my array elements are not simple and short in count)
For eg:
user.rb
class User < ActiveRecord::Base
def authencity_types
['Asian', 'Latin-Hispanic', 'Caucasian']
end
end
How am I going to use this array elements as dropdown using the best_in_place syntax.
PS: I did try something like this
<% #users.each do |user| %>
<%= best_in_place user, :authencity, type: :select, :collection => User::authencity_types %>
<% end %>
But it says undefined method authencity_types
You're defining an instance method on the User model, so try this.
<% #users.each do |user| %>
<%= best_in_place user, :authencity, type: :select, :collection => user.authencity_types %>
<% end %>
Alternatively you can define that as a class method like this.
class User < ActiveRecord::Base
def self.authencity_types
['Asian', 'Latin-Hispanic', 'Caucasian']
end
end
Or you may want to consider using a constant if it does not need to be dynamic.
If there are semantic errors in the form (mostly from external API), I'd like to add an explanatory message, like so:
<%= semantic_form_for #order, :url => checkout_purchase_url, :html => {:class => 'payment'}, :wrapper_html => { :class => "field" } do |f| %>
<% if f.has_errors? %>
<p>There were errors that prevented your order from being submitted. If you need assistance, please contact us toll-free at <strong>1-800-555-5555</strong>.</p>
<%= f.semantic_errors %>
<% end %>
<% end %>
However, has_errors? is a protected method. Is there a way that I can do this? Thanks.
If you have nested attributes you won't see any errors associated with them. To ensure you get all base errors and any nested attributes errors. Make sure your model contains:
validates_presence_of :nested_object
validates_associated :nested_object
and in your form:
f.semantic_errors *f.object.errors.keys
Not as hard as I thought. I fixed it by checking for errors on the object instead of the form:
<% if #object.errors.any? %>
<p>There were errors that prevented your order from being submitted. If you need assistance, please contact us toll-free at <strong>1-800-555-5555</strong>.</p>
<%= f.semantic_errors %>
<% end %>
Thanks for those who viewed.
For completeness, here's an alternative approach if you want to show similarly helpful messages on each field:
= f.label :title
- if f.object.errors.any?
.error = f.object.errors[:title].flatten.join(' and ')
= f.text_field :title
This gives a nicely formatted and easily-styled list of errors for each field. (You can use semantic_errors instead of object.errors if you prefer, same result.)
I have the following singular route:
scope '/seller' do
resource :seller_profile, :path => "/profile", :only => [:show, :edit, :update]
end
and the following controller:
class SellerProfilesController < ApplicationController
before_filter :validate_user_as_seller
def show
#seller_profile = current_user.seller_profile
end
def edit
#seller_profile = current_user.seller_profile
end
def update
#seller_profile = current_user.seller_profile
if #seller_profile.update_attributes(params[:seller_profile])
redirect_to(seller_profile_path, :notice => 'Profile was successfully updated.')
else
render :action => "edit"
end
end
end
I use a singular route given that the user must be authenticated before gaining access to the controller and therefore I can get the seller_profile from the user logged in.
This works like a charm, with only one problem. When I edit the seller_profile and validation error happen, the form is edited again and the errors are displayed correctly. The problem is that rails appends to the url the id of the edited record. For instance,
when I first edit the record, the url is:
http://0.0.0.0:3000/seller/profile/edit
but if the form is submitted with validation errors, the form itself is redisplayed under
http://0.0.0.0:3000/seller/profile.2
where 2 is the ID of the record being edited.
The form is the following:
<%= simple_form_for #seller_profile do |f| %>
<%= f.input :name %>
<%= f.input :description %>
<%= f.submit %>
<% end %>
Everything, as said, works great but I would totally mask the ID in the url. What should I do?
I have not really worked too much with simple_form_for. But it looks like it is guessing your url always as if they were not single resources. You can provide a custom one:
<%= simple_form_for #seller_profile, :url => seller_profile_path do |f| %>
<%= f.input :name %>
<%= f.input :description %>
<%= f.submit %>
<% end %>
I'm new to Rails and I've just spent another hour Googling and not finding an example.
So I have a simple form that I need to submit to an API. So I tried submitting it to the API directly but got advice that I do it in my app so I can do something with the results. Anyway, here's my simple form:
<%= form_tag(:action => 'submit') do |f| %>
<%= f.text_field :email, :value => "Your email address...", :class => "text", :id => "email", :name => 'email',
:onFocus => "change(this,'#222222'); this.value=''; this.onfocus=null;",
:size => "26" %>
<%= f.hidden_field :ref_code, :id => 'ref_code', :name => 'ref_code', :value => #referralid %>
<%= submit_tag "Enter To Win", :class => "button-positive submit" %>
<% end %>
Everything I'm seeing has forms that that use a model, I have no need to persist this data, just pass it on to the API.
So my thought was I just create an action in the home controller, where this page lives and have the action submit to it but I get a RoutingError and it's: No route matches {:action=>"submit", :controller=>"home"}
So what do I need to put in the Routes.rb? I tried:
namespace :home do
resources :submit
end
No Joy... I'm sure it's simple but I just can't find the right example.
I think that you should have a look at the ruby guides, it's very well explained (but I don't think it talks about API) and it will save you a lot of time in the future, I swear.
Not sure what you mean but I see some wired stuff, so I hope to be useful, but if you're following some tutorials from the net let us know the link.
Basically what I do is always to call an action of a controller (MVC), following this way you should have a controller (?? apis_controller ??) and call one action of it.
So you want to use form_tag instead of form_for because you're not addressing a model, therefor you want to get rid of f. and use suffix _tag (api).
<%= form_tag(send_api_path) do %>
<%= text_field_tag :email, "Your email address..." %>
<%= hidden_field_tag :ref_code, #referralid %>
<%= hidden_field_tag :api_name, 'your_api_name' %>
<%= submit_tag "Enter To Win" %>
<% end %>
Then, in your apis_controller.rb you create an action send where you send and manage your request.
#apis_controller.rb
def send
# TODO: your code here
end
Another thing is to set the routes, something like
#routes.rb
match 'apis/send' => 'apis#send', :as => :send_api
I'm sure this is not 100% working code, but it should be useful
How to call the api? I had I fast look and found this.
When you ask for help it's always good to attach the error you get, this makes it easier for people to understand the problem.