Add a join key to a group - ruby-on-rails

I'm creating an app to store game results between friends. In my app groups will be called Leagues.
To keep the leagues private I'd like to add a join key to it. When a league is created the creator chooses a join key. Later other users can join by choosing a league from a dropdown and filling in the exact join key. The user can only if the join key matches the selected league.
Controller:
def edit
#user = User.find(current_user.id)
#league_list = League.all.map{|l| [ l.league_name, l.id ] }
# #league_keys = League.all.map{|l| [ l.join_key, l.id ] }
end
def update
#user = User.find(current_user.id)
if #user.update(user_join_league_params) #&& #league_list.league_id == #league_keys.league_id
#user.save
redirect_to root_path, :notice => "Successfully joined this league!"
else
render 'index'
end
end
As you can see I have to edit the users league_id to complete the join.
View:
<div class="panel panel-default" style="margin-right:10px; margin-left:10px; text-align:center">
<div class="panel-heading">
JOIN A LEAGUE
</div>
<div class="panel-body">
<%= simple_form_for(#user) do |f| %>
<%= f.select(:league_id, #league_list) %><br> <br>
# <%= f.input_field :join_key %><br> <br>
<p>!! Watch out this cannot be changed after !!</p>
<br> <br> <%= f.submit "Join league", class: "btn-submit" %>
<% end %>
</div>
</div>
So I'd like this form to only perform the update action if the selected league matches the filled in key.
I've been looking for an answer in numerous posts on stackoverflow but I couldn't find a post with a simular issue.
How can I get this done?
EDIT:
Relations:
class User < ActiveRecord::Base
belongs_to :league
end
class League < ActiveRecord::Base
has_many :games
has_many :multiplayergames
has_many :users
end
SECOND EDIT:
So I've tried to implement the solloution.
I was using simple_form for <%= f.select(:league_id, #league_list) %>
I tried to do it like this:
<%= form_tag(user_path(#user), method: :put) do %>
<%= select_tag :league_id, options_for_select(#league_list) %><br> <br>
<p>Join Key</p>
<%= text_field_tag :join_key %><br> <br>
<p>!! Watch out this cannot be changed after !!</p>
<br> <br> <%= submit_tag "Join league", class: "btn-submit" %>
<% end %>
However this gives the error:
param is missing or the value is empty: user
THIRD EDIT:
Controller:
# JOIN A LEAGUE
def edit
#user = User.find(current_user.id)
#league_list = League.all.map{|l| [ l.league_name, l.id ] }
end
def update
#user = User.find(current_user.id)
#league = League.find_by_id(params[:league_id])
if #league.join_key == params[:join_key] && #user.update(user_join_league_params)
redirect_to root_path, :notice => "Successfully joined this league!"
else
redirect_to edit_user_path(current_user), notice: "Could not join league check if join key is correct!"
end
end
def user_join_league_params
params.permit!(:league_id,:join_key)
end
VIEW:
<%= form_tag(user_path(#user), method: :put) do %>
<%= select_tag :league_id, options_for_select(#league_list, :league_id) %><br> <br>
<p>Join Key</p>
<%= text_field_tag :join_key %><br> <br>
<p>!! Watch out this cannot be changed after !!</p>
<br> <br> <%= submit_tag "Join league", class: "btn-submit" %>
<% end %>

update action can look as follows:
def update
#user = User.find(current_user.id)
#league = League.find_by_id(params[:league_id])
if #league.join_key == params[:join_key] && #user.update(league_id: params[:league_id])
redirect_to root_path, :notice => "Successfully joined this league!"
else
render 'index'
end
end
form can look as follows:
<%= form_tag(user_path(#user), method: :put) do %>
<%= select_tag :league_id, options_for_select(#league_list) %><br> <br>
<%= text_field_tag :join_key %><br> <br>
<p>!! Watch out this cannot be changed after !!</p>
<br> <br> <%= submit_tag "Join league", class: "btn-submit" %>
<% end %>
Note: I have assumed join_key is an attribute in your League model.
Make sure you pass params accordingly in your user_join_league_params.
Edit:
Your should permit your params:
def user_join_league_params
params.permit!(:league_id,:join_key)
end

Related

Ruby on Rails: Populate dropdown with two fields of database record

In my database I have a Users table that looks something like:
User_ID Firstname Surname Company
1 Steve Jobs Apple
2 Bill Gates Microsoft
What I am trying to do is make a drop down menu in a form that would allow a user to choose from selecting their name or their company, e.g. when Steve Jobs is logged in he can either select "Steve" or "Apple" in the drop down menu.
What I have tried so far is the following:
<%= f.select :from_name, [session[:user_id],session[:user_id]] %>
Which obviously didn't work because it only returns the user id of the logged in user.
<%= f.select :from_name, [#user.firstname,#user.company] %>
Which gave me the error undefined methodfirstname for nil:NilClass`
My Users controller is as follows:
class UsersController < ApplicationController
before_filter :check_authorization, :except => [:show, :new, :create, :search ]
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def edit
#user = User.find(params[:id])
end
def create
#user = User.new(user_params)
#user.role = "customer"
if #user.save
session[:user_id] = #user.id
# Save a copy of the email address entered by the user into the Accounts table
#account = Account.create(email: params[:user][:primaryemailaddress], user_id: session[:user_id])
redirect_to root_path
else
render 'new'
end
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to #user
else
render 'edit'
end
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to users_path
end
private
def user_params
params.require(:user).permit(:title, :firstname, :surname, :housenumber, :street, :city, :postcode, :company, :primaryemailaddress, :password)
end
end
And my _form.html.erb is:
<%= form_for(#email) do |f| %>
<% if #email.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#email.errors.count, "error") %> prohibited this email from being saved:</h2>
<ul>
<% #email.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :from_name %><br>
<%= f.select :from_name, [current_user.firstname, current_user.company] %>
</p>
<p>
<%= f.label :From_Email_Address %><br>
<%= f.collection_select :account_id, Account.where(user_id: session[:user_id]),
:id,:email %>
</p>
<p>
<%= f.label :to %><br>
<%= f.text_field :to %>
</p>
<p>
<%= f.label :cc %><br>
<%= f.text_field :cc %>
</p>
<p>
<%= f.label :bcc %><br>
<%= f.text_field :bcc %>
</p>
<p>
<%= f.label :subject %><br>
<%= f.text_field :subject %>
</p>
<p>
<%= f.label :message %><br>
<%= f.text_field :message %>
</p>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I'm not too sure how to solve this issue, can someone please help.
#BenSmith I guess you are accessing EmailsController. And on that controller's new or edit method there is no #user variable.
In your edit and new method add
#user = User.find(session[:user_id])
undefined method firstname for nil:NilClass
Seems like some how #user is nil
create a helper and check for presence of #user
<%= f.select :from_name, dropdown_values %>
application_helper.rb
def dropdown_values
if #user.present?
[#user.firstname, #user.company]
else
['default', 'values']
end
end
<p>
<%= f.label :from_name %><br>
<%= f.select :from_name, [current_user.firstname, current_user.company] if #user.present?%>
</p>
because User.new time create blank object doesn't find username.i hope its will be help you.

Accessing Model ID inside of rails form helper

First off I'm new to rails, I have a join table Menus_orders which I'm trying to load ID's into on create.
I have this form helper which has access to Order.new(:id, :name) fields and fields_for Menus_order(:menu_id, :order_id). I can insert the menu_id from a select but I can't for the life of me figure out how to populate a hidden input with the current order_id which the form holds in #order.
look at ORDER_ID HERE
<div class="form">
<h1>Create a new order</h1>
<%= form_for #order do |f| %>
<%= f.label :name%><br>
<%= f.text_field :name%><br>
<h3>Select meals</h3>
<%= fields_for(#menus_order) do |i| %>
<div class="field">
<%= i.select :menu_id, options_for_select(Menu.all.pluck(:id)) %>
<%= i.hidden_field :order_id, :value => ORDER_ID HERE %>
</div>
<% end %>
<br>
<%= f.submit "Create"%><br>
<% end %>
</div>
Thanks, DW
You should use nested attributes for order model just apply
the conventions right & it will be handled, you can achieve this by
following example :
order.rb should be like :
class Order < ActiveRecord::Base
has_many :menu_orders
accepts_nested_attributes_for :menu_orders
end
menu_order.rb be like :
class MenuOrder < ActiveRecord::Base
belongs_to :order
end
orders/new.html
<div class="form">
<h1>Create a new order</h1>
<%= form_for #order do |f| %>
<%= f.label :name%><br>
<%= f.text_field :name%><br>
<h3>Select meals</h3>
<%= f.fields_for :menu_orders do |i| %>
<div class="field">
<%= i.select :menu_id, options_for_select(Menu.all.pluck(:id)) %>
</div>
<% end %>
<br>
<%= f.submit "Create"%><br>
<% end %>
</div>
OrdersController
class OrdersController < ApplicationController
def new
#order = Order.new
#order.menu_orders.build
end
def create
#order = Order.new(order_params)
if #order.save
redirect_to orders_path
flash[:success] = "Order created"
else
render 'new'
end
end
private
def order_params
params.require(:order).permit(:name, menu_orders_attributes: [ :menu_id, :order_id ])
end
end

How can I display an array of strings but selecting the index of the string in the array for form

Here is my problem.
I have a table for roles with two columns id and name.
The column id is linked through foreign key to the column role_id in the users table. The columns id and role_id are of type integer.
In the table roles I have these 4 records:
id name
-- ----
1 owner
2 doctor
3 receptionist
4 customer
For user I have a form to edit the privileges like admin and role_id.
I want to display values like the role names but when I click on the Submit button I want the id or role_id integer value to be used to update the customer.
The user_controller.rb file:
def show
#user = User.includes(:role).find(params[:id])
##role = #user.role
end
def edit
#user = User.includes(:role).find(params[:id])
end
def update
#user = User.includes(:role).find(params[:id])
if #user.update_attributes(user_params)
flash[:success] = "User Priviladges Updated"
#log_in #user
redirect_to #user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :role_id,
:password, :password_confirmation, :admin)
end
The edit.html.erb file:
<h1>Edit User Privileges</h1>
<strong><%= "Name: " %></strong><%=#user.name%>
<br>
<strong><%= "Email: " %></strong><%=#user.email%>
<br>
<strong><%= "Role: " %></strong><%=#user.role.name%>
<br>
<strong><%= "Role ID: " %></strong><%=#user.role_id%>
<%= form_for(#user) do |f| %>
<div class="field">
<%= f.check_box :admin %>
<%= f.label :admin %>
</div>
<div class="field">
<%= f.label :role_id %>
<%=f.select :role_id, options_for_select([1,2,3,4], f.object.role_id), :include_blank => false %>
</div>
<div class="actions">
<%= f.button 'Submit', class: "btn btn-sm btn-info" %>
</div>
<br>
<strong><%= link_to 'Back', :back %></strong>
<% end %>
The code works and values for role_id are updated correctly. However how I can display string in the drop down select list instead of numbers?
The solution I found is:
<%= f.select :role_id, options_from_collection_for_select(Role.order("id"), :id, :name, #user.try(:role_id)) %>

undefined method `reviews' for nil:NilClass

I'm trying to create a reviews model for company pages. For this I have:
Models
user.rb
has_many :reviews
class Review < ActiveRecord::Base
belongs_to :user
belongs_to :company
end
class Company < ActiveRecord::Base
has_many :reviews
end
My reviews controller is:
def create
#company = Company.find_by_slug(params[:id])
#review = #company.reviews.create(params[:review])
#review.save
redirect_to company_path(#company)
end
and I have this code in the company show page:
<% #company.reviews.each do |review| %>
<p>
<strong>Title:</strong>
<%= review.title %>
</p>
<p>
<strong>Avantage:</strong>
<%= review.avantage %>
</p>
<p>
<strong>Inconvenient:</strong>
<%= review.inconvenient %>
</p>
<% end %>
</br>
<%= form_for([#company, #company.reviews.build]) do |f| %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :avantage %><br>
<%= f.text_area :avantage %>
</div>
<div class="field">
<%= f.label :inconvenient %><br>
<%= f.text_area :inconvenient %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
However, when I go to a specific company page and try to create a review for this company I'm getting this error message undefined method reviewsfor nil:NilClass
Instead of #company = Company.find_by_slug(params[:id]) use this code #company = Company.friendly.find(params[:company_id])
There are a couple of things you may find useful:
If you're using Rails 4, you may encounter a further problem. In the third line of your create method, you are using unsecure params directly in a .create call. Check out the Rails Guide page on "strong params".
If you implement strong parameters as mentioned above, you should probably deliberately omit the company_id field from the list of permitted params.
Assuming your users are allowed to write a review for any company in your system, it might be simpler for you to embed the company_id as a hidden field in your form. This would allow you to also simplify the controller method. For example:
# _form.html.erb
<%= form_for(#review) do |f| %>
<%= f.hidden_field :company_id, value: #company.id %>
...bla bla bla
<% end %>
Then, in your reviews_controller...
# reviews_controller.rb
def create
#review = Review.new(approved_params)
if #review.save
flash[:success] = 'Review created!'
else
flash[:error] = "Review wasn't saved"
end
#company = #review.company
redirect_to #company
end
def approved_params
params.require(:review).permit(:title, :avantage, :inconvenient, :company_id)
end
In your companies_controller, you should add this to your show method
# companies_controller.rb
def show
#company = Company.find(params[:id]
# add this line below...
#review = Review.new
end
I hope this helps.

Form_for helper

I have 2 models that are associated with each other via a join table:
class Book < ActiveRecord::Base
has_many :reviews
end
class Reader < ActiveRecord::Base
has_many :reviews
end
class Reviews < ActiveRecord::Base
belongs_to :reader
belongs_to :book
end
Right now, I am able to update a review (which I created manually in the console) on route:
readers/:id/books
The above route was create using rails' member method:
resources :readers
member do
get 'books'
end
end
The update action in reviews controller (reviews#update) is defined like so:
def update
#reader = current_reader
#review = Review.find_by_reader_id(#reader.id)
#book = Book.find(params[:review][:book]
if #reader.books.include?(#book)
#review.update_attributes(review_params)
redirect_to (#reader)
else
flash[:error] = 'You can only edit reviews that belong to you'
end
end
My form_for reviews (reviews#update) looks like this:
Reader Reviews:
<% book.reviews.each do |review| %>
<% if current_reader == (review.reader) %>
<%= review.content %> written by <%= review.reader.name %>
<% if current_reader.reviews.include?(review) %>
<%= form_for ([book, review]) do |f| %>
<div class="field">
<%= f.hidden_field :book, :value => book.id %>
<%= f.text_area :content, placeholder: "compose new review" %>
</div>
<%= f.submit "Update", class: "btn btn-large btn-primary" %>
<% else %>
<%= form_for ([book, review]) do |f| %>
<div class="field">
<%= f.hidden_field :book, :value => book.id %>
<%= f.text_area :content, placeholder: "compose new review" %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
<% end %>
<% end %>
The above works for update. But the 2nd form doesn't.
My intent is to check for a review => if there is one - display a form so that reader can update review; if there isn't one then display a form so that reader can create a review. I have a private method in reviews controller that checks to make sure that a reader has a book before either action is carried out (a before_action method I guess).
The first form works well (the update form) but the second does not - the form is not displayed at all. I have tried various things to get the form to display but no luck. Can you please me determine the best way to resolve this issue?
Thank you very much!
There could be several issues:
elsif
The likely reason your other form won't show will be that your elsif logic won't be correct
I had a look at the .include? Ruby function, and it seems to just be for arrays. Why not try using .exists? instead?
<% elseif !current_reader.reviews.exists?(review) %>
You may have to use review.id or similar to get the correct response. Failing that, why don't you just use <% else %>?
form_for
The second issue may be with your second form_for
<%= form_for [:book, review] do |f| %>
You're currently passing a local variable called book to the form_for builder. Although this is probably correct (I can't find your reference to creating book), I've found it best to put a symbol in the nested form (to show Rails which data it needs to use)
Could you try using else instead of elsif !current_reader.reviews.include?(review)?
Also, it's elsif and not elseif. The problem should not because of this - The page would not have loaded in the first place if this is the case.
UPDATE
I fixed my first error by updating my forms:
Reader Reviews:
<% book.reviews.where(reader_id: current_reader.id).each do |review| %>
<li>
<span><%= review.content %> writen by <%= review.reader.name %> </span
<%= form_for ([book, review]) do |f| %>
<div class="field">
<%= f.hidden_field :book, :value => book.id %>
<%= f.text_area :content, placeholder: "compose new review" %>
</div>
<%= f.submit "Update", class: "btn btn-large btn-primary" %>
<% end %>
</li>
<% if book.reviews.where(reader_id: current_reader.id).size == 0 %>
<%= form_for ([book, book.reviews.build]) do |f| %>
<div class="field">
<%= f.hidden_field :book, :value => book.id %>
<%= f.text_area :content, placeholder: "compose new review" %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
<% end %>
<% end %>
This displays the forms (both post and update). BUT I got this error when I tried to post a new review:
(rdb:35) #review
#<Review id: nil, reader_id: 101, content: "Trial", created_at: nil, updated_at: nil, book_id: nil>
(rdb:35) review_params
Unpermitted parameters: book
{"content"=>"Trial"}
(rdb:35)
So I changed my create action for review to make sure book_id isn't nill:
def create
#reader = current_reader
# #book = Book.find(params[:book_id])
#book = Book.find(params[:review][:book])
if #reader.reviews.where(book_id: #book.id).exists?
flash[:error] = "You already reviewed this book"
else
#review = current_reader.reviews.create(:book_id => params[:book_id.to_i, :content => review_params[:content])
debugger
if #review.save
flash[:success] = "Review created"
redirect_to reader_path(#reader)
else
flash[:error] = "You can only review books that are in your library"
redirect_to reader_path(#reader)
end
end
end
Also changed how I defined review_params:
def review_params
params.require(:review).permit(:content, :book_id)
end
All this changes gave the desired results. My code isn't dry AT ALL but the most important thing to me at this point is getting things to work. Here is to hoping I don't break it again. Thanks for your help #RichPeck

Resources