I want my User to be able to change a boolean on a Share
that they own, but my attempt at implementation updates the wrong record.
When I go to the show page for an Item
with id:7
, my controller loads the associated Share
objects by looking for Share
s that have item_id
set to 7. When I then click the Hide
or Show
buttons, my code updates the associated Share
's active
attribute, and then redirects to that same Item
.
But if I go to the show page for an Item
with id:3
, and click those same buttons, my code redirects to and updates the active
attribute for the Share
with item_id:7
, instead of item_id:3
. Can anyone give me an idea as to why this is happening?
My Share model:
class Share < ActiveRecord::Base
belongs_to :user
belongs_to :item
def activate
self.active = true
save
end
def deactivate
self.active = false
save
end
end
My Item model:
class Item < ActiveRecord::Base
has_many :shares
end
In my ItemsController#show
action, I have this:
def show
@item = Item.friendly.find(params[:id])
@owned_share = current_user.shares.find_by(item_id: @item.id)
end
In my SharesController
, I have this:
def activate
@owned_share = current_user.shares.find_by(params[:item_id])
@owned_share.activate
respond_to do |format|
format.html { redirect_to item_path(@owned_share.item) }
format.json { render :index, status: :ok, location: @owned_share }
end
end
def deactivate
@owned_share = current_user.shares.find_by(params[:item_id])
@owned_share.deactivate
respond_to do |format|
format.html { redirect_to item_path(@owned_share.item) }
format.json { render :index, status: :ok, location: @owned_share }
end
end
And in my Item show view, I have this:
<% if @owned_share.active == true %>
<div class="eight wide column">
<%= link_to "Hide", share_deactivate_path(@owned_share.item), class: "button wide-button functional-red-button", method: :post %>
</div>
<% else %>
<div class="eight wide column">
<%= link_to "Show", share_activate_path(@owned_share.item), class: "button wide-button functional-mint-button", method: :post %>
</div>
<% end %>
As stated in the comments, the param you're receiving isn't item_id
, but share_id
, that's why despite you modify your query adding the attribute which to look for, it doesn't give you the expected result.
Update the param which to use for getting user's share, like:
@owned_share = current_user.shares.find_by(item_id: params[:share_id])
Although in this case isn't clear why you're using share_id to look for an item_id, most probably you could update that part too.
As both actions share some specific functionality, you could make just one that just updates the active attribute "flipping" its value:
# model
def toggle_active
update(active: !active)
end
# controller
def update_active_status
@owned_share = current_user.shares.find_by(item_id: params[:share_id])
@owned_share.toggle_active
respond_to do |format|
format.html { redirect_to item_path(@owned_share.item) }
format.json { render :index, status: :ok, location: @owned_share }
end
end
It gets the current user's shares active value and alternate it by using !
. Notice that if they don't have a default value, a negation of nil returns true.
!true # false
!false # true
!nil # true
Note @owned_share.active == true
can also be @owned_share.active?
or @owned_share.active
.
Because this:
@owned_share = current_user.shares.find_by(params[:item_id])
should be:
@owned_share = current_user.shares.find_by_item_id(params[:item_id])
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.