i have a opponents model, and a team model, i want to be able to create opponents on the fly, and have them assigned to a team id
at present within my model i have, which is creating the opponent but with a null team_id
def opponent_name
opponent.try(:name)
end
def opponent_name=(name)
self.opponent = Opponent.find_or_create_by_name_and_team_id(name,self.team_id) if name.present?
end
and in my view i am calling this method with the following
.row
.columns.large-2
= f.label :opponent_name, :class =>'left inline'
.columns.large-4
= f.text_field :opponent_name, data: {autocomplete_source: Opponent.order(:name).map(&:name)}
Shouldn't it be:
def opponent_name=(name)
self.opponent = Opponent.find_or_create_by_name_and_team_id(name,self.id) if name.present?
end
if this is a function in the Team model?
Related
I'm trying to create a select input that takes specific User models and displays them as a string while saving them as an integer. Typically I would set the enumerable up the same way as below but as a static hash.
While attempting to create a new Product, I keep receiving the following error: "undefined local variable or method `user_business_hash'"
I've tried moving the 'user_business_hash' method to application/products controller, application/products helper with no luck.
Model
enum user_id: user_business_hash
validates :user_id, inclusion: user_ids.keys
def user_business_hash
# output: {User.business_name => User.id }
# ex: {"Business Name A"=>2, "Business Name B"=>1, "Business Name C"=>5}
array = User.where(account_type: 'Business').map{|x| [x.business_name, x.id] }
hash = array.inject({}) do |memo, (key, value)|
memo[key] = value
memo
end
return hash
end
Form
<%= form.select :user_id, Product.user_ids.keys, prompt: 'Select', id: :product_user_id %>
I think that what you actually want is:
on your controller
#options = User.where(account_type: 'Business')
on your view
options_from_collection_for_select(#options, "id", "business_name")
I have a model A that can have up to 10 associated models B in a one-to-many relationship. These nested models have just a string attribute representing a word.
I want to display a form to create/edit the parent model and all the nested children, displaying fields for the 10 possible models. Then, if I only fill up two of them, two models will be created.
Finally, when editing model A I need to display 10 fields, two of them filled up with the model B associated with A data, and the rest blank ready to fill.
Tried fields_forwith an array, but it only displays fields for the already existing model B instances.
View:
= form_for #a, remote: true do |f|
= f.text_field :title, placeholder: true
= f.fields_for :bs, #a.bs do |ff|
/ Here, for the edit action, N text fields appear, being N equals to #soup.soup_words.size
/ and I need to display 10 fields everytime, because a Soup can have up to 10 SoupWord
/ For the new action, it should display 10 empty text fields.
/ Finally, if you fill three of the 10 fields,
/ model A should have only 3 instances of model B associated. i.e if there were 4 filled and
/ I set one of them blank, the model B instance should be destroyed.
= ff.text_field :word, placeholder: true
= f.submit
Controller:
class Bs < ApplicationController
def edit
respond_to :js
#soup = Soup.find params[:id]
end
def update
respond_to :js
puts params
end
end
Update
Create and edit actions now work, just put a reject_if parameter in model A,
accepts_nested_attributes_for :bs, reject_if: proc { |attrs| attrs[:word].blank? }
and set the build on the controller.
def new
respond_to :js
#a = A.new
10.times { #a.bs.build }
end
def edit
respond_to :js
#a = Soup.find params[:id]
#a.bs.size.upto(9) do |sw|
#a.bs.build
end
end
Now I need to destroy instances of model B if I set them blank in the edit action.
Normally you would delete nested records by using the allow_destroy: true option and by passing the _destroy param:
class Soup
accepts_nested_attributes_for :soup_words,
reject_if: proc { |attrs| attrs[:word].blank? },
allow_destroy: true
end
To get the behavior you want you can use javascript with a hidden input:
= form_for #soup, remote: true do |f|
= f.text_field :title, placeholder: true
= f.fields_for :soup_words, #soup.soup_words do |ff|
= ff.text_field :word, class: 'soup_word', placeholder: true
= ff.hidden_input :_destroy
= f.submit
$(document).on('change', '.soup_word', function(){
var $obj = $(this);
if (!this.value || !this.value.length) {
// set soup_word to be destroyed
$obj.siblings('input[name~=_destroy]').val('1');
}
$obj.fadeOut(50);
});
Make sure you have whitelisted the _destroy and id params.
def update_params
params.require(:soup).permit(:soup_words_attributes: [:word, :id, :_destroy])
end
I have a student model with fields :name, :address.
I want to create 2 different fields :country, :city, that, when filled in and submitted, would concatenate into the address db field.
How can it be done? Must I define something in student.rb? Or just some form view?
my student/_form.haml:
= simple_form_for #student do |f|
= f.input :name
= f.input :country #not in db
= f.input :city #not in db
= f.button :submit
(address must equal country + " " + city)
Note: I do not want to create separate db fields for country & city.
You can do it in following ways
make address in model --> this is the best way
make address in controller --> this is good way
way no 1
in model
attr_accessor :country
attr_accessor :city
def before_save
self.address = #country + " " + #city
end
in controller
def save
student = Student.new()
student.country = params[:country]
student.city = params[:city]
student.save
end
way no 2
For example model student, controller Student
in controller
def save
student = Student.new
student.address = params[:country] + " " + params[:city]
student.save
end
I hope it helps.
here is my code:
Perk not save on multiple select,when multiple true/false. perk save and habtm working.
class Perk < ActiveRecord::Base
has_and_belongs_to_many :companies
end
class Company < ActiveRecord::Base
has_and_belongs_to_many :perks
end
view perk/new.html.erb
<%= select_tag "company_id", options_from_collection_for_select(Company.all, 'id', 'name',#perk.companies.map{ |j| j.id }), :multiple => true %>
<%= f.text_field :name %>
Controller's code:
def new
#perk = Perk.new
respond_with(#perk)
end
def create
#perk = Perk.new(perk_params)
#companies = Company.where(:id => params[:company_id])
#perk << #companies
respond_with(#perk)
end
Your select_tag should return an array of company_ids:
<%= select_tag "company_ids[]", options_from_collection_for_select(Company.all, 'id', 'name',#perk.companies.map{ |j| j.id }), :multiple => true %>
http://apidock.com/rails/ActionView/Helpers/FormTagHelper/select_tag#691-sending-an-array-of-multiple-options
Then, in your controller, reference the company_ids param:
#companies = Company.where(:id => params[:company_ids])
(I assume that you've intentionally left out the #perk.save call in your create action... Otherwise, that should be included as well. Model.new doesn't store the record.)
It sounds like you may not have included company_id in the perk_params method in your controller. Rails four uses strong pramas this means you need to state the params you are allowing to be set.However it is difficult to say for sure without seeing more of the code.
In your controller you should see a method like this (there may be more options that just :name):
def perk_params
params.require(:perk).permit(:name)
end
You should try adding :company_id to it so it looks something like this:
def perk_params
params.require(:perk).permit(:name, :company_id)
end
if there are other params int your method leave them in and just added :company_id
EDIT to original answer
The above will only work on a one-to-many or one-to-one because you are using has_and_belongs_to_many you will need to add companies: [] to the end of your params list like this
def perk_params
params.require(:perk).permit(:name, companies: [] )
end
or like this
def perk_params
params.require(:perk).permit(:name, companies_ids: [] )
end
See these links for more details:
http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters
I generated two scaffolds: creditcards and creditscore.
There's a has_many association between users and creditcards.
There's a has_one association between users and creditscore.
In the creditcards credits.html.erb view, I'm trying to display the current_user's score from the creditscore model.
Here's what I've tried putting in creditcards_controller.rb:
def credits
#creditscores = Creditscore.find_all_by_user_id current_user[:id] if current_user
#creditscore = current_user.creditscore
end
And in credits.html.erb view:
<%= creditscore.score %>
Here's the error:
undefined local variable or method `creditscore' for #<#<Class:0x00000101a69558>:0x00000101a68680>
Only instance variables intialized in the controller is available in the views.
You should use
<%= #creditscore.score %>
Example:
Model: Dogs
Model: Cats
Controller: Cats
1 - Set your global in Cats controller:
#dogs = Dogs.all
2 - Use #dogs in your Cats view:
<%= #dogs.cats_hunted %>