I have gone through N number of solutions for creating a dynamic dropdown in rails but nothing seems to work.
I have a typical state and city model and I do not want to use carmen.
Here is my model :-
Market.rb
class Market < ActiveRecord::Base
attr_accessible :state, :cities_attributes
has_and_belongs_to_many :users
has_many :cities, :dependent => :destroy
accepts_nested_attributes_for :cities
validates :state, :presence => true, :uniqueness => true
end
City.rb
class City < ActiveRecord::Base
attr_accessible :city
belongs_to :market
has_and_belongs_to_many :users
end
in devise/registrations/new (I want the user to select the state and city at the time of signup itself)
%li
=f.collection_select :city, Market.all,:id, :state, html_options = { :class => "custom_textarea"}
%li
=render "devise/registrations/cities", :f => f
_cities.html.haml partial
-unless cities.blank?
=f.collection_select( :city, #cities, :id, :cities)
registrations_controller.rb
def update_city_select
#cities = City.where(:country_id => params[:id])
render :partial => "cities", :locals => {:cities => #cities}
end
I want the city list to change once the user selects a state and be populated with relevant cities.
How can I achieve this?
You must use ajax for this in your view which contains the state dropdown:
$("#stateDropdown").change(function(){
$.get("controller/update_city_select.html?id="+$("#stateDropdown").val(),
function(data){ $("#cityDropdownDiv").html(data); } );
});
This calls your action, and substitutes the content of your div to the new dropdown for cities.
To your partial:
#cityDropdownDiv
-unless #cities.blank?
= collection_select( :market, :city, #cities, :id, :cities)
With this, you don't need to add the :f => f parameter when rendering the partial.
You should add an id (I am assuming "stateDropdown") to your dropdown in the html_option part.
One more tutorial which was really helpfull and I guess will help anyone looking to implement dependent dropdown is http://www.petermac.com/rails-3-jquery-and-multi-select-dependencies/
Related
i try to spend a variable in my partial _showLastMeal.rb, before to come for asking your help i read http://api.rubyonrails.org and i try to find a solution in staskoverflow
<%= render :partial => "calendars/showLastMeal", :locals => { :calendar => "calendar" } -%>
In calendar_controller.rb:
def showLastMeal
#lastMeal = #user.calendar.findMeal
end
And the model
class Calendar < ActiveRecord::Base
attr_accessible :event, :published_on, :description, :user_id, :description_meal
belongs_to :user #, :foreign_key => :user_id
scope :findMeal, lambda { order('created_at').limit(6) }
end
i use rails 3.2.2
i have two models :
class Article < ActiveRecord::Base
belongs_to :league
has_many :photos, :dependent => :destroy
attr_accessible :content, :lead, :title, :title_slug,
:created_at, :updated_at,
:league_id, :photos_attributes
accepts_nested_attributes_for :photos
validates :content, :league, :presence => true
validates :lead , :length => {maximum: 1000}, :presence => true
validates :title ,:length => {maximum: 200}, :presence => true
validates_associated :photos
and
class Photo < ActiveRecord::Base
belongs_to :article
attr_accessible :photo
validates :photo, presence: true
has_attached_file :photo , :styles => { :medium => '440x312#', :small => '209x105!'}
end
My ArticlesController is
...
def new
#article = Article.new
#article.photos.build
end
def create
#article = Article.new(params[:article])
if #article.save
redirect_to([:admin,#article])
else
render 'new'
end
end
...
form view is :
= form_for([:admin,#article] , :html => {:multipart => true}) do |f|
- if #article.errors.any?
= render 'errors'
= f.fields_for :photos do |builder|
= builder.label :photo
= builder.file_field :photo
...
i have some question about it :
1) I dont want to save an article without empty photo but now when i dont choose a file my article saves.
2) When i have some errors on article's fields and render 'new' ,my photo field dissapear , what is the rails way to resolve it.
3) in the future i want to add another model: photo_type and assosciate it with photo. Each article will have two photo fields , each with own type (for example: small , big) . I wonder how to render that fields and what can i do to save article with two photos with different types.
Answer for 1: Use validates_associated :photos. Documentation
Answer for 2: I guess that is an file attachment field. For that, this is generally done by setting up a hidden cache field and by using some callbacks. MountUploader uses the same principle.
Answer for 3: Little skeptical, but I guess something will work along this way:
In your Article model, have two associations with Photo as:
has_one :small_photo, :class_name => "Photo"
has_one :big_photo, :class_name => "Photo"
This will enable you to have two sub-form fields present for both types while opening up the form for Article.
Hope it helps. Do comment if last one can work for you in this way. It looks like the good deal to me :)
This is hard to explain, but I will do my best:
I am building a system where user's can take courses. Courses are made up of steps, that must be taken in order. In the system there are 6 step types (Download, Presentation, Video, Text, Quiz, and Survey)
The way a user accesses a STEP currently is:
http://example.com/courses/2/course_steps/1
As you can tell course_steps are nested under courses.
Below is the show method in course steps:
def show
render "show_#{#course_step.step.step_type.name.downcase}"
end
As you can tell it basically picks a view to show_[TYPE] (quiz, survey, text..etc)
This works fine for simple steps such as a text, video, or download, but for complicated steps such as a quiz, this model does not work well for the following reasons:
How do I validate a form for a quiz or survey as I would be using a different controller (QuizAttemptsController).
It seems to break the REST principal as a quiz, survey..etc should be treated separately. (I know they are step types, but they can have their own actions and validations)
Step Model
class Step < ActiveRecord::Base
belongs_to :step_type
belongs_to :client
has_one :step_quiz, :dependent => :destroy
has_one :step_survey, :dependent => :destroy
has_one :step_text, :dependent => :destroy
has_one :step_download, :dependent => :destroy
has_one :step_video, :dependent => :destroy
has_one :step_presentation, :dependent => :destroy
has_many :course_steps, :dependent => :destroy
has_many :courses, :through => :course_steps
has_many :patient_course_steps, :dependent => :destroy
attr_accessible :step_type_id, :client_id, :title, :subtitle, :summary
validates :title, :presence=>true
validates :summary, :presence=>true
def getSpecificStepObject()
case self.step_type.name.downcase
when "text"
return StepText.find_by_step_id(self.id)
when "quiz"
return StepQuiz.find_by_step_id(self.id)
when "survey"
return StepSurvey.find_by_step_id(self.id)
when "download"
return StepDownload.find_by_step_id(self.id)
when "video"
return StepVideo.find_by_step_id(self.id)
when "presentation"
return StepPresentation.find_by_step_id(self.id)
end
end
end
Step Quiz Model:
class StepQuiz < ActiveRecord::Base
belongs_to :step, :dependent => :destroy
has_many :step_quiz_questions, :dependent => :destroy
has_many :quiz_attempts, :dependent => :destroy
accepts_nested_attributes_for :step
accepts_nested_attributes_for :step_quiz_questions, :allow_destroy => true
attr_accessible :step_id, :instructions, :step_attributes, :step_quiz_questions_attributes
validates :instructions, :presence=>true
end
CourseStep Model
class CourseStep < ActiveRecord::Base
belongs_to :step
belongs_to :course
validates_uniqueness_of :step_id, :scope => :course_id
def next_step()
Course.find(self.course.id).course_steps.order(:position).where("position >= ?", self.position).limit(1).offset(1).first
end
def previous_step()
Course.find(self.course.id).course_steps.order("position DESC").where("position <= ?", self.position).limit(1).offset(1).first
end
end
How would you suggest fixing this?
What you want to do is implement your Model as a Finite State Machine and continually reload the new or edit action until the desired state is reached, then your controller can display different views depending on state to allow multiple steps to happen.
One way I have solved the problem is by adding a member action of "submit_quiz"to the course_steps controller. I am not sure if I like this, as the code looks kind of ugly. I would appreciate feedback.(Note: I Am using CanCan so #course_step is created automagically in the course_steps_controller)
The things I don't like are:
show_quiz view has a lot of code in it
submit_quiz is in the course_steps_controller
quiz_attempt model has virtual attribute of quiz_questions (for validation purposes)
show_quiz.html.erb
<%= form_for (#quiz_attempt.blank? ? QuizAttempt.new(:started => Time.now.utc, :step_quiz_id => #course_step.step.step_quiz.id) : #quiz_attempt, :url => submit_quiz_course_course_step_path(#course_step.course, #course_step)) do |f| %>
<%= render :partial => 'shared/error_messages', :object => f.object %>
<% #course_step.step.step_quiz.step_quiz_questions.each do |quiz_question| %>
<h3><%= quiz_question.value %></h3>
<% quiz_question.step_quiz_question_choices.each do |quiz_question_choice| %>
<%= radio_button_tag("quiz_attempt[quiz_questions][#{quiz_question.id}]", quiz_question_choice.value, f.object.get_quiz_question_choice(quiz_question.id) == quiz_question_choice.value)%>
<%= quiz_question_choice.value %><br />
<% end %>
<% end %>
<%= f.hidden_field(:step_quiz_id)%>
<%= f.hidden_field(:started)%>
<%= submit_tag("Submit Quiz")%>
<% end %>
course_steps_controller.rb
def show
PatientCourseStep.viewed(current_user.id, params[:course_id], #course_step.step.id )
render "show_#{#course_step.step.step_type.name.downcase}"
end
def submit_quiz
#quiz_attempt = QuizAttempt.new(params[:quiz_attempt])
if !#quiz_attempt.save()
render 'show_quiz'
end
end
quiz_attempt.rb
class QuizAttempt < ActiveRecord::Base
belongs_to :step_quiz
belongs_to :patient
attr_accessor :quiz_questions
attr_accessible :step_quiz_id, :patient_id, :started, :ended, :correct, :incorrect, :quiz_questions
validate :answered_all_questions?
def get_quiz_question_choice(quiz_question_id)
unless self.quiz_questions.blank?
quiz_questions[quiz_question_id.to_s]
end
end
private
def answered_all_questions?
#Making sure they answered all the questions
if self.quiz_questions.blank? or self.quiz_questions.try(:keys).try(:count) != self.step_quiz.step_quiz_questions.count
errors.add_to_base "Not all questions were answered"
end
end
end
def submit_quiz
#quiz_attempt = QuizAttempt.new(params[:quiz_attempt])
if !#quiz_attempt.save()
render 'show_quiz'
end
end
I would like to assign two different "types" of tags (sector categories and free tagging) to a Company model using acts_as_taggable_on. NB: I'm new to RoR!
This is easy to do if just using standard text input fields, but I would like to use check-boxes on one type (a fixed sector category tag that is predefined), and then allow the user to add comma separated tags in an input field.
I have played around with this problem in various ways,... one inspired by this question...but I cannot get it to work
Here is what I have so far:
# models/company.rb
class Company ...
acts_as_taggable_on :tags, :sectors
has_many :taggings,
:as => :taggable,
:include => :tag,
:class_name => "ActsAsTaggableOn::Tagging",
:conditions => { :taggable_type => "Company" }
has_many :sector_tags,
:through => :taggings,
:source => :tag,
:class_name => "ActsAsTaggableOn::Tag",
:conditions => {:context => "sectors"}
end
in the form (using simple_form gem) I have...
# views/companies/_form.html.haml
= simple_form_for #company do |f|
= f.input :name
= f.association :sector_tags, :as => :check_boxes, :hint => "Please click all that apply"
= f.input :tag_list
= f.button :submit, "Add company"
And in my Company controller I have
# controllers/companies_controller.rb
def create
#company = current_user.companies.build(params[:company])
if #company.save
...
end
But this causes a validation error:
ActiveRecord::RecordInvalid in CompaniesController#create
Validation failed: Context can't be blank
Can anyone hint at how I can do this right?
A related question is if this is a good way to do it at all? Would I be better off just using a Category model for assigning sector tags through a joint model?
Thanks!
Well, I solved my problem. And it turned out to be quite simple. Alas, I ended up creating a separate Sector model through a joint "sectorizations" table. But if anyone is interested, I just wanted to update on what I did in the case above...
In my company model
# models/company.rb
class Company ...
acts_as_taggable_on :tags, :sectors
...
end
in the form
# views/companies/_form.html.haml
= simple_form_for #company do |f|
= f.input :name
= f.input :sector_list, :as => :check_boxes, :collection => #sectors, :hint => "Please check all that apply"
= f.input :tag_list
= f.button :submit, "Add company"
and in the company controller (create)
# controllers/company_controllers.rb
def new
#company = Company.new
#sectors = get_sectors
end
def get_sectors
sectors = []
for sector in Company.sector_counts
sectors << sector['name']
end
return sectors
end
It seems that act_as_taggable_on uses single table inheritance, so you actually don't need to create any additional tables. However you do need to follow their convention (that they never stated) as follows:
//add to model
attr_accessible :yourfieldname_list
acts_as_taggable_on :yourfieldname
//view
<%= f.text_field :yourfieldname_list %>
I've been full of questions lately, but thanks to this awesome community, I'm learning a ton.
I got all the help I needed with polymorphic associations earlier and now I have a question about tackling forms with polymorphic models. For instance I have Phoneable and User, so when I create my form to register a user, I want to be able to assign a few phone numbers to the user (ie: cell, work, home).
class User < ActiveRecord::Base
has_many :phones, :as => :phoneable
end
class Phone < ActiveRecord::Base
belongs_to :phoneable, :polymorphic => true
end
class CreateUsers < ActiveRecord::Migration
t.column :name, :string
t.references :phoneable, :polymorphic => true
end
class CreatePhones < ActiveRecord::Migration
t.column :area_code, :integer
t.column :number, :integer
t.column :type, :string
t.references :phoneable, :polymorphic => true
end
Now when I create my form, I'm getting confused. Normally I would do the following:
- form_for :user, :html => {:multipart => true} do |form|
%fieldset
%label{:for => "name"} Name:
= form.text_field :name
##now how do I go about adding a phone number?
##typically I'd do this:
##%label{:for => "phone"} Phone:
##= form.text_field :phone
Using polymorphism, would I just approach the same way, but use fields_for?
- user_form.fields_for :phone do |phone| %>
%label{for => "area_code"} Area Code:
= phone.text_field :area_code
%label{for => "number"} Number:
= phone.text_field :number
Is this the correct approach in this instance?
Before we go further, I did notice one issue - you do not need the t.references with the has_many side of the association. So you do not need it in the create_user model. What that does is it creates the phonable_id and the phoneable_type columns, you only need that in the polymorphic model.
You are heading down the correct path with the fields_for approach. But in order to get that working, you need to tell the model how to handle those fields. You do that with the accepts_nested_attributes_for class method.
class User < ActiveRecord::Base
has_many :phones, :as => :phoneable
accepts_nested_attributes_for :phones
end
and one minor thing, you will need to have the fields_for point to the exact name of the association
- form_for #user do |user_form|
- user_form.fields_for :phones do |phone|
Instead of
- form_for #user do |user_form|
- user_form.fields_for :phone do |phone|
and make sure you remove your stray %> erb tag :)
More on accepts_nested_attributes_for: http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
I hope this helps!