I have 2 models:
class Brigade < ActiveRecord::Base
attr_accessible :title
has_one :country
end
class Country < ActiveRecord::Base
attr_accessible :title
end
In my _form.html.erb I have:
<%= form_for(#brigade) do |f| %>
<p>
<%= f.label :title %>
<%= f.text_field :title %>
</p>
<p>
<%= f.label "Country" %>
<%= f.collection_select :country_id, Country.all, :id, :title %>
</p>
<% end %>
Running this I have a message:
undefined method `country_id' for #<Brigade:0x9a89cac> (ActionView::Template::Error)
I think in this case Rails must automatically join country_id to brigade, but it is not.
I don't know where is my mistake. Is it necessary to use accepts_nested_attributes_for?
Related
Rails : 5.1.4
I'm trying to search on :immo_type or/and :address
class SearchesController < ApplicationController
def home
#search = Purchase.find(params[:immo_type])
#purchases = Purchase.where("immo_type ILIKE ?", "%#{#search}%")
end
def index
#purchases = Purchase.all
#spurchases = Purchase.search_by_immo_type_and_address('#search')
end
end
From the view i used simple_form_for. I don't know how to see how to access the content of params[:immo_type]. When i used rails, i've this message
Couldn't find Purchase with 'id'=
I can see all my purchases with Purchase.all
<%= simple_form_for :immo_type, url: searches_url, method: :get do |f| %>
<%= f.hidden_field :immo_type, params[:immo_type] %>
<%= f.input :address, placeholder: 'Town', label: "Where" %>
<%= f.input :immo_type, placeholder: 'flat, house', label: "Flat or house" %>
<%= f.button :submit, "Rechercher", class: "btn btn-danger" %>
<% end %>
Here my models
class Purchase < ApplicationRecord
include PgSearch
pg_search_scope :search_by_immo_type_and_address, against: [:immo_type, :address]
belongs_to :user
has_many :users, :through => :searches
end
class Search < ApplicationRecord
belongs_to :user
belongs_to :leasing
belongs_to :purchase
end
I would like to search from my home.html.erb (root pages) and display the result on my index.html.erb
SearchesIndex
<ul>
<% #purchases.each do |purchase| %>
<li><%= link_to purchase.address %></li>
maison ou appartement : <%= purchase.immo_type %><br>
prix : entre <%= purchase.price_min %> et <%= purchase.price_max %><br>
<% end %>
</ul>
So, first i need to work with a search controller with the home and index views
class SearchesController < ApplicationController
def home
#searches = params[:immo_type]
end
def index
#purchases = Purchase.search_by_immo_type_and_address("#{params[:purchase][:immo_type]}")
end
end
This is my purchase model with Pg_Search gem
class Purchase < ApplicationRecord
belongs_to :user
has_many :users, :through => :searches
include PgSearch
pg_search_scope :search_by_immo_type_and_address, against: [:immo_type]
end
And the view with simple_form_for
<%= simple_form_for :purchase, url: searches_url, method: :get do |f| %>
<%= f.input :address %>
<%= f.input :immo_type %>
<%= f.button :submit, "Rechercher"%>
<% end %>
I hope it can help you !
I'm following this tutorial and the author is using Slim. Since I more familiar with standard Rails form, I try to change the slim markup to normal form like so:
new.html.erb
<%= render 'form' %>
_form.html.erb
<%= form_for(#user) do |f| %>
<%= f.text_field :name %>
<br><br>
<%= fields_for :user_photos do |photo| %>
<%= render "user_photo_fields", f: photo %>
<span class="links">
<%= link_to_add_association "add photo", f, :user_photos %>
</span>
<% end %>
<%= f.submit %>
<% end %>
_user_photo_fields.html.erb
<div class="nested-fields">
<div class="field">
<%= f.file_field :photo %>
</div>
<%= link_to_remove_association "remove", f %>
</div>
And, this is my models:
class User < ActiveRecord::Base
has_many :user_photos
validates_presence_of :name
accepts_nested_attributes_for :user_photos, allow_destroy: true
end
class UserPhoto < ActiveRecord::Base
belongs_to :user
mount_uploader :photo, PhotoUploader
end
And lastly, strong params inside the users_controller.rb. I didn't touch the rest methods inside the controller because I'm using rails g scaffold user name:string generator.
def user_params
params.require(:user).permit(:name, user_photos_attributes: [:id, :photo, :_destroy])
end
I get this error:
undefined method `new_record?' for nil:NilClass
What am I missing here?
I believe it's just a simple typo - your fields_for :user_photos should be f.fields_for :user_photos (so that it's properly connected to the parent form).
please try with this.
class User < ActiveRecord::Base
has_many :user_photos
validates_presence_of :name
accepts_nested_attributes_for :user_photos, allow_destroy: true
end
can you try to fix this by removing the f
<div class="nested-fields">
<div class="field">
<%= file_field :photo %>
</div>
<%= link_to_remove_association "remove" %>
</div>
I have three models: Lesson, Questions and Answers.
What I'm trying to do is on the show lesson view, display the questions and allow users to create answers for each answer. However, I'm not sure the best way to do this.
I tried this approach on my lesson#showview:
<% #questions.each do |question| %>
<%= question.content %><br /><br />
<%= simple_form_for :answers do |f| %>
<%= f.input :content %>
<%= f.hidden_field :question_id, :value => question.id %>
<%= f.button :submit %>
<% end %>
<% end %>
With this code, I receive the error param is missing or the value is empty: lesson
Answer has two fields: content, question_id.
My other concern is that I'd like to have this be user friendly, so if there are multiple questions, there should be multiple input boxes for the answers (one per each question) and one submit button (so multiple answers can be posted at one time).
I think that my approach my bad, but I'm not sure how else to do this, so any help would be greatly appreciated.
Here's what I have so far:
Models:
class Lesson < ActiveRecord::Base
has_many :questions, dependent: :destroy
has_many :answers, through: :questions
accepts_nested_attributes_for :questions, reject_if: :all_blank, allow_destroy: true
accepts_nested_attributes_for :answers, reject_if: :all_blank, allow_destroy: true
end
class Question < ActiveRecord::Base
belongs_to :lesson
has_many :answers, dependent: :destroy
end
class Answer < ActiveRecord::Base
belongs_to :question
end
Lessons Controller
class LessonsController < ApplicationController
def show
#questions = #lesson.questions
end
# PATCH/PUT /lessons/1
# PATCH/PUT /lessons/1.json
def update
respond_to do |format|
if #lesson.update(lesson_params)
format.html { redirect_to #lesson, notice: 'Lesson was successfully updated.' }
format.json { render :show, status: :ok, location: #lesson }
else
format.html { render :edit }
format.json { render json: #lesson.errors, status: :unprocessable_entity }
end
end
end
private
def lesson_params
params.require(:lesson).permit(:name,
answers_attributes: [:id, :content, :question_id]
)
end
end
routes.rb
resources :lessons
post '/lessons/:id', to: "lessons#update"
Add gem in Gemfile and run bundle install:-
gem "nested_form"
On lession show page:-
<%= nested_form_for #lession do |lession_form| %>
<%= #lession.content %>
<%= lession_form.fields_for :questions do |question_form| %>
<% #questions.each do |question| %>
<%= question.content %><br /><br />
<%= question_form.fields_for :answers do |answer_form| %>
<%= answer_form.text_field :content %>
<%= answer_form.link_to_remove "Remove this answer" %>
<% end %>
<%= question_form.link_to_add "Add more answer", :answers %>
<% end %>
<% end %>
<%= lession_form.submit 'Update' %>
<% end %>
I would have thought you are able to achieve without the use of a Gem.
You may need to specify inverse_of in your model. I have previously found this was required in nested attributes when dealing with forms.
class Question < ActiveRecord::Base
belongs_to :lesson
has_many :answers, dependent: :destroy, :inverse_of => :question
end
class Lesson < ActiveRecord::Base
has_many :questions, dependent: :destroy, :inverse_of => :lessons
has_many :answers, through: :questions
#etc.
end
In your lessons controller:
def show
#lesson = Question.find(params[:id])
#questions = #lesson.questions
x.times { #lesson.questions.answer.build }
end
In your views/lessons/show page:
<%= form_for #lesson do |lesson| %>
<%= #lesson.whatever_attribute %>
<%= lesson.fields_for :questions do |question| %>
<% #questions.each do |question| %>
<%= question.content %>
<% end %>
<div id="answers-div" class='form-group'>
<%= question_form.fields_for :answers do |answer| %>
<%= answer.text_field :content id:"answer-entry" %>
<% end %>
</div>
<% end %>
<% end %>
<%= lesson.submit 'Submit' %>
Below the form add some buttons to add further answers or remove:
<button class="btn btn-default" id="addNewAnswer">Add Another Answer Box</button><br>
<button class="btn btn-default" id="deleteNewAnswer">Delete Last Answer</button>
You can then add & remove answers on the fly with jQuery.
$(document).ready(function(){
$("#addNewAnswer").click(function() {
$("#answers-div").append(createNewInputElement($("#answers-div")));
});
});
function createNewInputElement(form) {
var newIndex = $("#answers-div").children('input#choice-entry').length;
var newInput = $("#answer-entry").clone().attr('name', generateNewInputName(newIndex));
newInput.val('');
return newInput;
};
function generateNewInputName(idx) {
return "question[answers_attributes][" + idx + "][content]"
};
$(document).ready(function(){
$("#deleteNewAnswer").click(function() {
if ($("#answers-div input").length > 1) {
$("#answers-div input:last-child").remove();
}
});
});
The use of a nested form is not an issue. You require a nested form to allow you to nest answers within your lessson.questions but you are only allowing the user to give input
If using Rails 4 (and the Strong params) you will also need to allow these with something along these lines (otherwise the params being passed will not be allowed through).
private (in your Lessons controller)
def lesson_params
params.require(:lesson).permit(:content, answer_attributes:[:content])
end
This may not be perfect but it's the start of some sort of solution to your question I would hope.
Try to testing this code, an email me again
in your lesson#show.html.erb
<% for question in #lesson.questions %>
<%= question.content %><br /><br />
<%= simple_form_for :answers do |f| %>
<%= f.input :content %>
<%= f.hidden_field :question_id, :value => question.id %>
<%= f.button :submit %>
<% end %>
<% end %>
I struggle with nested forms.
There're three classes Recipe, Quantity and Ingredient:
class Recipe < ActiveRecord::Base
belongs_to :user
has_many :quantities
has_many :ingredients, through: :quantities
accepts_nested_attributes_for :quantities
class Quantity < ActiveRecord::Base
belongs_to :recipe
belongs_to :ingredient
accepts_nested_attributes_for :ingredient, :reject_if => :all_blank
class Ingredient < ActiveRecord::Base
has_many :quantities
has_many :recipes, :through => :quantities
Recipe Controller
def new
#recipe = current_user.recipes.build
#quantity = #recipe.quantities.build
end
def create
#recipe = current_user.recipes.build(recipe_params)
if #recipe.save
redirect_to #recipe
else
render 'new'
end
end
private
def recipe_params
params.require(:recipe).permit(
:name,
quantities_attributes: [:id, :amount, :ingredient_id],
)
end
View for recipe#new
<%= form_for #recipe, html: {class: "form-horizontal"} do |f| %>
<li class="control-group">
<%= f.label :name, "Recipe Name", class: "control-label" %>
<div class="controls"><%= f.text_field :name %></div>
</li>
<%= f.fields_for :quantities do |quantity| %>
<%= render 'quantity_fields', f: quantity %>
<% end %>
<%= f.submit %>
<% end %>
_quantity_fields
<%= f.label :amount, "Amount:" %>
<%= f.text_field :amount %>
Here should follow a Select input with content from Ingredient and the POST request should insert the ingredient_id in the column of Quantity.
<%= f.select("ingredient_id", "ingredient_id", Ingredient.all.collect
{|p| [ p.name, p.id ] }, {include_blank: 'Choose'}) %>
getting
NoMethodError in Recipes#new
Showing C:/Sites/4.2/sample_app - Kopie/app/views/recipes/_quantity_fields.html.erb
where line #6 raised:
undefined method `merge' for [["Sugar", 1], ["Butter", 2]]:Array
Any ideas? Thanks!
<%= f.collection_select(:ingredient_id, Ingredient.all, :id, :name) %>
solved the select statement
but how can I create multiple quantities here?
I am stuck on the error "Can't mass-assign protected attributes: user" for my form. I have a user that creates a family and other users through a single form. Currently I am trying to create the functionality to have the user create a new family and one new user in one form. I have the Cocoon gem installed and am using Rails 3.2.16. https://github.com/nathanvda/cocoon
The error is occuring on this line
families_controller.rb
def create
binding.pry
#user = current_user
#family = Family.new(params[:family]) <<<<<
The params are:
=> {"utf8"=>"✓",
"authenticity_token"=>"EqWGxK3Fuj2uYk3namWK9SbXLPRKSn6cReT7wQddG0E=",
"family"=>
{"name"=>"test Family",
"users_attributes"=>{"0"=>{"first_name"=>"jane", "last_name"=>"smith"}}},
"commit"=>"Create Family",
"action"=>"create",
"controller"=>"families"}
Models
user.rb
class User < ActiveRecord::Base
attr_accessible :first_name, :last_name, :age_months, :height_inches, :weight_ounces
has_many :user_families
has_many :families, through: :user_families
end
family.rb
class Family < ActiveRecord::Base
attr_accessible :location, :name, :users_attributes, user_families_attributes
has_many :user_families
has_many :users, through: :user_families
accepts_nested_attributes_for :users, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :user_families, :reject_if => :all_blank, :allow_destroy => true
end
View
families.new.html.erb
<%= form_for(#family) do |f| %>
<form class = 'form-horizontal' role = 'form'>
<div class='form-group'>
<%= f.label :name %>
<%= f.text_field :name, placeholder: 'Family Name' %>
</div>
<div class='form-group'>
<%= f.fields_for #new_user do |ff| %>
<%= label_tag :first_name %>
<%= ff.text_field :first_name, placeholder: 'First Name' %>
<%= label_tag :last_name %>
<%= ff.text_field :last_name, placeholder: 'Last Name' %>
<%= label_tag :age_months %>
<%= ff.number_field :age_months, placeholder: 'Enter Age' %>
<%= label_tag :height_inches %>
<%= ff.number_field :height_inches, placeholder: 'Height in Inches' %>
<%= label_tag :weight_ounces %>
<%= ff.number_field :weight_ounces, placeholder: 'Weight in Pounds' %>
<% end %>
</div>
<div class='actions'>
<%= f.submit %>
</div>
</form>
<% end %>
Controller
families_controller.rb
class FamiliesController < ApplicationController
def index
#families = Family.all
end
def show
#user = current_user
#family = Family.find(params[:id])
end
def new
#user = current_user
#family = Family.new(name: "#{#user.last_name} Family")
#family.users.build
#new_user = User.new
end
def edit
#family = Family.find(params[:id])
end
def create
#user = current_user
#family = Family.new(params[:family])
#family.users << #user
#family.save
redirect_to root_path
end
def update
#family = Family.find(params[:id])
#family.update_attributes(params[:family])
#family.save
redirect_to root_path(anchor: 'profile')
end
def destroy
#family = Family.find(params[:id])
#family.destroy
redirect_to families_path
end
end
Family and User are associated with 1-M relationship.
In your view families/new.html.erb
Change
<%= f.fields_for #new_user do |ff| %>
To
<%= f.fields_for :users, #new_user do |ff| %>