I have a table: family_children (the model is family_child) where family has many children.
I get the children like this:
#family_children = #family.children
where .children is an association to family_children table.
In a view I want to iterate through the children, and put each of them in a text_field. Of course, I need these fields as params when the page is POSTing. I.e. I think that I should get the children as an array.
How can I achieve that?
I mean, if I'll write
<%= text_field 'child', 'name' %>
I don't really get what I need.
Try something like this in your view:
<% #family_children.each_with_index do |c, i| %>
<%= text_field_tag "children[#{i}]", c.name %>
<br />
<% end %>
This should return params[:children] after posting which should be an array. I wasn't sure of the name of the property you want to show in the text box so I have assumed it is called 'name'.
Actually, #family_children object acts as array, so you can simply call each or map on it.
Do you want to put the children's names in a form field or in the view as just a part of the page text? could you include the view file?
since u want the family_children data to be POSTed, u need to see the concept of nested attributes. please see http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html and http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for
class Family
has_many :children, :class => "FamilyChild"
accepts_nested_attributes_for :children
end
class FamilyChild
belongs_to :family
end
and the form can be as
<%= form_for #family do |p| %>
First name: <%= p.text_field :first_name %>
Last name : <%= p.text_field :last_name %>
<%= fields_for #family.children do |c| %>
<%= c.text_field :child_name %>
<% end %>
<%= f.submit %>
<% end %>
Related
I'm working on an app in Rails that has teacher and student users. I want to list all the users that belong to a teacher and then let the teacher select a student to send a message to. I have a message model that has :content and :user_id for params. I want to set the :user_id based on the student selected. Here is my code:
<% #students = Student.all %>
<% #students.each do |student| %>
<% if student[:teacher_id] == #current_user.id %>
<%= radio_button 'student', 'id', student.id %>
<%= student.name %>
<% #current_student = Student.find(student.id) %>
<% end %>
<% end %>
<%= form_for Message.new do |f| %>
<%= f.text_area :content, class: 'messageTextarea' %> <br>
<%= f.hidden_field :user_id, :value => #current_student.id %>
<%= f.submit %>
<% end %>
So, I am looping through all students and printing those that have the same ID as the current user (the teacher) with a radio button. The radio button's value is the student's id. Then I want to pass that value to the :user_id of the message so it will then be retrievable for the student's view.
Currently, this code always passes in the value of the last student listed rather than the student selected. How can I change
<% #current_student = Student.find(student.id) %>
to find the student selected rather than the last one?
I did test this code using
<%= f.hidden_field :user_id, :value => #current_user.id %>
and that did work, but I don't want the current_user's id, of course. Thanks for any help!
If you want one form with radio buttons for the students, You gonna need a little bit JavaScript(Or Jquery), All you have to do is to put a listener on these radio button and when user click on one of them you change the hidden input of user_id name.
User example in this link will help you to put listener on a bunch of radio buttons and change another field value, it will be something like this:
$('input[type=radio][name=student[id]]').change(function() {
$('#user_id').val($(this).val());
});
all you have to do is to make sure of name=student[id] and #user_id, if you used this approach you won't need this line anymore:
<% #current_student = Student.find(student.id) %>
Hope it works.
I have a model like:
class User < ActiveRecord::Base
enum :status [:banned, :registered, :trial, :pending]
end
On my edit page, I want to show a list of 4 radio buttons and pre-select the radio button that is currently set for a user.
How can I do this?
<%= form_for #user do |f| %>
<%= f.collection_radio_buttons :status, User.statuses, :first, :first %>
<%= f.submit %>
<% end %>
Ref
Rails creates a class method using the pluralized attribute name when you use enum. The method returns a key value pair of strings you've defined and what integers they map to. So, you could do something like this:
<% User.status.keys.each do |status| %>
<%= f.radio_button :status, status %>
<%= f.label status.to_sym %>
<% end %>
I have three Models:
class Question < ActiveRecord::Base
has_many :factor_questions
has_many :bigfivefactors, through: :factor_questions
accepts_nested_attributes_for :factor_questions
accepts_nested_attributes_for :bigfivefactors
end
class Bigfivefactor < ActiveRecord::Base
has_many :factor_questions
has_many :questions, through: :factor_questions
end
and my join-table, which holds not only the bigfivefactor_id and question_id but another integer-colum value.
class FactorQuestion < ActiveRecord::Base
belongs_to :bigfivefactor
belongs_to :question
end
Creating an new Question works fine, using in my _form.html.erb
<%= form_for(#question) do |f| %>
<div class="field">
<%= f.label :questiontext %><br>
<%= f.text_field :questiontext %>
</div>
<%= f.collection_check_boxes :bigfivefactor_ids, Bigfivefactor.all, :id, :name do |cb| %>
<p><%= cb.check_box + cb.text %></p>
<% end %>
This let's me check or uncheck as many bigfivefactors as i want.
But, as i mentioned before, the join model also holds a value.
Question:
How can I add a text-field next to each check-box to add/edit the 'value' on the fly?
For better understanding, i added an image
In the console, i was able to basically do this:
q= Question.create(questiontext: "A new Question")
b5 = Bigfivefactor.create(name: "Neuroticism")
q.bigfivefactors << FactorQuestion.create(question: q, bigfivefactor: b5, value: 10)
I also found out to edit my questions_controller:
def new
#question = Question.new
#question.factor_questions.build
end
But i have no idea how to put that into my view.
Thank you so much for your help!
Big Five Factors model considerations
It looks like your Bigfivefactors are not supposed to be modified with each update to question. I'm actually assuming these will be CMS controlled fields (such that an admin defines them). If that is the case, remove the accepts_nested_attributes for the bigfivefactors in the questions model. This is going to allow param injection that will change the behavior sitewide. You want to be able to link to the existing bigfivefactors, so #question.factor_questions.first.bigfivefactor.name is the label and #question.factor_questions.first.value is the value. Notice, these exist on different 'planes' of the object model, so there wont be much magic we can do here.
Parameters
In order to pass the nested attributes that you are looking for the paramater needs to look like this:
params = {
question: {
questiontext: "What is the average air speed velocity of a sparrow?",
factor_questions_attributes: [
{ bigfivefactor_id: 1, value: 10 },
{ bigfivefactor_id: 2, value: 5 } ]
}
}
Once we have paramaters that look like that, running Question.create(params[:question]) will create the Question and the associated #question.factor_questions. In order to create paramaters like that, we need html form checkbox element with a name "question[factor_questions_attributes][0][bigfivefactor_id]" and a value of "1", then a text box with a name of "question[factor_question_attributes][0][value]"
Api: nested_attributes_for has_many
View
Here's a stab at the view you need using fields_for to build the nested attributes through the fields for helper.
<%= f.fields_for :factor_questions do |factors| %>
<%= factors.collection_check_boxes( :bigfivefactor_id, Bigfivefactor.all, :id, :name) do |cb| %>
<p><%= cb.check_box + cb.text %><%= factors.text_field :value %></p>
<% end %>
<% end %>
API: fields_for
I'm not sure exactly how it all comes together in the view. You may not be able to use the built in helpers. You may need to create your own collection helper. #question.factor_questions. Like:
<%= f.fields_for :factor_questions do |factors| %>
<%= factors.check_box :_destroy, {checked => factors.object.persisted?}, '0','1' %> # display all existing checked boxes in form
<%= factors.label :_destroy, factors.object.bigfivefactor.name %>
<%= factors.text_box :value %>
<%= (Bigfivefactor.all - #question.bigfivefactors).each do |bff| %>
<%= factors.check_box bff.id + bff.name %><%= factors.text_field :value %></p> # add check boxes that aren't currently checked
<% end %>
<% end %>
I honestly know that this isn't functional as is. I hope the insight about the paramters help, but without access to an actual rails console, I doubt I can create code that accomplishes what you are looking for. Here's a helpful link: Site point does Complex nested queries
I have a Product model, an Order, and an OrderItem model.
An OrderItem object has a single Product (that is, it belongs to a product)
An Order has multiple order items.
When you want to add an OrderItem to your order, you fill out a form. One of the fields is to enter the product that will be assigned to this order item. The order model stores the product_id as a foreign key, and so Rails complains (as it should) when I write
<%= form_for #orderItem, url: {:action => :create} do |f| %>
<p>
<%= f.label :product_name %>
<%= f.text_field :product_name %>
</p>
<%= f.submit %>
<% end %>
What I have in mind is to to have someone use the form to create order items. When they choose which product to assign to this order item, they will pick a name from a list of product names (which are unique), and then when they submit the form, the controller retrieves the appropriate Product object and assigns its ID to the OrderItem.
How can I set up my form to accomplish this?
Sounds like you want to use nested attributes. They'll let you save information about both an OrderItem and a Product at the same time from a single form.
In your OrderItem, add the line accepts_nested_attributes_for :product.
Then in your form you'll want something like:
<%= form_for #orderItem, url: {:action => :create} do |f| %>
<p>
<%= fields_for :product do |fp| %>
<%= fp.label :product_name %>
<%= fp.text_field :product_name %>
<% end %>
</p>
<%= f.submit %>
<% end %>
(Note the use of fp.label instead of f.label within the fields_for block.
The above is from memory so there may be some mistakes (and you'll probably need to change things in your OrderItemsController too), but it should give you a starting point.
You might find this Railscast helpful too.
I have what seems like a simple query. I need to create a view that will accept multiple records based on a single model. In my case the model is Project, which has 1 foreign key (person) and 2 fields time, role. I need to create a view (form) to insert 5 roles.
<%= form_for(#project) do |f| %>
<% 5.times do |index|%>
<div class="field">
<%= f.label :position %><br />
<%= f.text_field "fields[#{index}][stime]" %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I get an error message: undefined method `fields[0][stime]'
I do not think the railscasts for nested models is what I need.
How would I go about creating this?
EDIT: The Project model code is below:
class Project < ActiveRecord::Base
belongs_to :person
attr_accessible :role, :stime
end
The Projects_Controller code for the new method is below:
def new
#project = Project.new
end
I see you're planning to make some 1-to-many relationship (Product has_many :roles).
Here's some advices.
First, take a look at the accepts_nested_attributes_for method. You need to add it to your model to be able to perform mass-create.
Second, fields_for is what you need to design nested forms.
I'll give you some example of mass-creating for a simple Product has_many :line_items case:
<%= form_for #product do |f| %>
<%= f.fields_for :line_items, [LineItem.new]*5 do |li_fields| %>
<%= li_fields.text_field :quantity %>
<%= li_fields.text_field :price %>
<br>
<% end %>
<%= f.submit "Create line items" %>
<% end %>
All you need is to write in you controller something like:
#product.update_attributes params[:product]
and 5 line_items will be created at once.
Don't forget to white-list association_attributes (see params in your logs to see it). But I think if you get the mass-assignment error you'll do it anyway :)
I hope it helps.