because I'm pretty new to Ruby on Rails I'll explain what I did. I've got a virtual attribute in my model called testing. I've defined it like this:
class Comment < ActiveRecord::Base
attr_accessor :testing
attr_accessible :user_name, :comment, :user, :testing
I then added custom method for custom validation like this:
validate :custom_validation
I also added the method, of course:
def custom_validation
# a bit of custom_validation
end
I then added a field in my form:
<%= form_for(#comment) do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<%= f.hidden_field :post_id, :value => #post.id %>
<% if !signed_in? %>
<div class="field">
<%= f.label :user_name %>
<%= f.text_field :user_name, :class => "user_field" %>
</div>
<% else %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<% end %>
<div class="field">
<%= f.label :comment %>
<%= f.text_area :comment, :style => "height: 50px; width: 80%;" %>
</div>
<div class="field pin">
<%= f.label :testint %>
<%= f.text_field :testing, :class => "user_field" %>
</div>
<div class="buttons">
<%= f.submit "Speichern" %>
</div>
<% end %>
That's all I did. So please don't assume I did something else I didn't describe here, because I didn't ;)
My problem is, that my virtual field testing is always nil inside of my custom_validation method. Unless I run the validation in the console:
co = Comment.new
co.testing = "Hello"
co.valid?
I've checked using the logger. If I run via the console the testing-field isn't nil. If I run it via the browser, it is. It seems that the parameter is somehow not passed to the model correctly. I hope I just missed something really obvious. Hope you can help me.
Cheers,
Michael
It has to do with what's in your create or update actions. The scaffold generator will put in code to set real attributes, but does not call setter methods from attr_accessor.
add attr_reader :testing to your model!
Related
I'm trying to create #booking and #booking.build_passenger in form_for with nested attributes in Rails 4.2.1
The error I get:
As you see in the console at the bottom of the image:
1. params.require(:booking) returns a Hash-like params for #booking
2. params.class returns ActionController::Parameters
As the params seems to behave correctly, IMO the problem hides somewhere in the form:
<%= form_for #booking do |f| %>
<%= f.hidden_field :flight_id, value: params[:flight_id] %>
<%= render 'flights/flight_info' %>
<div class="field">
<b><%= f.label :num_tickets, "Tickets" %></b>
<%= f.select(:num_tickets, #num_tickets) %>
</div><br>
<h4>Passenger info:</h4>
<%= f.fields_for #booking.build_passenger do |pass| %>
<div class="field">
<%= pass.label :name %>
<%= pass.text_field :name %>
</div>
<div class="field">
<%= pass.label :email %>
<%= pass.email_field :email %>
</div>
<% end %>
<%= f.submit 'Book Flight!' %>
<% end %>
Booking model:
class Booking < ActiveRecord::Base
belongs_to :flight
belongs_to :passenger
accepts_nested_attributes_for :passenger
end
Question: Where and how do I have to edit my code for the app to start creating #booking instances + #booking.build_passenger()
Your booking_params needs to be something like:
def booking_params
params.require(:booking).permit(:flight_id, :num_tickets, passenger_attributes: [:id, :name, :email])
end
When I enter something into a number_field and post the form to the controller, Rails can't save because i have a numericality validation:
validates :rating, numericality: { greater_than: 0, less_than: 6 }
I debugged the controller by this piece of code:
raise "It exploded into pieces!" unless #comment.save
The exception I used for debugging said that my :rating was a string instead of an integer. Before this, i rendered the json errors for #comment and that said that :rating was not a number.
These are very useful to spot the problem, but I can't find any solutions to fix the problem. I checked the database schema and it says that :rating should be an integer, as in:
t.integer "rating"
I don't know what to do at this point. Can somebody help me? Thank you in advance.
P.S. I use number_field.
P.P.S.
In my controller:
def ccreate
#comment = Comment.new(params.permit(:rating, :body, :name, :game_id))
raise "It exploded into pieces!" unless #comment.save
end
In my view:
<% if #comments.count < 10 %>
<%= form_for(comment_path) do |f| %>
<div class="field">
<%= f.label :rating %><br>
<%= f.number_field :rating %>
</div>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
It's a strong params thing. Permit :comments, then the attributes
params.require(:comments).permit(:rating, :body, :name, :game_id)
and, use form_for #comment, not comment_path
I think you need to setup the form properly, I think the validation will work fine if the form posts as it should:
comments_controller.rb
def new
#comment = Comment.new
end
def create
#comment = Comment.new(comment_params)
raise "It exploded into pieces!" unless #comment.save
end
private
def comment_params
params.require(:comment).permit(:rating, :body, :name, :game_id)
end
There we are changing the strong params to require the new comment key in params (which will be the result of the second change to the view below). I also moved this into a private function to clean this up.
So then in your view:
<% if #comments.count < 10 %>
<%= form_for(#comment) do |f| %>
<div class="field">
<%= f.label :rating %><br>
<%= f.number_field :rating %>
</div>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
This uses the form_for tag with the model instance which should, I think, solve this issue.
try this in the comment_controller.rb
#rating = params[:comment][:rating].to_i
to make every input of the ratings to be converted as integer
Hello i have a form like
<%= form_for #user,
:url => url_for(:controller => 'frontend',
:action => 'registration_completion') do |f| %>
<div class="control-group">
<%= f.label :name, "Jméno", :class => 'control-label' %>
<div class="controls">
<%= f.text_field :name, :class => 'text_field' %>
</div>
</div>
And user is displaying the form where he can see already registered values, but some of that value i want to hide if some condition (specifically i need hide value of username if it contains #) It is possible? thank you
solution: it seems that
<% if #user.name.include?('#') %>
<%= f.text_field :name %>
<% else %>
<%= f.text_field :name, :value => "" %>
<% end %>
works
I strongly suggest to put your logic inside a helper method:
module UserHelper
def name_input(instance, f, options = {})
options[:html_options] ||= {}
f.text_field :name, options[:html_options] if instance.name.include?('#')
end
end
Then in your view:
<%= name_input(#user, f, html_options: { class: 'text_field' }) %>
If you want to simply hide the value you can do:
<%= f.text_field :name, value: #user.name.include?('#') ? #user.name : '' %>
Feel free to move this to a helper method also.
To create a hidden field when the username contains an # symbol you could use the following helper method
module UserHelper
def hidden_name_field(user, f, options = {})
options[:html_options] ||= {}
if user.name.include?('#')
f.hidden_field(:name, options[:html_options])
else
f.text_field(:name, options[:html_options])
end
end
end
and use it in you form:
<%= hidden_name_field(#user, f, html_options: { class: 'text_field' }) %>
I'm starting with ruby on rails. I have a simple scaffold.
Here is my model:
class Pet < ActiveRecord::Base
belongs_to :user
belongs_to :petRace
attr_accessible :birth, :exactAge, :nick
def initialize
birth = DateTime.now.in_time_zone.midnight
end
end
the html code
<%= form_for #pet, :html => { :class => 'form-horizontal' } do |f| %>
<div class="control-group">
<%= f.label :nick, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :nick, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :birth, :class => 'control-label' %>
<div class="controls">
<div class="input-append date datepicker" data-date="<%=#pet.birth.strftime("%d/%m/%Y") %>" data-date-format="dd/mm/yyyy">
<%= f.text_field :birth, :class => 'input-append', :value => #pet.birth.strftime("%d/%m/%Y") %>
<span class="add-on"><i class="icon-th"></i></span>
</div>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
pets_path, :class => 'btn' %>
</div>
<% end %>
the controller:
def new
#pet = Pet.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #pet }
end
end
I just replace the original code for the :birth attribute, as you can see here:
<%= f.text_field :birth, :class => 'input-append', :value => #pet.birth.strftime("%d/%m/%Y") %>
when i select the option new the birth property seems to be no value and i get this execption
undefined method `[]' for nil:NilClass
Extracted source (around line #11):
8:
9: </script>
10: <%end%>
11: <%= form_for #pet, :html => { :class => 'form-horizontal' } do |f| %>
12: <div class="control-group">
13: <%= f.label :nick, :class => 'control-label' %>
14: <div class="controls">
app/views/pets/_form.html.erb:11:in `_app_views_pets__form_html_erb__3291519358612565784_70159905628180'
app/views/pets/new.html.erb:4:in `_app_views_pets_new_html_erb__1494749415896629355_70159907398120'
app/controllers/pets_controller.rb:28:in `new'
It's my understanding that the birth value is set with the actual date and time(in the initialize method). Am i wrong or missing something? When i edit a record i have no problem.
Thanks in advance.
There are a variety of ways to set a default value as #Rob mentioned in his comment.
A callback as #Dave mentioned in his comment is an OK idea, too.
I suspect the main reason the after_initialize approach isn't working for you is that you need to explicitly use self as in self.birth = rather than birth =. Ruby thinks you are defining a local variable named birth rather than assigning a value to ActiveRecord's attribute birth that is implemented via method_missing internally. This is why #pet.birth is nil even though it might appear that you assigned a value to it.
Also note that the after_initialize callback will be called even for persisted objects when you instantiate them by loading them from the database. It is also called after the attributes are assigned via initialize for new records. Thus to prevent the user-specified value from being trampled on by your default (for both persisted and new records), be sure to do something like this:
self.birth = value if birth.nil?
Emphasis on the if birth.nil?
Well here is the solution. First of all, the after_initialize method was not executed. But after this modification it worked:
class Pet < ActiveRecord::Base
belongs_to :user
belongs_to :petRace
attr_accessible :birth, :exactAge, :nick
after_initialize :init
protected
def init
self.birth = DateTime.now.in_time_zone.midnight
end
end
I'm trying to generate a form using the form_for helper in RoR but I am encountering what seems to be a routing error. Here are the relevant files:
models/equipment.rb
class Equipment < ActiveRecord::Base
attr_accessible :name, :tracking_number
validates :tracking_number, :presence => true,
:uniqueness => { :case_sensitive => true }
end
controllers/equipments_controllers.rb
class EquipmentsController < ApplicationController
def index
#equipments = Equipment.paginate(:page => params[:page])
end
def new
#equipment = Equipment.new
end
end
views/equipments/new.html.rb
<h1>Add an equipment</h1>
<%= form_for (#equipment) do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div class="field">
<%= f.label :name %> <br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :tracking_number %><br />
<%= f.text_field :tracking_number %>
</div>
<%= f.submit "Add" %>
<% end %>
routes.rb
EquipmentTracking::Application.routes.draw do
root :to => "equipments#index"
resources :equipments
end
I don't see anything wrong but they output the following:
NoMethodError in Equipments#new
Showing /opt/ror/equipment_tracking/app/views/equipments/new.html.erb where line #2 raised:
undefined method `equipment_index_path' for #<#<Class:0xb6725a2c>:0xb6724640>
If I changed it to
<%= form_for (:equipment) do |f| %>
it seems to work ok. I'm also certain that the static variable #equipment is getting passed since
<%= #equipment %>
returns
#<Equipment:0xb685ece0>
I am at a loss here. I just did what I did while I was following the railstutorial.org book and I was able to finish the book.
I think your problem lies in your use of the word "equipments". If you open the Rails console run 'equipment'.pluralize you'll see that the plural of "equipment" is "equipment".
So I'd do a search through your project and replace any instance of "equipments" with "equipment" and I'd bet that would fix it.