I want to use carmen-rails gem in my rails project, but in documentation at github i can't understand well how to use it , so i think : if for example i want my users have a country and state :
first : i should add 2 columns in my user model (country and state), Right ?
second : add select country and state to my user form :
<%= simple_form_for #user do |f| %>
<div class="field">
<%= f.label :country_code %><br />
<%= f.country_select :country_code, priority: %w(US CA), prompt: 'Please select a country' %>
</div>
<div class="field">
<%= f.label :state_code %><br />
<%= render partial: 'subregion_select', locals: {parent_region: f.object.country_code} %>
</div>
<% end %>
then my partial should be look like :
<div id="order_state_code_wrapper">
<% parent_region ||= params[:parent_region] %>
<% country = Carmen::Country.coded(parent_region) %>
<% if country.nil? %>
<em>Please select a country above</em>
<% elsif country.subregions? %>
<%= subregion_select(:order, :state_code, parent_region) %>
<% else %>
<%= text_field(:order, :state_code) %>
<% end %>
I'm right ?
then how to validate country and state when the form is submitted ?
finally how to change language of countries and states in the select form (to french for example ) ?
Yes and yes.
Take a look at their demo app: https://github.com/jim/carmen-demo-app/
You need to add the route to fill the states partial, then add the appropiate controller method to render the partial. Don't forget to define the partial route first and then users controller routes.
e.g. (routes.rb)
get '/users/subregion_options' => 'users#subregion_options'
resources :users
e.g. (users_controller.rb)
def subregion_options
render partial: 'subregion_select'
end
You need to add some JS to catch change event on countries select and then with the country code call the users controller method to render the states partial.
e.g. (users.js.coffee)
$ ->
$('select#user_country_code').change (event) ->
select_wrapper = $('#user_state_code_wrapper')
$('select', select_wrapper).attr('disabled', true)
country_code = $(this).val()
url = "/users/subregion_options?parent_region=#{country_code}"
select_wrapper.load(url)
You can handle validation on the user's model class as usual. The sample app includes information on changing locales.
Related
I have a model Responsibility with has one text field of responsibility. Other model is Stage, in Stage form field there is a text_field responsibility I want to render an option list from responsibilities table how can i do that in rails?
routes.rb
resources :projects do
resources :responsibilities
resources :stages
end
stage _form.html.erb
<%= form_with(model: stage, url: [#project, stage], local: true) do |form| %>
<div>
<%= form.label :responsibility, :class=>"required" %>
<%= form.text_field :responsibility %>
</div>
<div>
<%= form.submit %>
</div>
<% end %>
How can I render responsibilities list as an option in stage responsibility form field?
what is tried is:
stage _form.html.erb
<div>
<%= form.label :responsibility %>
<%= select_tag "colors", #responsibilities , multiple: true %>
</div>
stages_controller.rb
def new
#stage = Stage.new
#project = Project.find(params[:project_id])
#responsibilities = #project.responsibilities
end
I was able to render form but in responsibility field none of the responsibility was accessed as option.
select_tag accepts as a second parameter string that contains options as a string.
Rails provides some helper methods that are useful for generation of those <option>
tags
options_from_collection_for_select, options_for_select
If you inspect with your browser's developer tools the html code of the <select> tag you will see something like this:
<select name="colors[]" id="colors" multiple="multiple">
#<Responsibility::ActiveRecord_Relation:0x00007f3f72cc7eb0>
</select>
This is because select_tag calls to_s method of #responsibilities collection.
The correct way of creating select_tag would looks something like this:
<%= select_tag "colors", options_from_collection_for_select(#responsibilities, :id, :name) , multiple: true %>
There is another way to build select field using the FormBuilder method collection_select. It might look something like this:
<div>
<%= form.label :responsibility %>
<%= form.collection_select :responsibility, #responsibilities, :id, :name, prompt: true %>
</div>
I hope this answer will be useful.
In my RoR application I have functionality that allows a user to select contacts to send an email to. I want to add to this functionality so that a user can search the contacts.
Currently, the contacts are displayed on the views/emails/form.html.erb in checkboxes that the user can select through:
<%= f.collection_check_boxes :contact_ids, Contact.where(user_id: session[:user_id]), :id, :firstname %>
Is it possible to build on this by adding a search bar above the checkboxes that allows the user to search the checkboxes by first name?
You can have a form to work with an unobstrusive javascript.
Like
<div class="form-group">
<!-- Form outside your main form... the REMOTE flag will tell rails
to prevent the default behaviour of a form make a request
for JS response --!>
<%= form_tag contacts_path, remote: true, method: :get do %>
<%= input_tag :search %>
<%= button_tag "Search" %>
<% end %>
<div id="email-form">
<%= form_for #email, email_path do |f| %>
<!-- Many inputs relative with email omited--!>
<div class="contact-list">
</div>
<%= f.submit 'Submit' %>
<% end %>
</div>
Have an controller/action that search for your contacts and returns it for a js view...
// ContactController
def index
respond_to do |format|
format.html { #contacts = Contact.all }
format.js { #contacts = Contact.find_by(firstname: params[:search]) }
end
end
And have a view for that action/controller that manipulate the html to append the contacts to be selected
// views/contacts/index.js.erb
$(document).ready(function() {
$('#contact-list').append("<%= collection_check_boxes :email, :contact_ids, #collection, :id, :firstname %>")
})
That is a very simple example... and I don't handle repetition... if you search for the same thing twice...
I have a class activity that has the follow atributes:
String type, Date date, String title
By including the associations it also has user_id and place_id.
class Activity < ActiveRecord::Base
belongs_to :user
belongs_to :place
In the other side User has many activities and place has many activities
So, the problem is when I want to create a new activity:
Scaffold creates the helper _form :
<%= form_for(#activity) do |f| %>
<% if #activity.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#activity.errors.count, "error") %> prohibited this activity from being saved:</h2>
<ul>
<% #activity.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :type %><br>
<%= f.text_field :type %>
</div>
<div class="field">
<%= f.label :date %><br>
<%= f.datetime_select :date %>
</div>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :user_id %><br>
<%= f.number_field :user_id %>
</div>
<div class="field">
<%= f.label :place_id %><br>
<%= f.number_field :place_id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I want to receive the first 3 fields from the form (type, date and title) but to associate a user and a place I have to do other way. I need the user that is actual logged in and the place is choosen by tiping the name.
My idea to do this is the following:
1) The user issue, I can make a query by using the current_logged_user that I have acess and get his ID.
2) The place issue, I can use the name that I receive from form and query my Places table for the place with the name X and get the ID after.
But, because I don't know too much about rails, how can I do this? How can I use f.text_field and then made the query or whatever and use after in the controller?
Controller has already this stuff :
def create
#activity = Activity.new(activity_params)
(...)
private
# Use callbacks to share common setup or constraints between actions.
def set_activity
#activity = Activity.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def activity_params
params.require(:activity).permit(:type, :date, :title, :user_id, :place_id)
end
You can structure your rails app to get neither the user_id nor the place_id directly from the form. Especially getting user_id from a submitted form is generally not a good idea. You usually do not want to whitelist user_id at all.
For user_id:
If you are using a gem like devise for user authentication, it gives you access to a method called current_user, which you can use to set the user_id from.
For place_id:
I suggest putting the activity as a sub route of place. e.g. instead of having the form under <host>/activities/new, put it under ``/places/:place_id/activities/new`. In your route file put the route as follows:
resources :places do
resources :activities
end
Now, in your controller action you can do the following:
def create
#activity = current_user.activities.new(activity_params)
#activity.place_id = params[:place_id] (or even safer will be #activity.place = Place.find(params[:place_id], but this will require one more sql query )
(...)
private
# Never trust parameters from the scary internet, only allow the white list through.
def activity_params
params.require(:activity).permit(:type, :date, :title)
end
UPDATE:
If you absolutely want to have the form under /activities/new route then you can have a select tag for place_id in your form:
select_tag 'activity[place_id]', options_from_collection_for_select(Place.all, 'id', 'name')
This will create a selection with name 'activity[place_id]' (named this way for params.require(:activity).permit(place_id) ) and options looking like
<option value="1">Barcelona</option>
I am trying to DRY up my Rails application a bit, so I would like to render a form in my show view but disable all input fields.
// show.html.erb
<%= form_for(#project) do |f| %>
<%= render 'fields', :f => f %>
<% end %>
What would be the best way to do that?
Thanks for any help.
Javascript
One way would be to do it using JS. Include a div with a specific class in the show view :
// show.html.erb
<div class='disable_input'>
<%= form_for(#project) do |f| %>
<%= render 'fields', :f => f %>
<% end %>
</div>
Then in your JS file :
$('.disable_input :input').prop('disabled', true);
Rails
If you want to actually generate it server side, you can pass a variable to your partial that will tell the partial if it has to add the disabled option on each field. It's a bit more work though!
Using a variable, you could do something like this :
<%= form_for(#project) do |f| %>
<%= render 'fields', :f => f, :disabled => true %>
<% end %>
In the partial :
<% disabled ||= false
#We do this so if disabled is not passed to the partial it doesn't crash.
# We default it to false
%>
<% # Then for all your fields, add disabled: disabled %>
<%= f.text_field :some_attribute, disabled: disabled %>
Form builder
Edit : actually, one way to avoid explicitly passing disabled everywhere would be to create a Custom form builder. There's some good resources talking about it, like this one : http://johnford.is/writing-a-custom-formbuilder-in-rails/
In this example, it's done for onkeypress, shouldn't be hard to adapt for your case!
You can wrap all fields in <fieldset disabled>
// show.html.erb
<%= form_for(#project) do |f| %>
<fieldset disabled>
<%= render 'fields', :f => f %>
</fieldset>
<% end %>
You can use stylesheets for this thing.
The show action might be in controller say 'Project', hence you might be having a file in stylesheets with the name of your controller.
Now enclose your form in show.html.erb in a div, and give it a unique id ,say 'disable_input', that you wont be giving to any element in any page.
Now disable all input fields in you css under this div. You can write it like this..
disable_input input{
# whatever you want to do
}
Hence no need to code.
On the front page of my rap lyrics explanation site, there's a place where users can try explaining a challenging line:
alt text http://dl.dropbox.com/u/2792776/screenshots/2010-02-06_1620.png
Here's the partial I use to generate this:
<div class="stand_alone annotation" data-id="<%= annotation.id %>">
<%= song_link(annotation.song, :class => :title) %>
<span class="needs_exegesis"><%= annotation.referent.strip.gsub(/\n/, "\n <br />") %></span>
<% form_for Feedback.new(:annotation_id => annotation.id, :created_by_id => current_user.try(:id), :email_address => current_user.try(:email)), :url => feedback_index_path, :live_validations => true do |f| %>
<%= f.hidden_field :annotation_id %>
<%= f.hidden_field :created_by_id %>
<p style="margin-top: 1em">
<%= f.text_area :body, :rows => 4, :style => 'width:96%', :example_text => "Enter your explanation" %>
</p>
<p>
<% if current_user %>
<%= f.hidden_field :email_address %>
<% else %>
<%= f.text_field :email_address, :example_text => "Your email address" %>
<% end %>
<%= f.submit "Submit", :class => :button, :style => 'margin-left: .1em;' %>
</p>
<% end %>
</div>
However, putting more than one of these on a single page is problematic because Rails automatically gives each form an ID of new_feedback, and each field an ID like feedback_body (leading to name collisions)
Obviously I could add something like :id => '' to the form and all its fields, but this seems a tad repetitive. What's the best way to do this?
If you don't want to change your input names or your model structure, you can use the id option to make your form ID unique and the namespace option to make your input IDs unique:
<%= form_for Feedback.new(...),
id: "annotation_#{annotation.id}_feedback"
namespace: "annotation_#{annotation.id}" do |f| %>
That way our form ID is unique, i.e. annotation_2_feedback and this will also add a prefix, e.g. annotation_2_, to every input created through f.
Did you consider nested_attributes for rails models? Instead of having multiple new feedback forms where each is tied to an annotation, you could have multiple edit annotation forms where each annotation includes fields for a new feedback. The id's of the generated forms would include the annotations id such as edit_annotation_16.
The annotation model would have a relationship to its feedbacks and will also accept nested attributes for them.
class Annotation < ActiveRecord::Base
has_many :feedbacks
accepts_nested_attributes_for :feedbacks
end
class Feedback < ActiveRecord::Base
belongs_to :annotation
end
You could then add as many forms as you want, one for each annotation. For example, this is what I tried:
<% form_for #a do |form| %>
Lyrics: <br />
<%= form.text_field :lyrics %><br />
<% form.fields_for :feedbacks do |feedback| %>
Feedback: <br/>
<%= feedback.text_field :response %><br />
<% end %>
<%= form.submit "Submit" %>
<% end %>
<% form_for #b do |form| %>
Lyrics: <br />
<%= form.text_field :lyrics %><br />
<% form.fields_for :feedbacks do |feedback| %>
Feedback: <br/>
<%= feedback.text_field :response %><br />
<% end %>
<%= form.submit "Submit" %>
<% end %>
And the quick and dirty controller for the above edit view:
class AnnotationsController < ApplicationController
def edit
#a = Annotation.find(1)
#a.feedbacks.build
#b = Annotation.find(2)
#b.feedbacks.build
end
def update
#annotation = Annotation.find(params[:id])
#annotation.update_attributes(params[:annotation])
#annotation.save!
render :index
end
end
I had this same issue on a site I'm currently working on and went with the solution you mention at the bottom. It's not repetitive if you generate the ID programmatically and put the whole form in a partial. For example, on my site, I have multiple "entries" per page, each of which has two voting forms, one to vote up and one to vote down. The record ID for each entry is appended to the DOM ID of its vote forms to make it unique, like so (just shows the vote up button, the vote down button is similar):
<% form_for [entry, Vote.new], :html => { :id => 'new_up_vote_' + entry.id.to_s } do |f| -%>
<%= f.hidden_field :up_vote, :value => 1, :id => 'vote_up_vote_' + entry.id.to_s %>
<%= image_submit_tag('/images/icon_vote_up.png', :id => 'vote_up_vote_submit' + entry.id.to_s, :class => 'vote-button vote-up-button') %>
<% end -%>
I also had the same issue but wanted a more extensible solution than adding the ID to each field. Since we're already using the form_for ... |f| notation the trick is to change the name of the model and you get a new HTML ID prefix.
Using a variant of this method: http://www.dzone.com/snippets/create-classes-runtime (I removed the &block stuff)
I create a new model that is an exact copy of the model I want a second form for on the same page. Then use that new model to render the new form.
If the first form is using
#address = Address.new
then
create_class('AddressNew', Address)
#address_new = AddressNew.new
Your ID prefix will be 'address_new_' instead of 'address_' for the second form of the same model. When you read the form params you can create an Address model to put the values into.
For those stumbling here, looking for the solution for Rails 3.2 app, look at this question instead:
Rails: Using form_for multiple times (DOM ids)