When a :user_id is selected how can we show in collection_select that user's challenges? In other words, how can we make #user equal to whatever :user_id was selected in _dueler_fields?
duels/_form.html.erb
<%= simple_form_for(#duel) do |f| %>
<%= f.fields_for :duelers do |dueler| %>
<%= render 'dueler_fields', :f => dueler %>
<% end %>
<%= link_to_add_association f, :duelers do %>
+ Dueler
<% end %>
The loser(s) will <%= f.text_field :consequence, placeholder: "Enter Consequence" %>
<% end %>
duels/_dueler_fields.html.erb
<%= f.select :user_id, User.order(:name).map { |user| [user.full_name, user.id] } %> will
<%= collection_select(:dueler, :challenge_id, #challenges, :id, :full_challenge) %>
duels_controller
def new
#duel = Duel.new
#duel.duelers << Dueler.new(user_id: current_user.id, user_name: current_user.name, user_last_name: current_user.last_name)
#user = # How can we set this to whatever was selected?
#challenges = #user.challenges.order(:created_at)
end
schema.rb
create_table "duelers", force: true do |t| #belongs_to :user & :challenge & :duel
t.integer "user_id"
t.integer "challenge_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "duel_id", null: false
t.boolean "accept"
t.string "user_name"
t.string "user_last_name"
t.string "challenge_name"
end
add_index "duelers", ["duel_id"], name: "index_duelers_on_duel_id", using: :btree
create_table "duels", force: true do |t| #belongs_to :user & :challenge, has_many :duelers
t.text "consequence"
t.text "reward"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
UPDATE
<%= f.select :user_id, User.order(:name).map { |user| [user.full_name, user.id] }, include_blank: true, id: "change-challenge-options" %> will
<%= collection_select(:dueler, :challenge_id, #challenges, :id, :full_challenge, include_blank: true) %>
<script> # Doesn't Work
$( "#change-challenge-options" ).change(function() {
$.ajax({
type: "GET",
url: '<%= user_challenges_path %>',
data: {name: $('#change-challenge-options').prop('value')}
});
});
</script>
Is not necessary go to controller to get user challenges while refreshing the page, the best form to solve it seems to get a function that returns the challenges to a json petition activated from the "change" action of the users_id select
in users_controller:
def challenges
user = User.find_by_id(user_params)
#challenges = user.challenges.order(:created_at)
respond_to |format|
format.js { render json: #challenges.as_json, status: 200 }
end
end
def user_params
params.require(:user).permit(:user_id)
end
in javascript:
$("#user_select").on("change", function(){
// make ajax petition with the user: {user_id: $(this).val()}
// and rescue the results to display wher you want
})
Related
server log:
`ActionController::ParameterMissing (param is missing or the value is empty: comment)`
used pry gem gem params:
<ActionController::Parameters {"utf8"=>"✓", "comment_name"=>"123432",
"comment_description"=>"231424", "commit"=>"submit",
"controller"=>"comments", "action"=>"create", "article_id"=>"5"} permitted: false>
I know the :comment should wrapper coment_name and comment_description
so on validate add submitHandler try fix the format error
click submit button the browser show:
jquery validate:
$(function () {
$("form#new_comment").validate({
rules: {
comment_name: {
required: true,
minlength: 3
},
comment_description: {
required: true,
minlength: 5
},
submitHandler: function (form) {
$.ajax({
url: form.action,
type: form.method,
data: $(form).serializeArray(),
dataType: 'script'
});
}
}
});
});
_form.html.erb:
<%= simple_form_for [#article, #article.comments.build], remote: true do |f| %>
<%= f.input :name, input_html: { name: "comment_name"} %>
<%= f.input :description, input_html: { name: "comment_description" } %>
<%= f.submit :submit, class: "btn btn-default" %>
<% end %>
comment_controller:
class CommentsController < ApplicationController
before_action :get_article
before_action :authenticate_user!
def create
#comment = #article.comments.create(comment_params)
#comment.user_id = current_user.id
if #comment.save
respond_to do |format|
format.html { redirect_to #article, notice: "creaed succeed"}
format.js { }
end
else
redirect_to #article, notice: "characters is too short or name has been taken"
end
end
def destroy
#comment = #article.comments.find(params[:id])
if #comment.destroy
respond_to do |format|
format.html { redirect_to #article }
format.js { }
end
end
end
private
def comment_params
params.require(:comment).permit(:name, :description, :article_id, :user_id)
end
def get_article
#article = Article.find(params[:article_id])
end
end
any help thank 🙃
The controller expects
<ActionController::Parameters {"utf8"=>"✓", "comment"=>
{name"=>"123432","description"=>"231424"}, "commit"=>"submit",
"controller"=>"comments", "action"=>"create", "article_id"=>"5"}
permitted: false>
In your form, by declaring "name" attributes for the 'name' and 'description' fields, you are essentially overwriting the "name" field's name from comment[name] to comment_name. So just remove those name attributes from your form
<%= simple_form_for [#article, #article.comments.build], remote: true do |f| %>
<%= f.input :name%>
<%= f.input :description%>
<%= f.submit :submit, class: "btn btn-default" %>
<% end %>`
I have a problem with my nested attributes. I want someone to be able to just visit my website and add songs to an event. They can only add those songs if they supply a partycode for that event. I have my nested attributes set up correctly I think but I am getting an unpermitted paramter error.
Events controller:
class EventsController < ApplicationController
def new
#event = Event.new
#event.songs.build
end
def show
#event = Event.find(params[:id])
#songs = #event.songs.paginate(page: params[:page])
end
def create
#event = current_user.events.build(event_params)
if #event.save
flash[:success] = "Event Created!"
redirect_to user_path(#event.user)
else
render 'welcome/index'
end
end
def destroy
end
private
def event_params
params.require(:event).permit(:name, :partycode, song_attributes: [:artist, :title, :genre, :partycode])
end
end
application_controller:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
include SessionsHelper
end
Here is the new.html.erb file in the songs view, which contains the code to add songs to the event, note that the user is not signed in when they are adding songs:
<br>
<br>
<div class ="container">
<div class="jumbotron">
<%= form_for Event.new do |f| %>
<h3>Enter a song:</h3>
<%= f.fields_for :songs, Song.new do |song_form| %>
<%= song_form.collection_select(:event_id, Event.all, :id, :name) %>
<%= song_form.text_field :artist, placeholder: "Artist" %>
<%= song_form.text_field :title, placeholder: "Title" %>
<%= song_form.text_field :genre, placeholder: "Genre" %>
<% end %>
<%= link_to_add_fields "Add Song", f, :songs %>
<%= f.text_field :partycode %>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
The link_to_add_fields method is in the application_helper.rb file:
module ApplicationHelper
def link_to_add_fields(name, f, association)
new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, child_index: id) do |builder|
render("songs_fields", f: builder)
end
link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
end
end
The songs_field partial is defined as follows:
<fieldset>
<%= f.text_field :artist, placeholder: "Artist" %>
<%= f.text_field :title, placeholder: "Title" %>
<%= f.text_field :genre, placeholder: "Genre" %>
</fieldset>
The coffee-script that adds the fields:
$(document).on 'click', 'form .add_songs', (event) ->
time = new Date().getTime()
regexp = new RegExp($(this).data('event_id'), 'g')
$(this).before($(this).data('songs').replace(regexp, time))
event.preventDefault()
The person from the new.html.erb page will be able to select a event from the drop down menu then on demand add more fields that are for a song and then enter a partycode for the certain event that they picked. Any help on this would be fantastic! Thanks
EDIT error:
undefined method `events' for nil:NilClass
In your EventsController, your nested params is spelled as song_attributes in event_params method
private
def event_params
params.require(:event).permit(:name, :partycode, song_attributes: [:artist, :title, :genre, :partycode])
end
But your error says unpermitted parameter: songs_attributes.
You spelled it incorrect.Change your event_params method in EventsController as follows
private
def event_params
params.require(:event).permit(:name, :partycode, songs_attributes: [:artist, :title, :genre, :partycode])
end
I am encountering a minor problem with some javascripts/AJAX and i was hoping someone can help me or point me to the right direction.
What I am trying to do is to populate my per-carton-price-field using collection_select in the same form. This is an order form which is suppose to create an entry into my order table. Form view as below:
new.html.erb
<h1>Add a new order for <%= #customer.name %></h1>
<div class="row">
<%= form_for(#order) do |f| %>
<div class="col-md-6">
<%= render 'shared/error_messages', object: f.object %>
<%= f.hidden_field :customer_id, :value => #customer.id %>
<h3>Order Details</h3>
<%= f.label :address_id, "Delivery Address" %>
<%= f.collection_select :address_id, #addresses, :id, :select_address, :prompt => "Select delivery location",class: 'form-control' %></br>
<%= f.label :remark, "Order Remark" %>
<%= f.text_area :remark, class: 'form-control' %></br>
<h3>What items would you like to place?</h3>
<%= f.add_nested_fields_link :single_orders, "Add Product" %>
<%= f.nested_fields_for :single_orders do |builder| %>
<%= builder.collection_select :product_id, #products, :id, :select_product, {:prompt => "choose product"}, {:class => "product_selection form-control"} %>
<%= builder.text_field :ctn_price, placeholder: "Price/carton", id: "price", class: 'ctn_price_field form-control' %>
<%= builder.text_field :qty, placeholder: "Quantity",id: "quantity", class: 'form-control' %>
<%= builder.text_field :price, placeholder: "Amount", id: "total-amount", readonly: true, class: 'form-control' %>
<%= builder.remove_nested_fields_link %>
<% end %>
</div>
<%= f.submit "place order", class: "btn btn-primary" %>
<% end %>
</div>
I would like the collection_select:product_id to pull out all the products in the products table. When the user selects whichever product they want to order from the dropdown, the price for the selected product will populate the text_field:ctn_price.
product.rb
class Product < ActiveRecord::Base
has_many :special_prices, dependent: :destroy
has_many :single_orders
has_many :package_orders_products
before_save :upcase_stock_code
validates :name, presence: true, length: { maximum: 50 }
validates :stock_code, presence: true, length: { maximum: 20 }
validates :status, presence: true, length: { maximum: 10 }
validates :price, presence: true
private
def select_product
"#{name} - #{price}"
end
# Converts stock_code to all upper-case.
def upcase_stock_code
self.stock_code = stock_code.upcase
end
end
single_order.rb
class SingleOrder < ActiveRecord::Base
belongs_to :order
belongs_to :product
validates :order, presence: true
validates :product_id, presence: true
validates :qty, presence: true
validates :price, presence: true
validates :ctn_price, presence: true
end
Any help is appreciated as I have been stuck for days :(
Thanks for any help in advance.
You can do this using ajax call. Before that create a api to take product_id as input and render #product as output.
$("#product_selection_id").on('change', function(){
var product_id = $(this).val();
$.ajax({
method: "GET",
type: 'html',
url: "call_url_for_get_product_api_with_product_id",
cache: false,
success: function(data, textStatus, jqxhr) {
console.log("success");
}
});
});
Suppose your url_for_get_product_api goes to get_product action as a js request. so create a template with get_product.js.erb as follows
$('#ctn_price_field').val(#product.price)
#ihave not tested this code change this according to your requirements.
Note: Here i have given a pattern impliment this by your own. Thanks.
Im trying to update my create item action to work with Ajax but Im getting an error of undefined methoditem_path` which i wasn't getting before when it was responding in regular html format. The item is created and saved but ajax doesn't seem to work properly though.
Here is my _from partial :
<%= form_for [#user, item], remote: true do |f|%>
<div class="form-group">
<%= f.label :name, class: 'sr-only' %>
<%= f.text_field :name , class: 'form-control', placeholder: "Enter a new item " %>
</div>
<%= f.submit "Submit Item", class: 'btn btn-primary pull-right' %>
<% end %>
item#create:
def create
#item = Item.new(item_params)
#item.user = current_user
if #item.save
flash[:notice] = 'Item saved successfully.'
else
flash[:alert] = 'Item not saved. Title is too short or missing. Please try again.'
end
respond_to do |format|
format.html
format.js
end
end
create.js.erb:
$('.js-items').prepend("<%= escape_javascript(render(#item)) %>");
$('.new-item').html("<%= escape_javascript(render partial: 'items/form', locals: {user: #user , item: #item }) %>");
User#show view
<div class='new_item'>
<%= render :partial => 'items/form', :locals =>{:item => Item.new , :user => #user} %>
</div>
<div class='js-items'>
<%= render #user.items %>
</div>
routes:
user_items GET /users/:user_id/items(.:format) items#index
POST /users/:user_id/items(.:format) items#create
new_user_item GET /users/:user_id/items/new(.:format) items#new
edit_user_item GET /users/:user_id/items/:id/edit(.:format) items#edit
user_item GET /users/:user_id/items/:id(.:format) items#show
PATCH /users/:user_id/items/:id(.:format) items#update
PUT /users/:user_id/items/:id(.:format) items#update
DELETE /users/:user_id/items/:id(.:format) items#destroy
The error im getting in rails s :
ActionView::Template::Error (undefined method `item_path' for #<#<Class:0x007fa4f0d30cd8>:0x007fa4f31b26b0>):
1: <%= form_for [#user, item], remote: true do |f|%>
2: <div class="form-group">
3: <%= f.label :name, class: 'sr-only' %>
4: <%= f.text_field :name , class: 'form-control', placeholder: "Enter a new item " %>
app/views/items/_form.html.erb:1:in `_app_views_items__form_html_erb__331698480542899910_70173200751480'
app/views/items/create.js.erb:2:in `_app_views_items_create_js_erb___3618987352886002527_70173200313760'
app/controllers/items_controller.rb:17:in `create'
Do something like that.
<%= form_for [#user, item], user_items, remote: true do |f|%>
If it doesn't work then run
rake routes
in terminal see what's your path.
I'm trying to create a new location and a devise user in the same form and link them. The user and the location are created, but the location_id is not saving to the user. There is a location_id column in the user table.
My form
<% resource.build_location %>
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => {:class => 'form-vertical' }) do |f| %>
<%= f.error_notification %>
<!-- capture location details hidden values -->
<%= f.fields_for :location do |location_form| %>
<%= location_form.text_field :name, :name => "name", :type => "hidden" %>
<%= location_form.text_field :street_address, :name => "formatted_address", :type => "hidden" %>
<%= location_form.text_field :lat, :name => "lat", :type => "hidden" %>
<%= location_form.text_field :long, :name => "lng", :type => "hidden" %>
<% end %>
<!-- devise user authenticate -->
<%= f.input :name, :autofocus => true %>
<%= f.input :email, :required => true %>
<%= f.input :password, :required => true %>
<%= f.input :password_confirmation, :required => true %>
<%= f.button :submit, 'Sign up', :class => 'btn-primary' %>
<% end %>
<%= render "devise/shared/links" %>
Location model
class Location < ActiveRecord::Base
has_many :users, :dependent => :destroy
accepts_nested_attributes_for :users, :allow_destroy => true
attr_accessible :lat, :long, :name, :street_address
attr_accessible :user_attributes
end
Location controller
def new
#location = Location.new
#location.user.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: #location }
end
end
# GET /locations/1/edit
def edit
#location = Location.find(params[:id])
end
# POST /locations
# POST /locations.json
def create
#location = #user.location.build(params[:location])
respond_to do |format|
if #location.save
format.html { redirect_to #location, notice: 'Location was successfully created.' }
format.json { render json: #location, status: :created, location: #location }
else
format.html { render action: "new" }
format.json { render json: #location.errors, status: :unprocessable_entity }
end
end
end
User Model
class User < ActiveRecord::Base
belongs_to :location
accepts_nested_attributes_for :location
rolify
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :role_ids, :as => :admin
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :location, :location_id, :location_attributes
end
User controller
class UsersController < ApplicationController
before_filter :authenticate_user!
def index
authorize! :index, #user, :message => 'Not authorized as an administrator.'
#users = User.all
end
def show
#user = User.find(params[:id])
end
def update
authorize! :update, #user, :message => 'Not authorized as an administrator.'
#user = User.find(params[:id])
if #user.update_attributes(params[:user], :as => :admin)
redirect_to users_path, :notice => "User updated."
else
redirect_to users_path, :alert => "Unable to update user."
end
end
def destroy
authorize! :destroy, #user, :message => 'Not authorized as an administrator.'
user = User.find(params[:id])
unless user == current_user
user.destroy
redirect_to users_path, :notice => "User deleted."
else
redirect_to users_path, :notice => "Can't delete yourself."
end
end
end
No errors when creating the user, just getting a location_id="nil" when creating the user. I can access the location and a location_id is created but not linked to the user. Any ideas on how to save the location_id to the user?
I am populating the location info with json returned from a google location api autocomplete and assigning to an element with name="". It seems that everything works fine when I manually enter location info, but fails when the fields are populated from the autocomplete.
The first thing to note is that you do not need accepts_nested_attributes_for on both models, only the one that has the has_many association. Also, it looks like the pluralization is wrong in the Location model for users attributes
class Location < ActiveRecord::Base
has_many :users, :dependent => :destroy
accepts_nested_attributes_for :users, :allow_destroy => true
attr_accessible :lat, :long, :name, :street_address
attr_accessible :users_attributes # <- This should be plural
end
Remove the accepts_nested_attributes_for in the user model
class User < ActiveRecord::Base
belongs_to :location
accepts_nested_attributes_for :location # <- This should be removed
rolify
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :role_ids, :as => :admin
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :location, :location_id # Also remove location_atributes
end
Also, this line
#location = #user.location.build(params[:location])
Should be
#location = Location.new(params[:location)
since the way your models are setup now a location has a user so you do not need to build a location from a user. That being said, I would recommend you create the association in the opposite direction where a user has_many locations, but this of course may be contrary to your function so take it with a grain of salt :).
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html