I have a model association between two models Listing & Pricing. These are associated through Listing_Pricings model on a many to many basis.
If a listing is created the user can select through a check box field one of three pricing options which I intend to have saved in a seperate model Listing_Pricings. When a user selects the pricing option I can see it in the params hash but it fails to save in my database model.
Help please
My controller
class ListingsController < ApplicationController
protect_from_forgery except: [:upload_photo]
before_action :authenticate_user!, except: [:show]
before_action :set_listing, except: [:new, :create]
before_action :set_step, only: [:update, :edit]
before_action :is_authorised, only: [:edit, :update, :upload_photo, :delete_photo]
before_action :set_category, only: [:new, :edit, :show]
def new
#listing = current_user.listings.new
#listing.listing_pricings
#urgencies = Urgency.all
end
def create
#listing = current_user.listings.new listing_params
#listing.listing_pricings.first.listing_id = current_listing.id
if #listing.save
redirect_to edit_listing_path(#listing), notice: "Save..."
else
redirect_to request.referrer, flash: { error: #listing.errors.full_messages}
end
end
def edit
#urgencies = Urgency.all
#listing = Listing.find(params[:id])
#listing_category = #listing.category
#category_pricings = #listing_category.pricings.all
#listing_price = #listing.listing_pricings
end
def update
#listing = Listing.find(params[:id])
#listing_category = #listing.category
##category_pricings = #listing_category.pricings.all
##category = Category.find(params[:id])
#category_pricings = #listing_category.pricings.paginate(page: params[:page], per_page: 5)
#listing_pricing = #listing.listing_pricings
##listing_price = #listing_pricing.first.pricing
#listing_price = #listing.listing_pricings.build
#urgencies = Urgency.all
if #step == 2 && #listing.listing_pricings.each do |pricing|
if #listing.has_single_pricing && !pricing.bronze?
next;
else
if pricing[:listing_id].blank?
#|| pricing[:description].blank? || pricing[:complete_by_date].blank? || pricing[:price].blank?
return redirect_to request.referrer, flash: {error: "Invalid Pricing"}
end
end
end
end
if #step == 3 && listing_params[:description].blank?
return redirect_to request.referrer, flash: {error: "Description cannot be blank"}
end
if #step == 4 && #listing.photos.blank?
return redirect_to request.referrer, flash: {error: "You don't have any photos"}
end
if #step == 5
#listing_category_pricings.each do |pricing|
if #listing.has_single_pricing || !pricing.bronze? || !pricing.silver? || !pricing.gold? || !pricing.platinum?
next;
else
if pricing[:overview].blank? || pricing[:description].blank? || pricing[:complete_by_date].blank? || pricing[:price].blank?
return redirect_to edit_listing_path(#listing, step: 2), flash: {error: "Invalid pricing"}
end
end
end
if #listing.description.blank?
return redirect_to edit_listing_path(#listing, step: 3), flash: {error: "Description cannot be blank"}
elsif #listing.photos.blank?
return redirect_to edit_listing_path(#listing, step: 4), flash: {error: "You don't have any photos"}
end
end
if #listing.update(listing_params)
flash[:notice] = "Saved..."
else
return redirect_to request.referrer, flash: {error: #listing.errors.full_messages}
end
if #step < 5
redirect_to edit_listing_path(#listing, step: #step + 1)
else
redirect_to users_dashboard_path
end
end
def show
#listing = Listing.find(params[:id])
#listing_category = #listing.category
#listing_category_pricings = #listing_category.pricings.all
#urgencies = Urgency.all
end
def upload_photo
#listing.photos.attach(params[:file])
render json: { success: true}
end
def delete_photo
#image = ActiveStorage::Attachment.find(params[:photo_id])
#image.purge
redirect_to edit_listing_path(#listing, step: 4)
end
def set_pricing_id
Listing.update_all({pricing_id: true}, {id: params[:listing_id]} )
end
private
def set_step
#step = params[:step].to_i > 0 ? params[:step].to_i : 1
if #step > 5
#step = 5
end
end
def set_category
#categories = Category.all
end
def set_listing
#listing = Listing.find(params[:id])
end
def is_authorised
redirect_to root_path, alert: "You do not have permission" unless current_user.id == #listing.user_id
end
def listing_params
params.require(:listing).permit(:title, :video, :description, :active, :category_id, :budget, :urgency_id, :has_single_pricing,:pricing_id)
end
def category_params
params.require(:category).permit(:name)
end
end
Listing.rb
class Listing < ApplicationRecord
belongs_to :user
belongs_to :category
belongs_to :urgency
has_many :listing_pricings, dependent: :destroy
has_many :pricings, through: :listing_pricings
has_many_attached :photos
has_rich_text :description
validates :title, presence: { message: 'cannot be blank' }
#has_many :pricings
#accepts_nested_attributes_for :pricings
#has_many :listing_categories
end
Pricings.rb
class Pricing < ApplicationRecord
belongs_to :category, optional: false
has_many :listing_pricings
has_many :listings, through: :listing_pricings
enum pricing_type: [:bronze, :silver, :gold, :platinum]
end
ListingPricing.rb
class ListingPricing < ApplicationRecord
belongs_to :listing, optional: true, dependent: :destroy
belongs_to :pricing, optional: true, dependent: :destroy
end
My View
<div class="step-content <%= 'is-active' if #step == 2 %>">
<div class="field">
<div class="control">
<div class="tile is-ancestor">
<% #category_pricings.each do |cp| %>
<div class="tile is-parent">
<article class="tile is-child box">
<div class="subtitle"><%= "#{cp.overview}" %></div>
<div class="content"><%= "Deposit payable: £#{cp.price}" %></div>
<div class="content"><%= "Time to complete: #{pluralize(cp.complete_by_date, 'Day')}" %></div>
<tr valign="bottom"><div class="content"><%= "#{cp.description}" %></div></tr>
<tr valign="bottom"><div class="content"><%= "#{cp.id}" %></div></tr>
<%= f.fields_for :listing_pricings do |lp| %>
<%= hidden_field_tag "pricing_id[]", cp.id %>
<div class="form-group">
<%= lp.check_box_tag :pricing_id, cp.id %>
</div>
<% end %>
</article>
</div>
<% end %>
</div>
</div>
</div>
</div>
My error trace says
PG::NotNullViolation: ERROR: null value in column "pricing_id" violates not-null constraint DETAIL: Failing row contains (16, 2, null, 2019-12-13 17:51:50.722906, 2019-12-13 17:51:50.722906).
Any thoughts guys ?
Parameters:
{"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"tOnX6Q5YjHgXn3Xk5Wh2NioPfLrziiPVwyHkLF8BBFOjuWHdM1w8A7AdGpHdFGR3n+zlFsN2B/3IOMenXU1daA==",
"step"=>"2",
"listing"=>{"title"=>"Please clean my home", "category_id"=>"3", "urgency_id"=>"10", "has_single_pricing"=>"0", "description"=>"<div>This is my second listing </div>", "video"=>""},
"pricing_id"=>"1",
"commit"=>"Save & Continue",
"id"=>"2"}
I do this for one of my project. I replace my models with Pricing, Listing and ListPricing for you.
In your model, you have to have dependent: :destroy on has_many ... through relationship (otherwise, unchecking checkbox will not work).
# app/model/listing.rb
class Listing < ApplicationRecord
has_many :listing_pricings
has_many :pricings, through: :listing_pricings, dependent: :destroy
# your code
end
In your view,
- Pricing.all.each do |p|
= f.check_box :pricing_ids, { multiple: true }, p.id, false
= f.label :pricing_id, p.something
end
In listing controller, make sure you permit :pricing_ids in listing controller
# app/controllers/listings_controller.rb
def listing_param
params.require(:listing).permit(
# other params you permit,
pricing_ids: []
)
end
Related
I am trying simple_form nested attributes as suggested in https://github.com/plataformatec/simple_form/wiki/Nested-Models
The thing is, when I render the form I just can see the submit button, but not the input field. What am I doing wrong?
_form.html.erb
<%= simple_form_for [:admin, #incident] do |f| %>
<%= f.error_notification %>
<%= f.simple_fields_for :comments do |builder| %>
<%= builder.input :info, label: "Informe de seguimiento" %>
<% end %>
<div class="form-actions">
<%= f.submit "Enviar", class: "btn btn-primary" %>
</div>
<% end %>
incidents_controller.rb
class Admin::IncidentsController < ApplicationController
before_action :set_incident, only: [:show, :edit, :update]
def index
#incidents = Incident.all
end
def show
end
def new
#incident = Incident.new
#incident.comments.build
end
def edit
end
def update
respond_to do |format|
if #incident.update(incident_params)
format.html { redirect_to #incident, notice: 'Incidencia actualizada actualizada con éxito.' }
format.json { render :show, status: :ok, location: #incident }
else
format.html { render :edit }
format.json { render json: #incident.errors, status: :unprocessable_entity }
end
end
end
private
def set_incident
#incident = Incident.find(params[:id])
end
def incident_params
params.require(:incident).permit(:info, :subject, :status, comments_attributes: [:info])
end
end
incident.rb
class Incident < ApplicationRecord
belongs_to :user, optional: true
has_many :comments, dependent: :destroy
accepts_nested_attributes_for :comments, allow_destroy: true, reject_if: proc { |attributes| attributes['info'].blank? }
enum status: [:abierto, :tramite, :pendiente, :cerrado]
after_initialize :set_default_status, :if => :new_record?
def set_default_status
self.status ||= :abierto
end
end
comment.rb
class Comment < ApplicationRecord
belongs_to :user, optional: true
belongs_to :incident
end
You need to add #incident.comments.build to the show action of Admin::IncidentsController. Now it has no comments, I suppose, so the form is empty.
And you need to add :id to comments_attributes, without it comment can't be saved. If you planning to have some 'Delete' checkbox for existing comments you also need to add :_destroy to the attributes array
I am trying to create a nested attribute form for my Request model.
My parameters are not saving correctly when the Create action is triggered. Though in my console, the data is structured correctly for how I want it to be entered.
The :quantity attribute is on the JoinTable model of RequestDrink.
How can I white-list these parameters correctly?
Console Output
Started POST "/requests" for 127.0.0.1 at 2017-06-08 12:38:40 -0400
Processing by RequestsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"3ljcH44E7ZrEXNztlgGacyA0nyumNsTX6NyMMu9N+3SY0rCRXSsj/hsg0JP8jtVfDFkcEWOWHi/VwHrgertlLg==", "request"=>{"concierge_name"=>"Alex", "concierge_number"=>"954-123-4567", "concierge_email"=>"alex#email.com", "client_name"=>"Adam", "client_number"=>"954-765-4321", "client_email"=>"adam#email.com", "hotel_employee"=>"0", "concierge_service"=>"0", "vip_promoter"=>"0", "arriving_with_client"=>"1", "client_alone"=>"0", "males"=>"", "females"=>"1", "table_minimum"=>"1000", "event_date_id"=>"1", "arrival_time(1i)"=>"2017", "arrival_time(2i)"=>"6", "arrival_time(3i)"=>"8", "arrival_time(4i)"=>"16", "arrival_time(5i)"=>"38", "drinks_attributes"=>[{"id"=>"1", "quantity"=>"1"}, {"id"=>"2", "quantity"=>""}, {"id"=>"3", "quantity"=>""}, {"id"=>"4", "quantity"=>""}], "commit"=>"Submit"}
Completed 404 Not Found in 18ms (ActiveRecord: 0.0ms)
ActiveRecord::RecordNotFound (Couldn't find Drink with ID=1 for Request with ID=):
app/controllers/requests_controller.rb:34:in `create'
app/models/request.rb
class Request < ApplicationRecord
has_many :request_drinks
has_many :drinks, through: :request_drinks
accepts_nested_attributes_for :drinks
end
app/models/drinks.rb
class Drink < ApplicationRecord
has_many :request_drinks
has_many :requests, through: :request_drinks
end
app/models/request_drink.rb
class RequestDrink < ApplicationRecord
belongs_to :request
belongs_to :drink
end
app/controllers/request_controller.rb
class RequestsController < ApplicationController
before_action :set_request, only: [:show,
:edit,
:update,
:destroy]
def index
redirect_to root_path unless admin_signed_in?
#requests = Request.search(params[:term], params[:filter], params[:page])
end
def show
end
def new
#request = Request.new
#drinks = Drink.active
#chasers = Chaser.active
#table_locations = TableLocation.active
#event_dates = EventDate.active
end
def edit
end
def create
#request = Request.new(request_params)
#request.people = (#request.males || 0) + (#request.females || 0)
#drinks = Drink.active
#chasers = Chaser.active
#table_locations = TableLocation.active
#event_dates = EventDate.active
respond_to do |format|
if #request.save
format.html { redirect_to thanks_path, notice: 'Request was successfully created.' }
format.json { render :show, status: :created, location: #request }
else
format.html { render :new }
format.json { render json: #request.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #request.update(request_params)
format.html { redirect_to #request, notice: 'Request was successfully updated.' }
format.json { render :show, status: :ok, location: #request }
else
format.html { render :edit }
format.json { render json: #request.errors, status: :unprocessable_entity }
end
end
end
def destroy
#request.destroy
respond_to do |format|
format.html { redirect_to requests_url, notice: 'Request was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_request
#request = Request.find(params[:id])
end
def request_params
params.require(:request).permit(:concierge_name,
:concierge_number,
:concierge_email,
:client_name,
:client_number,
:client_email,
:hotel_employee,
:concierge_service,
:vip_promoter,
:arriving_with_client,
:client_alone,
:people,
:males,
:females,
:table_minimum,
:arrival_time,
:comments,
:event_date_id,
:drinks_attributes => [:id, :quantity]
)
end
end
app/views/requests/_form.html.erb
<%= form_with(model: request, local: true) do |f| %>
...
<h4>Drinks</h4>
<% #drinks.all.each do |d| %>
<%= hidden_field_tag "request[drinks_attributes][][id]", d.id %>
<%= number_field_tag "request[drinks_attributes][][quantity]", 0, in: 0..10 %>
<%= d.name %>
<br />
<% end %>
...
<% end %>
The :quantity attribute is on the JoinTable model of RequestDrink.
Yet your are using drinks instead of request_drinks. Try changing your code to use the latter:
Model:
class Request < ApplicationRecord
has_many :request_drinks
has_many :drinks, through: :request_drinks
accepts_nested_attributes_for :request_drinks
end
View:
...
<%= hidden_field_tag "request[request_drinks_attributes][][id]", d.id %>
<%= number_field_tag "request[request_drinks_attributes][][quantity]", 0, in: 0..10 %>
...
Controller:
class RequestsController < ApplicationController
# other actions
def request_params
params.require(:request).permit(..., :request_drinks_attributes => [:id, :quantity])
end
end
Thank you, this worked as well as tweaking my parameters a little more. This is the completed code
app/models/request.rb
class Request < ApplicationRecord
has_many :request_drinks
has_many :drinks, through: :requests
accepts_nested_attributes_for :request_drinks
end
app/controllers/request_controller.rb
class RequestController < ApplicationRecord
...
def request_params
params.require(:request).permit(:concierge_name,
:concierge_number,
:concierge_email,
:client_name,
:client_number,
:client_email,
:hotel_employee,
:concierge_service,
:vip_promoter,
:arriving_with_client,
:client_alone,
:people,
:males,
:females,
:table_minimum,
:arrival_time,
:comments,
:is_deleted,
:approved,
:attended,
:event_date_id,
:request_drinks_attributes => [:request_id, :drink_id, :quantity]
:table_location_ids => []
)
end
end
app/views/requests/_form.html.erb
...
<h4>Drinks</h4>
<% #drinks.all.each do |d| %>
<%= hidden_field_tag "request[request_drinks_attributes][][request_id]", request.id %>
<%= hidden_field_tag "request[request_drinks_attributes][][drink_id]", d.id %>
<%= number_field_tag "request[request_drinks_attributes][][quantity]", 0, in: 0..10 %>
<%= d.name %>
<br />
<% end %>
So I am working on an assignment at the moment, where I am trying to display favorited posts. I currently have the favorited post displayed, but when I click it, it doesn't doesn't redirect me to anywhere.
Here is the code I currently have:
User#show where I am currently trying to display the favorited posts:
<div class="row">
<div class="col-md-8">
<div class="media">
<br />
<% avatar_url = #user.avatar_url(128) %>
<% if avatar_url %>
<div class="media-left">
<%= image_tag avatar_url, class: 'media-object' %>
</div>
<% end %>
<div class="media-body">
<h2 class="media-heading"><%= #user.name %></h2>
<small>
<%= pluralize(#user.posts.count, 'post') %>,
<%= pluralize(#user.comments.count, 'comment') %>
</small>
</div>
</div>
</div>
</div>
<h2>Posts</h2>
<%= posts_exists? %>
<%= render #user.posts %>
<h2>Comments</h2>
<%= comments_exists? %>
<%= render #user.comments %>
<h2>Favorites</h2>
<% #posts.each do |post| %>
<%= render partial: 'votes/voter', locals: { post: post } %>
<%= link_to post.title, topic_post_path(#topic, post) %>
<%= image_tag current_user.avatar_url(48), class: "gravatar" %>
<%= post.comments.count %> Comments
<% end %>
The error is occuring on the following line:
<%= link_to post.title, topic_post_path(#topic, post) %>
Here is the output from the error:
ActionView::Template::Error (No route matches {:action=>"show", :controller=>"posts", :id=>"54", :topic_id=>nil} missing required keys: [:topic_id]):
29: <h2>Favorites</h2>
30: <% #posts.each do |post| %>
31: <%= render partial: 'votes/voter', locals: { post: post } %>
32: <%= link_to post.title, topic_post_path(#topic, post) %>
33: <%= image_tag current_user.avatar_url(48), class: "gravatar" %>
34: <%= post.comments.count %> Comments
35: <% end %>
app/views/users/show.html.erb:32:in `block in _app_views_users_show_html_erb__1919900632491741904_70127642538380'
app/views/users/show.html.erb:30:in `_app_views_users_show_html_erb__1919900632491741904_70127642538380'
Obviously Topid.id is nil, but I can't figure out why. I'm going to provide you with everything I think you could need? I know this is probably a simple nooby issue, but I've been stuck on it for nearly an entire day already.
Here is my User#Controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new
#user.name = params[:user][:name]
#user.email = params[:user][:email]
#user.password = params[:user][:password]
#user.password_confirmation = params[:user][:password_confirmation]
if #user.save
flash[:notice] = "Welcome to Bloccit #{#user.name}!"
create_session(#user)
redirect_to root_path
else
flash[:error] = "There was an error creating your account. Please try again."
render :new
end
end
def show
#user = User.find(params[:id])
#posts = #user.posts.visible_to(current_user)
#posts = Post.joins(:favorites).where('favorites.user_id = ?', #user.id)
#favorites = current_user.favorites
end
end
Here is my Post#Controller:
class PostsController < ApplicationController
before_action :require_sign_in, except: :show
before_action :authorize_user, except: [:show, :new, :create]
def show
#post = Post.find(params[:id])
end
def new
#topic = Topic.find(params[:topic_id])
#post = Post.new
end
def create
#topic = Topic.find(params[:topic_id])
#post = #topic.posts.build(post_params)
#post.user = current_user
if #post.save
#post.labels = Label.update_labels(params[:post][:labels])
flash[:notice] = "Post was saved."
redirect_to [#topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :new
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
#post.assign_attributes(post_params)
if #post.save
#post.labels = Label.update_labels(params[:post][:labels])
flash[:notice] = "Post was updated."
redirect_to [#post.topic, #post]
else
flash[:error] = "There was an error saving the post. Please try again."
render :edit
end
end
def destroy
#post = Post.find(params[:id])
if #post.destroy
flash[:notice] = "\"#{#post.title}\" was deleted successfully."
redirect_to #post.topic
else
flash[:error] = "There was an error deleting the post."
render :show
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end
def authorize_user
post = Post.find(params[:id])
unless current_user == post.user || current_user.admin?
flash[:error] = "You must be an admin to do that."
redirect_to [post.topic, post]
end
end
end
Here is my Topics#Controller:
class TopicsController < ApplicationController
before_action :require_sign_in, except: [:index, :show]
before_action :authorize_user, except: [:index, :show]
def index
#topics = Topic.all
end
def show
#topic = Topic.find(params[:id])
end
def new
#topic = Topic.new
end
def create
#topic = Topic.new(topic_params)
if #topic.save
#topic.labels = Label.update_labels(params[:topic][:labels])
redirect_to #topic, notice: "Topic was saved successfully."
else
flash[:error] = "Error creating topic. Please try again."
render :new
end
end
def edit
#topic = Topic.find(params[:id])
end
def update
#topic = Topic.find(params[:id])
#topic.assign_attributes(topic_params)
if #topic.save
#topic.labels = Label.update_labels(params[:topic][:labels])
flash[:notice] = "Topic was updated."
redirect_to #topic
else
flash[:error] = "Error saving topic. Please try again."
render :edit
end
end
def destroy
#topic = Topic.find(params[:id])
if #topic.destroy
flash[:notice] = "\"#{#topic.name}\" was deleted successfully."
redirect_to action: :index
else
flash[:error] = "There was an error deleting the topic."
render :show
end
end
private
def topic_params
params.require(:topic).permit(:name, :description, :public)
end
def authorize_user
unless current_user.admin?
flash[:error] = "You must be an admin to do that."
redirect_to topics_path
end
end
end
Here is my User Model:
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
has_many :comments, dependent: :destroy
has_many :votes, dependent: :destroy
has_many :favorites, dependent: :destroy
before_save { self.email = email.downcase }
before_save { self.role ||= :member }
EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :name, length: { minimum: 1, maximum: 100 }, presence: true
validates :password, presence: true, length: { minimum: 6 }, if: "password_digest.nil?"
validates :password, length: { minimum: 6 }, allow_blank: true
validates :email,
presence: true,
uniqueness: { case_sensitive: false },
length: { minimum: 3, maximum: 100 },
format: { with: EMAIL_REGEX }
has_secure_password
enum role: [:member, :admin]
def favorite_for(post)
favorites.where(post_id: post.id).first
end
def avatar_url(size)
gravatar_id = Digest::MD5::hexdigest(self.email).downcase
"http://gravatar.com/avatar/#{gravatar_id}.png?s=#{size}"
end
end
Here is my Topic Model:
class Topic < ActiveRecord::Base
has_many :posts, dependent: :destroy
has_many :labelings, as: :labelable
has_many :labels, through: :labelings
end
Here is my Post Model:
class Post < ActiveRecord::Base
belongs_to :topic
belongs_to :user
has_many :comments, dependent: :destroy
has_many :votes, dependent: :destroy
has_many :labelings, as: :labelable
has_many :labels, through: :labelings
has_many :favorites, dependent: :destroy
default_scope { order('rank DESC') }
scope :visible_to, -> (user) { user ? all : joins(:topic).where('topics.public' => true) }
validates :title, length: { minimum: 5 }, presence: true
validates :body, length: { minimum: 20 }, presence: true
validates :topic, presence: true
validates :user, presence: true
def up_votes
votes.where(value: 1).count
end
def down_votes
votes.where(value: -1).count
end
def points
votes.sum(:value)
end
def update_rank
age_in_days = (created_at - Time.new(1970,1,1)) / 1.day.seconds
new_rank = points + age_in_days
update_attribute(:rank, new_rank)
end
end
Any insight anyone could provide, I would be extremely grateful for. If you have the time to explain where I went wrong as well, that would be even more helpful.
User#show where I am currently trying to display the favorited posts
But you're not setting #topic in your User#show action. That's why it's nil.
def show
#user = User.find(params[:id])
#posts = #user.posts.visible_to(current_user)
#posts = Post.joins(:favorites).where('favorites.user_id = ?', #user.id)
#favorites = current_user.favorites
# your #topic object is not in here?
end
Since a post belongs_to a topic you could do something like this:
<%= link_to post.title, topic_post_path(post.topic, post) %>
So I know where the problem is, but I'm fairly new to ROR and don't know how to work out what methods are available/which variables I should be using.
What I'm trying to do:
a user should be directed to views/relationship/edit when they press 'edit relationship'.
the variables should correspond so the edit relationship page deals with an accepted, pending or requested relationship between the current_user and the person they're trying to connect to (followed)
if a relationship exists in any state, show the edit button. (works)
click edit button (this is where the error comes up)
show edit page for the relationship between current user and person theyre trying to connect to. (where can accept/delete request)
i don't know why it's saying there is no decorator method - it was working before..
error:
NoMethodError in RelationshipsController#edit
undefined method `decorate' for nil:NilClass
Extracted source (around line #71):
# #relationship = current_user.active_relationships.find(params[:id]).decorate
#followed = User.find_by(name: params[:id])
#relationship = current_user.pending_relationships.find_by(followed_id: #followed).decorate
end
view/users/index:
<% if logged_in? %>
<ul>
<% #users.each do |user| %>
<li>
<%= user.name %>
<div id="relationship-status">
<% if current_user.following.include?(#followed) || current_user.pending_following.include?(user) || current_user.requested_following.include?(user) %>
<%= link_to "Edit Relationship", edit_relationship_path(followed_id: #followed, id: current_user.id), class: "btn btn-primary" %>
followed: <%= #followed %>
current_user: <%= current_user.id %>
relationship: <%= #relationship %>
<% else %>
<%= link_to "Add Relationship", new_relationship_path(follower_id: user.id), class: "btn btn-primary", id: 'add-relationship', data: { followed_id: user.id.to_param } %>
<% end %>
</div>
</li>
<% end %>
</ul>
<% end %>
relationships_controller:
def edit
# #followed = #relationship.followed
# #relationship = current_user.active_relationships.find(params[:id]).decorate
#followed = User.find(name: params[:id])
#relationship = current_user.pending_relationships.find_by(followed_id: #followed).decorate
end
views/relationship/edit:
<div class="page-header">
<h1>Viewing Relationship</h1>
</div>
<h3><%= #relationship.sub_message %></h3>
<div class="form-actions">
<% if #relationship.requested? %>
<%= form_for #relationship, url: accept_relationship_path(#relationship), method: :put do |form| %>
<%= submit_tag "Accept Relationship", class: 'btn btn-primary' %>
<% end %>
<% end %>
</div>
<%= form_for #relationship, url: relationship_path(#relationship), method: :delete do |form| %>
<%= submit_tag "Delete Relationship", class: 'btn btn-danger' %>
<% end %>
model/user:
class User < ActiveRecord::Base
has_one :profile, dependent: :destroy
has_many :pending_relationships, class_name: "Relationship",
foreign_key: "follower_id"
has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
dependent: :destroy
has_many :following, -> { where(relationships: { state: "accepted" } ) }, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower
has_many :pending_following, -> { where(relationships: { state: "pending" } ) }, through: :pending_relationships, source: :followed
has_many :requested_following, -> { where(relationships: { state: "requested" } ) }, through: :pending_relationships, source: :followed
...
# Follows a user.
def follow(other_user)
active_relationships.create(followed_id: other_user.id)
end
# Unfollow a user.
def unfollow(other_user)
active_relationships.find_by(followed_id: other_user.id).destroy
end
# Return true if the current user is following the other user.
def following?(other_user)
following.include?(other_user)
end
def pending_following?(user)
pending_following.include?(user)
end
def requested_following?(user)
pending_following.include?(user)
end
user db table:
relationship controller:
class RelationshipsController < ApplicationController
before_action :logged_in_user, only: [:new, :create, :index, :accept, :edit, :destroy]
respond_to :html, :json
def new
if params[:followed_id]
#followed = User.find(params[:followed_id])
#active_relationship = current_user.active_relationships.new(followed: #followed)
else
flash[:danger] = "Relationship required"
end
rescue ActiveRecord::RecordNotFound
render 'public/404', status: :not_found
end
def create
if params[:relationship] && params[:relationship].has_key?(:followed_id)
#followed = User.find(params[:relationship][:followed_id])
# #followed = User.where(name: params[:relationship][:followed_id]).first
#relationship = Relationship.request(current_user, #followed)
respond_to do |format|
if #relationship.new_record?
format.html do
flash[:danger] = "There was a problem creating that relationship request"
redirect_to followed_path(#followed)
end
format.json { render json: #relationship.to_json, status: :precondition_failed }
else
format.html do
flash[:success] = "Friend request sent"
redirect_to followed_path(#followed)
end
format.json { render json: #relationship.to_json }
end
end
else
flash[:danger] = "Friend Required"
redirect_to users_path
end
end
# def create
# if params[:followed_id]
# #followed = User.find(params[:followed_id])
# current_user.follow(#followed)
# redirect_to user
# else
# flash[:danger] = "else statement"
# end
# end
def accept
#relationship = current_user.active_relationships.find(params[:id])
if #relationship.accept!
flash[:success] = "You are now connected with #{#relationship.followed.name}"
else
flash[:danger] = "That connection could not be accepted."
end
redirect_to relationships_path
end
def index
#relationships = current_user.active_relationships.all
#followed = User.find_by(name: params[:id])
end
def edit
#orig
# #followed = #relationship.followed
# #relationship = current_user.active_relationships.find(params[:id]).decorate
#2nd
# #followed = User.find_by(name: params[:id])
# #relationship = current_user.pending_relationships.find_by(followed_id: #followed).decorate
# stack
# #followed = User.find_by(id: params[:id])
# #relationship = current_user.pending_relationships.find_by(followed_id: #followed).decorate
#stack2
#followed = User.find_by(id: params[:id])
#relationship = current_user.pending_relationships.find_by(follower_id: #followed.id).decorate
end
def destroy
...
end
end
You are finding users by name but passing "ID" for the condition, so it is not able to retrieve corresponding records. Change this and Try Once:
def edit
# #followed = #relationship.followed
# #relationship = current_user.active_relationships.find(params[:id]).decorate
#followed = User.find_by(id: params[:id])
#relationship = current_user.pending_relationships.find_by(follower_id: #followed.id).decorate
end
Update:
You have specified follower_id as foreign key for your pending relationships try the above edit method. I have updated it.
It was saying, with the params[:id] no active_relationships exists for the current user.
I have a clan.rb and clan_options.rb
clan.rb
class Clan < ActiveRecord::Base
has_one :options, :class_name => "ClanOptions", :foreign_key => "clan_id", dependent: :destroy
accepts_nested_attributes_for :options
end
clan_options.rb
class ClanOptions < ActiveRecord::Base
belongs_to :clan
end
To create an edit form for clan.rb and clan_options.rb I use the following in edit.html.erb:
<%= form_for #clan, :html => {:class => 'form-horizontal'} do |clan| %>
<fieldset>
<!-- Form stuff -->
<%= clan.fields_for :options do |o| %>
<!-- o.text_field -->
<% end %>
</fieldset>
<% end %>
I can update the fields of clan.rb but when I try to edit the value backgroundurl it won't save it. Backgroundurl is one of the clan_options.rb
clans_controller.rb
class ClansController < ApplicationController
before_filter :check_login, :only => [:new, :edit]
before_filter :check_bound, :only => [:new, :edit]
before_filter :check_clan, :only => :new
def update
#clan = Clan.find(params[:id])
if #clan.update_attributes(clan_update_params)
flash[:status] = TRUE
flash[:alert] = "Successfully updated your clan."
redirect_to clan_path(params[:id])
else
flash[:status] = FALSE
flash[:alert] = #clan.errors.full_messages
redirect_to edit_clan_path(#clan.id)
end
end
def edit
clan = Clan.where(id: params[:id])
if !clan.blank?
#clan = Clan.find(params[:id])
user = User.where(id: session[:user_id])
if !user.blank?
#De gebruiker is ingelogt en zit in de clan
#user = User.find(session[:user_id])
if #clan.id != #user.clan.id
flash[:status] = FALSE
flash[:alert] = 'That was not your clan, you may not edit theirs.'
redirect_to clans_path
elsif #user.clanmember.group.rank != 10
flash[:status] = FALSE
flash[:alert] = "You must be the leader to edit the clan."
redirect_to clan_path(#clan.id)
end
end
else
flash[:status] = FALSE
flash[:alert] = 'that clan doesn\'t exist or has been removed.'
redirect_to clans_path
end
end
def clan_params
params.require(:clan).permit(:name, :prefix, :description, :user_id)
end
def clan_update_params
params.require(:clan).permit(:name, :prefix, :description, :user_id, options: [:id, :clan_id, :backgroundurl])
end
end
I've fixed it by changing
def clan_update_params
params.require(:clan).permit(:name, :prefix, :description, :user_id, options: [:id, :clan_id, :backgroundurl])
end
to
def clan_update_params
params.require(:clan).permit(:name, :prefix, :description, :user_id, options_attributes: [:backgroundurl])
end