Getting params out of an array - Rails - ruby-on-rails

I'm still learning here and i'm sure its something pretty easy i can't figure out. But basically,i'm working on an e-commerce platform.
When a customer clicks checkout in the cart, the new action is triggered in the Orders controller.
However, i'm trying to load the line_items that are in the cart onto the checkout page.
So far, i've only been able to load one of them.
If there are 2 -3 items in the cart, i want the customer to be able to see what he is paying for.
In the controller, i have:
def new
#order = Order.new
#item = current_cart.line_items
end
In the view i have:
UPDATED
<script src="https://checkout.stripe.com/checkout.js">
data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
data-currency="gbp"
<% #item.each do |t| %>
data-name="<%=t.quantity %> × <%= t.product.title %>"
data-description="<%= t.size %>, <%= t.color %>"
data-amount="<%= (t.product.price * 100) %>"
<% end %>
data-email="<%= current_user.email %>"
data-shipping-address="true"
data-locale="auto">
</script>
My issue is there's clearly 2 items in the cart when i look in the console. But i just can't get that to show as it seems #item is an array.
Any help would be appreciated. Thanks in advance!

As you are saying, you want to show two items from #item instance variable; that means you are showing those values in show action but fetching in new action. I think you need to fetch it in show action and then apply an each loop.
def show
#item = current_cart.line_items
end
Then in 'show' view, loop it through each loop.

Related

Couldn't find Order in ruby on rails

I am trying to build a page to load order id but it threw back Couldn't find Order, can you help?
routes.rb get '/orders/cancellation', to: 'orders#cancel'
<h1>Preview & Cancel your order here</h1>
<div class="block">
<h1> Order <%= #order.name %></h1>
<div id="multiple-file-preview">
<ul id="sortable">
<div class="clear-both"></div>
</ul>
</div>
</div>
def cancel
paginate_versions PaperTrail::Version.where(order_id: order.id).order(created_at: :desc)
remote_versions_pagination
end
def order
#order ||= Order.find_by!(shopify_id: params[:id])
end
It might be due to the cancellation being taken as order id. You can verify it using debugger in show action.
If it is the case then you need to modify the routes file in such a way that orders/cancellation comes before the orders/:id i.e. the show action as rails will try to match the route in an up-down fashion and the request will be dispatched to the first matching route.
You should have instance variable defined in that specific controller action.
It will solve that issue
def cancel
#order ||= Order.find_by!(shopify_id: params[:id]) # Whatever you need to assign.. just make sure we have #order here pints to some order record
paginate_versions PaperTrail::Version.where(order_id:order.id).order(created_at: :desc)
remote_versions_pagination
end

rails 5.1.4 ( ActionCable + Jobs + Devise + ConversationsController.render )

Actually I need a big help, I'm using rails 5.1.4, I get stuck when rendering a partial with ActionCable and background Jobs. In my partial, I have a condition on current_user to check if current_user is the message owner and get his username with green color to make somes differents, so far display an update and delete button for each message he's the owner in the room conversations. But, if I refresh the page or remove current_user in the partial before rendering it works. However, I want that condition happens. Or, looking for a best way if there is one. THANKS IN ADVANCE.
Here is the error displayed in my terminal:
ERROR: ActionView::Template::Error: Devise could not find the warden::Proxy instance on your request environment.
Those are my files content.
The partial: _conversation.html.erb
<div id="message">
<% if conversation.user == current_user %>
<span style="text-align: center; color: green"><%= conversation.user.username %>
</span>
<% else %>
<span style="text-align: center; color: magenta"><%=
conversation.user.username %></span>
<% end %>
<p style="color: black"><%= conversation.body %></p>
</div>
Message_controller.rb
def create
conversation = #room.conversations.new(conversation_params)
conversation.user = current_user
conversation.save
MessageRelayJob.perform_later(conversation)
End
Room/show.html
<div id="conversations" data-room-id="<%= #room.id %>">
<%= render #room.conversations %>
</div>
MY JOB CLASS
class MessageRelayJob < ApplicationJob
queue_as :default
def perform(conversation)
ActionCable.server.broadcast "room_tchats_#{conversation.room.id}_channel",
conversation: render_conversation(conversation)
end
private
def render_conversation(conversation)
ConversationsController.render partial: 'conversations/conversation', locals: {conversation: conversation}
end
end
It can be happening when you try to get Devise current_user in some part of code being managed by action cable. like a background job to render comment or something else. you can resolve it by using something like following in your controller, since you cant access warden at a model or job level(according to my limited knowledge): (I call a job right after creation of my comment in CommentsController create action, which calls a private method to render a comment partial containing edit and delete button, for which current_user was required)
def create
#product = Product.find(comment_params[:product_id])
#comment = #product.comments.build(comment_params)
#comment.save!
gon.comment_id = #comment.id
gon.comment_user_id = #comment.user_id
ActionCable.server.broadcast "chat", comment: render_comment
render :create, layout: false
end
def render_comment
CommentsController.renderer.instance_variable_set(:#env, {"HTTP_HOST"=>"localhost:3000",
"HTTPS"=>"off",
"REQUEST_METHOD"=>"GET",
"SCRIPT_NAME"=>"",
"warden" => warden})
CommentsController.render(
partial: 'comments/comment_detail',
locals: {
product: #product,
comment: #comment
}
)
end
this will help you resolve warden issue, if you have used devise's current_user in that partial, it will give you the commentor user (as it should since that user initiated the rendering of partial). Now to solve this, if you have a front end framework you might need to fetch the current user from cookies in order to restrict some actions like edit/delete. but if you are working in pure rails the solution I came across is that you have to make a hidden field in the dom having current users id, and you will fetch that id for comparison in a script. you might need to access rails variables in javascript, for that you can use GON gem. I know this answer might contain much more than asked but I've searched alot and no where I found a satisfactory solution to this problem, feel free to discuss.

Rails: Having a button in a view call a method in a controller, route not working

Hi I'm making a rails app that uses Zendesk API calls. I have a controller that uses two classes I defined
class TicketsController < ApplicationController
require 'ticket_fields'
require 'ticket_search'
def getTickets
#search_fields = SearchFields.new(client)
#tickets = TicketSearch.new(client)
end
def search_tickets
#ddcustomvalues = [params[:customer_company_id], params[:study_id], params[:type_id], params[:system_id]]
#tickets.search_tickets(ddcustomvalues)
end
end
One class SearchFields uses the api to load values I want to filter tickets by into arrays. My view then uses these values to populate drop down lists.
The other class TicketSearch looks like this.
class TicketSearch
attr_reader :tickets, :text
def initialize(client)
#text = "query"
#tickets = Array.new
client.tickets.all do |resource|
#tickets << resource
end
end
def search_tickets(custom_search_fields)
querystring = "type:ticket+tags:"
custom_search_fields.each_with_index do |field, index|
unless field == ""
if index ==0
querystring += "#{field}"
else
querystring += " #{field}"
end
end
end
#text = querystring
end
end
What I want to happen in my view is when a button is pressed it changes the value of #text to the querystring generated by the drop down list options that were selected. I'm currently doing this for testing to see if my querystring is correct and the button works. What I eventually want it to do is send the querystring to the ZenDesk Server and returns the tickets I filtered for. the #tickets array would then be replaced with the filtered tickets the server returned. Currently my button code looks like this.
<%= button_to 'Search', :action => 'search_tickets' %>
with all the route code I've tried I either get an error upon starting the page. Or when I press the button nothing happens and the #text being displayed in my view remains "query". Can someone help explain what I need to do I don't quite understand how routes work.
==================================================================================
Hey so I made the changes you suggested and did some reading up on AJAX and js and I think I'm almost at the answer my view now looks like this
<div id="test" >
<%= render partial: 'text', locals: { text: #tickets.text} %>
<div id="test" >
and I created a partial _text file that looks like this
<p> Query: <%=text%> </p>
and a js file search_tickets.js.erb
$("#test").html("<%= escape_javascript(render partial: 'text', locals: { text: #tickets.text } ) %>");
any idea what may be going wrong everything loads up okay but the text remains the same in the partial i set up when i hit the button still
the console outputs this after the button is hit
ActionController::RoutingError (No route matches [POST] "/tickets/search_tickets"):
so I guess it may actually be a routing error my route looks like this
resources :tickets do
collection do
put :search_tickets
end
end
and the form tag calling the path looks like this
<%= form_tag search_tickets_tickets_path, remote: :true do %>
<table>
<tr>
<td align = "left" valign="middle"> <font size = 4> Customer Company </font> </td>
<td align = "left" valign="middle">
<%= select_tag "customer_company_id", options_for_select(#search_fields.customer_companies), :prompt => "Select One" %>
</td>
</tr>
......
<tr>
<td> </td>
<td align = "left" valign="middle">
<%= submit_tag "Search" %>
</td>
</tr>
</table>
<% end %>
==================================================================================
(Update)
I think I fixed my last problem by changing my form tag to this
<%= form_tag search_tickets_tickets_path(#tickets), method: :put, remote: :true do%>
however now I get this error from the terminal after I hit the button
NoMethodError (undefined method search_ticket' for nil:NilClass):
app/controllers/tickets_controller.rb:15:insearch_tickets'
how would I pass #tickets as a parameter through my route because clearly its not accessible by search_tickets right now as its giving a nil class error.
Variables
when a button is pressed it changes the value of #text to the querystring generated
It looks to me like you're confused with the stateless nature of Rails - in that, just because a view has been rendered doesn't mean the values / variables are still available for use.
It was mentioned in the comments that it seems you're basing a lot on experience with other frameworks / programming patterns. The best way to describe your solution is that Rails has to "refresh" all your variables / values each time it processes a request; consequently meaning that if you send a button request - you'll have to perform the request as if it were the first one
Ajax
The bottom line is that you need to use an ajax request to pull this off.
To do this, you'll be be best creating a form (not just a button_to), as this will give you the ability to send as many params as you want. You should use form_tag:
#config/routes.rb
resources :tickets do
collection do
get :search_tickets
end
end
#view
<%= form_tag tickets_search_tickets_path, remote: :true do %>
... #-> fields for your params
<%= submit_tag "Search" %>
<% end %>
This will give you the ability to define the following in your controller:
#app/controllers/tickets_controller.rb
Class TicketsController < ApplicationController
def search_tickets
#ddcustomvalues = [params[:customer_company_id], params[:study_id], params[:type_id], params[:system_id]]
#tickets.search_tickets(ddcustomvalues)
respond_to do |format|
format.js #-> loads /views/tickets/search_tickets.js.erb
format.html
end
end
end
#app/views/tickets/tickets_search.js.erb
//JS here to manipulate your original page
Requests
The bottom line here is that if you want to "manipulate" your view without refreshing, unlike "native" application frameworks, where you can rely on a persistent state, with Rails, you basically have to construct the request from scratch (IE passing all the params required for the method to run)

Rails - Execute actions on post's index page

I have a model "Products" (which is a child model of parent model "Assortments") which can be liked by the user. Right now, you can only like the Product on the Products Show page because i'm able to find the products ID, which is what i need to like it
def like
#assortment = Assortment.find(params[:assortment_id])
begin
current_user.vote_for(#product = Product.find(params[:id]))
respond_with #product, :location => assortment_product_path
rescue ActiveRecord::RecordInvalid
redirect_to #product
end
end
I would also like user's to be able to like the product on the products index page. For example, if you go to Pinterest, you can like all the products on their fluid grid layout page as well as on each pictures respective page.
This is one of those things I have yet to learn how to do with Rails. How can i accomplish this??
Thanks in advance! Happy Holidays
Assuming your like action is in your ProductsController, and you have set #products equal to the products you want for your index page, and you're using erb, put something like this in your view:
<% #products.each do |product| %>
<%= link_to "Like", product_link_path(id: product.id) %>
<% end %>
Even if you have it set up differently, it can't be too far off from this.

Custom Button Action in Rails View - Ruby on Rails

Rails newbie here. I have an array of hashes that contain Facebook Friends that I'd like to optionally turn into 'Contacts'. I have an index view that lists all of the users's 'friends'. I'd like to have a custom button that enables the user to turn each friend into a contact. How do I do this in Rails?
Index view - I am currently listing each user with their avatar & name. I'd like to add the button in each list item.
Note: I do not have a Friend model, as I am simply pulling this data in from the Facebook Graph API as an array of hashes.
<% #friends.each do |friend|%>
<li> <%= image_tag(fb_avatar(friend["id"], "type=square"))%> <%=friend["name"]%> #put button here </li>
<% end %>
Custom make_friend_contact method in Application Helper (to be called on a friend):
def make_friend_contact
Contact.new(name: self["name"], uid: self["id"], avatar_url: fb_avatar(self["id"], "type=square"), user_id: params[:user])
end
Any help is much appreciated. I've done quite a bit of reading, and I can't seem to crack this one. Thanks!
One solution might be to use button_to. You can check it out in the Rails API. Here is one of their examples:
<%= button_to [:make_happy, #user] do %>
Make happy <strong><%= #user.name %></strong>
<% end %>
# => "<form method="post" action="/users/1/make_happy" class="button_to">
# <div>
# <button type="submit">
# Make happy <strong><%= #user.name %></strong>
# </button>
# </div>
# </form>"
where the button calls the make_happy action in the Users controller on #user.
You could do something similar by making an action in your Users controller that creates a new Contact, using a friend parameter.
def make_friend_contact
friend = params[:friend]
Contact.new(name: friend["name"]...
end
Then you just have to send the friend parameter with the button's POST request.

Resources