So I am a beginner in ROR, like I know it for a month (school assignment and we don't get a cursus we need to use 'google')
So I want a dropdown box with a list of all my cities. Then if I pick a city I need to save the city_id in my database together with the date. The code I have so far seem to work except when I click on save it says that city is empty (and it can't be empty because of the failsave)
this is my code
<div class="field">
<%= f.label :stad_id %><br />
<% cities_array = Stad.all.map { |stad| [stad.naam, stad.land] } %>
<%= select_tag(Stad, options_for_select(cities_array)) %>
</div>
<div class="field">
<%= f.label :datum %><br />
<% datum = Time.now.to_s(:db) %>
<%= f.text_field :datum, :value => datum.inspect, :readonly => true %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I don't really know what I am doing wrong except I have an eery feeling I don't actually give the command to save it.
help is much thanked
sincerely
Robin
There are a few things I notice here that are wrong.
1) Put the creation of the cities_array into your controller, not in your view:
def edit
#something = Something.find(params[:id])
#cities_array = ... whatever ...
end
2) When creating your cities_array, you need to specify the ID of the city as the second parameter, like this:
#cities_array = Stad.all.map { |stad| [stad.naam, stad.id] }
3) The select_tag call isn't for Stad, it's for the model you're trying to save. For example, your form might look like this:
<%= form_for #something %>
<%= f.label :city %>
<%= f.select :city_id, #cities_array %>
# or!
<%= select :something, :city_id, #cities_array %>
<% end %>
I hoep this clears things up for you.
Related
I'm new on rails. I work on a project, and I try to add physical address to my users. I want that the address can be help-complete with Google map for later exploitation. I find the jt-rails-address which look like perfect for my project. But I can't implement it. I need complete address (street, zip code, city & country).
add_address_to_users.rb :
class AddAddressToUsers < ActiveRecord::Migration[5.1]
def change
add_column :users, :address, :address
end
end
form edit.html.erb :
<div class="col-md-6 col-md-offset-3">
<%= form_for (#user), :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :phone, "Téléphone :" %>
<%= f.phone_field :phone, class: 'form-control' %>
<%= f.label :address, "Addresse :" %>
<div class="jt-address-autocomplete">
<!-- This field is used to search the address on Google Maps -->
<%= f.text_field :address, class: 'jt-address-search' %>
<!-- All fields are hidden because the javascript will set their value automatically -->
<% for attr in JT::Rails::Address.fields %>
<%= f.hidden_field "address_#{street}", class: "jt-address-field-#{street}" %>
<% end %>
<% for attr in JT::Rails::Address.fields %>
<%= f.hidden_field "address_#{zip_code}", class: "jt-address-field-#{zip_code}" %>
<% end %>
<% for attr in JT::Rails::Address.fields %>
<%= f.hidden_field "address_#{city}", class: "jt-address-field-#{city}" %>
<% end %>
<% for attr in JT::Rails::Address.fields %>
<%= f.hidden_field "address_#{country}", class: "jt-address-field-#{country}" %>
<% end %>
</div>
<%= f.submit "Enregistrer les changements", class: "btn btn-primary" %>
<% end %>
</div>
application.js :
// This function is call when Google Maps is loaded
window.googleMapInitialize = function(){
// Simple usage
$('.jt-address-autocomplete').jt_address();
};
I have already put :address in my user_params in the users controller and has_address :address in the user model
I also have put my Google Api.
My actual error:
undefined local variable or method `street' for #<#Class:0x00007fe91ec7f768:0x00007fe91dfaefc0>
Thanks in advance for your help.
No more error but a bug, maybe because of Google Map, I don't know how
to resolve it, I can't write the address and there is an error message:
problem
Here the code of the inspector:
First, you should add fields like in documentation or scope them using select, now you have code that will create duplicated hidden fields.
You should check from rails console that method address is available on User instance of model.` Maybe you forgot to run migration or didn't restart server after installing this gem as this is js gem and will need restart.
Hope this answers your questions. Add comment to this answer if problem is still there.
On the edit page for this form all of the fields outside of the fields_for tag (inbox name, automatic reconciliation, and a few others not listed here) are all populating based on their corresponding db value. However, everything inside the fields_for tag are not, even though they're posting to the db just fine.
I posted :group_member_roles as an example but there are a few other fields inside their own other fields_for that are doing the same thing. It's just confusing that it will post to the db but not display on edit.
The more I read into fields_for the more I feel like I'm not using it correctly. It seems to be more inclined to populating db tables outside of the one your form is currently referencing, but I'm just trying to serialize data within the inbox table. When I look at the :group_member_roles column I want it to be an array/hash containing process true/false, action add/delete, and a string of values.
#_form.html.erb
<%= form_for(#inbox) do |f| %>
<%= f.label :inbox_name %>
<%= f.text_field :name, placeholder: "Inbox Name" %>
<%= f.label :automatic_reconciliation, "Turn on/off automatic reconciliation" %>
<div class="switch small">
<%= f.check_box :automatic_reconciliation, class: "switch-input" %>
<label class="switch-paddle" for="inbox_automatic_reconciliation">
<span class="show-for-sr">Automatic reconciliation</span>
<span class="switch-active" aria-hidden="true">On</span>
<span class="switch-inactive" aria-hidden="true">Off</span>
</label>
</div>
<%= f.fields_for :group_member_roles do |group_member_roles| %>
<h4>Group Member Roles</h4>
<%= group_member_roles.label :process, "Turn On/Off Processing" %>
<div class="switch small">
<%= group_member_roles.check_box :process, class: "switch-input" %>
<label class="switch-paddle" for="inbox_group_member_roles_process">
<span class="show-for-sr">Group Member Roles Processing</span>
<span class="switch-active" aria-hidden="true">On</span>
<span class="switch-inactive" aria-hidden="true">Off</span>
</label>
</div>
<%= group_member_roles.label :action, class: "hide" %>
<%= group_member_roles.select :action, ["Add", "Delete"], { selected: "Add" }, { class: "hide" } %>
<%= group_member_roles.label :values %>
<%= group_member_roles.text_field :values, placeholder: "1234, 1337, 1986" %>
<% end %>
Thanks in advance for any help or guidance.
The fields were being stored as a hash and the field was looking for an object to populate with so I added an OpenStruct dummy object to the fields_for to make it so. If anyone can think of a better way please let me know as this is pretty ugly code.
<%= f.fields_for :group_member_roles, OpenStruct.new(f.object.group_member_roles) do |group_member_roles| %>
I have a field called delivery_day which is of type string in delivery_preference model.
In form, I want to provide 7 checkboxes for each day like Sunday,Monday,etc., and later want to concat.
For example if a user checks Sunday and Friday, I want to concat & store it as "Sunday,Friday" in delivery_day field.
Thanks in Advance!!
You can design your form like this -
<%= form_for #delivery_preference do |f|%>
<%= f.check_box :delivery_day, {multiple: true}, "Sunday" %>Sunday
<%= f.check_box :delivery_day, {multiple: true}, "Monday" %> Monday
<%= f.submit "Add" %>
<% end %>
After submitting the form, you can get your check box selections in your controller as follows:
def your_action_name
params[:delivery_preference][:delivery_day].delete("0")
DeliveryPreference.create(delivery_day: params[:delivery_preference][:delivery_day].join(","))
end
Hope it helps!
Might have better solutions, but when I encountered similar problem, I used check_box_tag to solve it.
<%= check_box_tag "delivery_preference[delivery_day][0]", 'monday' %>Monday
<%= check_box_tag "delivery_preference[delivery_day][1]", 'tuesday' %>Tuesday
<%= check_box_tag "delivery_preference[delivery_day][2]", 'wednesday' %>Wednesday
<%= check_box_tag "delivery_preference[delivery_day][3]", 'thursday' %>Thursday
<%= check_box_tag "delivery_preference[delivery_day][4]", 'friday' %>Friday
<%= check_box_tag "delivery_preference[delivery_day][5]", 'saturday' %>Saturday
<%= check_box_tag "delivery_preference[delivery_day][6]", 'sunday' %>Sunday
then you will receive an array like { deliver_day: ['monday', 'tuesday'] } in you controller. You can choose to concat in your controller, and then save, or you can move the logic to your model.
in your controller, you strong parameter should be like
params.require(:delivery_preference).permit(.., :deliver_day => [])
to permit the array.
I do not have enough reputation to leave a brief comment yet. However, does your migration have delivery_day have something similar to t.boolean :public, default: true_or_false_here within it?
If so, within the form, you could have something like:
...
<div class="form-group">
<%= f.label :public, class: 'checkbox' do %>
<%= f.check_box :public %> Monday
<% end %>
</div>
<div class="form-group">
<%= f.label :public, class: 'checkbox' do %>
<%= f.check_box :public %> Tuesday
<% end %>
</div>
...
After above, you could designate (via boolean logic) your "concat & store it as "Sunday,Friday"
I know from looking at the Rails api that there's a way to create custom validations, but I can't figure it how to do it with this. I want the user to only be able to select 2 of the 4 check_boxes... Pretend the controller is named favorites_controller and the favorites table has these attributes
Is there a way to make them only select 2 of the 4?
<div class="field">
<%= f.label(:sex, "Sex") %>
<%= f.check_box(:sex) %> </br>
</div>
<div class="field">
<%= f.label(:chocolate, "Chocolate") %>
<%= f.check_box(:chocolate) %> </br>
</div>
<div class="field">
<%= f.label(:computers, "Computers") %>
<%= f.check_box(:computers) %> </br>
</div>
<div class="field">
<%= f.label(:comicbooks, "Comic Books") %>
<%= f.check_box(:comicbooks) %> </br>
</div>
#obrok how far off am I with this function, using a before_save, I know it's not right but can you steer me in the right direction. How do I trigger the validation function on the form submission? I'm a newbie (and generally not very smart :(
before_save :check_box_count
....
def check_box_count
#check_box_count = check_box(:sex) + check_box(:chocolate) + check_box(:computers) + check_box(:comicbooks)
unless #check_box_count == 2 return false
end
You can do this simply by writing a method which counts how many checkboxes are ticked and then validating that.
Edit:
Something like this I think.
validates_inclusion_of :check_box_count, :in => 2..2, :message => "Two checkboxes should be ticked"
...
private
def check_box_count
[sex, chocolate, computer, comicbooks].select{|x| x }.count
end
Rails newbie here.
I have 2 models: Target and Observation
Target works fine. I generated scaffolding for Observation, like this:
rails generate scaffold Observation date:date target:references
So app/models/observation.rb says:
class Observation < ActiveRecord::Base
belongs_to :target
end
Then I edited app/models/target.rb:
class Target < ActiveRecord::Base
has_many :observations
end
The scaffolding created app/views/observations/_form.html.erb which includes:
<div class="field">
<%= f.label :target %><br />
<%= f.text_field :target %>
</div>
And app/controllers/observation_controller.rb which includes:
def create
#observation = Observation.new(params[:observation])
I then go to create a new Observation. I enter a date and the ID of a target in the target field. When I submit, I get this error in the browser:
ActiveRecord::AssociationTypeMismatch in ObservationsController#create
Target(#2190392620) expected, got String(#2148287480)
Seems like the scaffolding would set up something that would work. But the error makes sense. It's receiving the ID of the Target instead of the Target itself. So I edited app/controllers/observation_controller.rb to say:
def create
#target = Target.find(params[:observation][:target])
#observation = #target.observations.create(:date => params[:observation][:date])
Now it creates the Observation record, with the reference to the Target. But the date field is blank.
I realize this may be a dumb newbie or RTFM question, but I'd really appreciate a pointer in the right direction. Thanks.
Here's the full contents of the form, after changing it to reflect the answer received.
<%= form_for(#observation) do |f| %>
<% if #observation.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#observation.errors.count, "error") %> prohibited this observation from being saved:</h2>
<ul>
<% #observation.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :date %><br />
<%= f.date_select :date %>
</div>
<div class="field">
<%= f.label :target %><br />
<%= f.collection_select :target_id, Target.all, :id, :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
change
<%= f.text_field :target %>
to
<%= f.text_field :target_id %>
And really better is to use something like select for this thing. Like:
<%= f.collection_select :target_id, Target.all, :id, :title %>
UPD
As far as date_select helper set not ordinary banch of variables for each element (year, month, day) you shoul do this:
date = [ params[:observation]['date(1i)'], params[:observation]['date(2i)'], params[:observation]['date(3i)'] ].join(".")
#observation = #target.observations.create(:date => date)
Actually just look into HTML source and you'll see it
(Not sure if you are still monitoring this, OP? For the benefit of everyone coming here via Google:)
There will be no params[:observation][:date] because dates are entered using several HTML input fields, and then magically merged in assignment. The keyword for this is "multi-parameter attributes", and this is the best explanation I've found:
How do ruby on rails multi parameter attributes *really* work (datetime_select)
I also wonder if this simpler snippet would work.
#observation = #target.observations.create(params[:observation])
You can use:
<%= collection_select(:observation, :target_id, Target.all, :id, :title %>
i think it will help you.