Issue with has_and_belongs_to_many association in rails - ruby-on-rails

Can you help a noob, please?
I have 2 models - Player and Poker Tables, which have has_and_belongs_to_many association. When i try create player i catch error
undefined method `poker_table'
respond_to do |format|
**if #player.save**
format.html { redirect_to #player, notice: 'Player was successfully created.' }
format.json { render :show, status: :created, location: #player }
else
I use checkboxes for mark needed poker tables, here form code:
<% #poker_tables = PokerTable.all %>
<% #poker_tables.each do |poker_table| %>
<div>
<%= check_box_tag "player[poker_table_ids][]", poker_table.id %>
<%= poker_table.name %>
<%= poker_table.actual_time %>
</div>
<% end %>
create method and params
def create
#player = Player.new(player_params)
respond_to do |format|
if #player.save
format.html { redirect_to #player, notice: 'Player was successfully created.' }
format.json { render :show, status: :created, location: #player }
else
format.html { render :new }
format.json { render json: #player.errors, status: :unprocessable_entity }
end
end
end
def player_params
params.require(:player).permit(:email, :poker_table_ids => [])
end
I can create poker table, but couldn't create a player with associated poker tables.
I don't really understand what I'm doing wrong. I studied a lot of resources about this theme, but i can't find answer.

Related

How to create a method for specific values in a column from a table?

Issue: I am looking for a way to have separate notices for different values in a tables column.
I have order_status that has 3 separate values, created, cancelled, and charged.
I would like 3 separate notices for each when the columns are changed from a view.
a view will be something like:
<%= form_for #order, remote: true do |f| %>
<%= f.hidden_field :order_status, value: "cancelled" %>
<%= f.button type:'submit', class: "btn btn-danger" %>
<% end %>
This will change the column to "cancelled".
I then want to create a method like:
def cancel_update
respond_to do |format|
if #order.update(params[:order_update])
if user_signed_in?
if #order.order_status = "cancelled"
format.html { redirect_to #order, notice: 'Order was successfully cancelled.' }
format.json { render :show, status: :ok, location: #order }
else
format.html { render :edit }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
end
end
But this method didn't work how i planned. When i use this method, nothing happens when i click the button, no page reload, redirect, etc. I get the error: "The action 'update' could not be found for OrdersController"
(This was tested by taking out the original update method - which is below).
Now when i use this update method, it works but doesn't pin point the value update on the order_status only.
def update
respond_to do |format|
if #order.update(order_params)
if user_signed_in?
format.html { redirect_to #order, notice: 'Order was successfully uploaded.' }
format.json { render :show, status: :ok, location: #order }
else
format.html { render :edit }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
if buyer_signed_in?
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { render :show, status: :ok, location: #order }
else
format.html { render :edit }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
end
Here is another attempt that somehow didn't function:
def order_cancel
respond_to do |format|
if #order.update(order_status)
format.html { redirect_to #order, notice: 'Order was successfully cancelled.' }
format.json { head :no_content }
end
end
end
private
def order_status
params.permit(:order_status)
end
How can I pin point the order_status values from the controller to allow me to have separate actions and notices when the values are changed by a end user?
Given that you use the Rails form builder to generate the form's HTML
<%= form_for #order, remote: true do |f| %>
<%= f.hidden_field :order_status, value: "cancelled" %>
I would expect that the generated name of the input field is nested under order. That said you will need to follow these nesting when permitting the params:
def order_status
params.require(:order).permit(:order_status)
end
When you are unsure how the parameters really look like you might want to have a look at the generated HTML structure of the form or you can look at the Rails logs for the update request to the application.
So, those three lines are wrong:
if #order.update(params[:order_update])
if user_signed_in?
if #order.order_status = "cancelled"
Should be:
if user_signed_in?
if #order.update(status: params[:order_status])
if #order.order_status == "cancelled"
But actually should be #order.update!(status: :cancelled) in a cancel action, or at least have a state machine to validate that the user is not messing up the states of the orders.
Or like is expected by your form, those should be in a update method (not cancel_update)
The update method you posted doesn't make sense, it has a minimum of 2 renders, I think you meant to not have the buyer_signed_in section.

Rails form with remote: true reloads the page

In my Rails 5.1 app i have 2 controllers: home_controller and posts_controller which i created with the scaffold tool, so what i'm doing is rendering the partial _form.html.haml in the index view of my home_controller.rb like this: (by the way i'm using haml)
.top-space
.row.center-xs
.col-xs-8.col-md-10
.row
.col-sm-3.col-lg-2.col-xs-10.top-space
%ul.no-bullets.text-left
%li=link_to "Explore", "#"
%li=link_to "Suggestions", "#"
.col-sm.col-xs-10
=render "posts/form"
#posts
i added remote: true to the form like this:
= form_for #post, remote: true do |f|
- if #post.errors.any?
#error_explanation
%h2= "#{pluralize(#post.errors.count, "error")} prohibited this post from being saved:"
%ul
- #post.errors.full_messages.each do |message|
%li= message
.mdl-textfield.mdl-js-textfield.full-width
= f.text_area :body, class:"mdl-textfield__input", row:3
= f.label :body, "Write something",class:"mdl-textfield__label"
.actions.text-right
= f.submit 'Save',class:"mdl-button mdl-js-button mdl-button--raised mdl-button--colored"
as you can see it has remote: true but when i submit the form it takes me to the show view in my posts_controller,
this is my posts_controller:
def create
#post = current_user.posts.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post}
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
i created a show.js.coffee to show the post created in a <div id="posts"> below the form
$('#posts').append('<%= j render #post %>')
Basically what i want is to show the post created below the form without reloading the page or taking me to show view in my posts_controller.
What am i doing wrong and how can i achieve this?
Try to set your create action like this maybe:
def create
#post = current_user.posts.new(post_params)
respond_to do |format|
if #post.save
format.js
format.html { redirect_to #post}
format.json { render :show, status: :created, location: #post }
else
format.js
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
i have just added format.js

Insert a data in another table

I have two tables, leagues and teams. I have no problem creating a league, but I am having a trouble creating a team in a particular league. When I create a team, it appears on all the leagues, I want to show it only on the league that I choose on my drop down box. This is my my drop down box (teams/form):
<select style="width: 193px" type="text">
<% #leagues.each do |league| %>
<option><%= league.league_name %></option>
<% end %>
</select>
And this is my def new (teams_controller):
def new
#team = Team.new
#leagues = League.all
end
And my def create (teams_controller):
def create
#team = Team.new(team_params)
respond_to do |format|
if #team.save
format.html { redirect_to #team, notice: 'Team was successfully created.' }
format.json { render :show, status: :created, location: #team }
else
format.html { render :new }
format.json { render json: #team.errors, status: :unprocessable_entity }
end
end
end
I think it has something to do with the def create, but I don't know what. Please help me. Thank you very much in advance.

Display form's message by remote method using ujs on Rails

I followed the episode http://railscasts.com/episodes/136-jquery-ajax-revised
and create my cusotm example.
I put the create form in the index, and create a book by remote method
But I have no idea how to put error message in the page.
please give me some example , thanks~
index
<%= render 'form' %>
<p>
<table id='books_tbl' class="table">
<th>id</th>
<th>title</th>
<th>ISBN</th>
<th>sn</th>
<th>price</th>
<th>Functions</th>
<div class="books" id="books">
<%= render #existed_books %>
</div>
</table>
the controller
# POST /books
# POST /books.json
def create
#book = Book.new(params[:book])
respond_to do |format|
if #book.save
format.html { redirect_to #book, notice: 'Book was successfully created.' }
format.json { render json: #book, status: :created, location: #book }
format.js
else
format.html { render action: "new" }
format.json { render json: #book.errors, status: :unprocessable_entity }
format.js
end
create.je.erb
<% unless #book.save %>
<% else %>
$('#books_tbl tr:last').after('<%= j render(#book) %>');
<% end %>
First, change your books_controller so that it will always render create.js.erb whether the book is persisted or not.
def create
#book = Book.new(params[:book])
respond_to do |format|
if #book.save
format.html { redirect_to #book, notice: 'Book was successfully created.' }
format.json { render json: #book, status: :created, location: #book }
else
format.html { render action: "new" }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
format.js
end
end
Then, in you create.js.erb, you will want to check whether your book is persited? or not:
<% if #book.persisted? %>
# ...
<% else %>
# display the error message
<% end %>
Let's say we are going to display the error message in a <p> with the .errors class:
$('<p>').text('<%= #book.errors.full_messages.to_sentence.capitalize %>')
.prepend('form');
The thing is that you will have to remove the errors paragraph every time you render create.js.erb so that former errors won't stick around:
$('p.errors').remove();
All in all, it gives:
$('p.errors').remove();
<% if #book.persisted? %>
# ...
<% else %>
$('<p>').text('<%= #book.errors.full_messages.to_sentence.capitalize %>')
.prepend('form')
<% end %>

Nested Routes in Rails 3.2.3

I am trying to create nested routes for a project that has many boards.
First I am creating a link to a new board:
<%= link_to 'New Board', new_project_board_path(#project) %>
In routes.rb I just nested the restful routes:
resources :projects do
resources :boards
end
And in the boards controller I adapted the new and create action as follows:
def new
#project = Project.find(params[:project_id])
#board = #project.boards.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #board }
end
end
def create
#project = Project.find(params[:project_id])
#board = #project.boards.new(params[:board])
respond_to do |format|
if #board.save
format.html { redirect_to #board, notice: 'Board was successfully created.' }
format.json { render json: #board, status: :created, location: #board }
else
format.html { render action: "new" }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end
At least I also changed the _form.html.erb into:
<%= form_for([#project, #board]) do |f| %>
etc.
My problem starts when I click the button create board (so the new action is executed) it says no route matches. I guess it has to do with the create action because it doesn't get the id of the project anymore? I really don't know what else to change and where.
Seems your error is here
format.html { redirect_to #board, notice: 'Board was successfully created.' }
You don't have non-nested :boards resources, do you? Try to change this line to
format.html { redirect_to [#project, #board], notice: 'Board was successfully created.' }

Resources