Couldn't find Order in ruby on rails - 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

Related

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.

Getting params out of an array - 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.

Rails, current_page?(user_path) giving an error

I have element witch I want hide on specific pages, for example on pages located at app/views/users/ (there I have new.html.erb; edit.html.erb; show.html.erb. And I have div in my layouts/application.html.erb it will be shown on all pages, so I want to hide it.
I thought i can do it like this:
<% unless current_page?(new_user_path) || current_page?(user_path) %>
<div>Some content</div>
<% end %>
But it will give me an error, pretty obvious: for user_show method he need an id of the user, but we are not visiting pages where variable #user is present. Can you land me a help:
Any possibility to get around this error? (And I don't want to assign #user variable every where and I don't want make list of all page what are allowed)
Is there any other way to hide element on specific pages?
Not entirely sure what you are trying to achieve, but this is how you can guard from user not being present:
unless current_page?(new_user_path) || #user && current_page?(user_path(#user))
I think what you probably want is:
<% unless current_page?(controller: 'users') %>
<div>Some content</div>
<% end %>
By passing controller: 'users' you catch all routes (actions) for that controller, including the new/edit/show routes.
For more detail see the docs.

Better way of getting objects id from another controller

I have ideas controller and static_pages controller. The latter has home action which displays all ideas and which i also use as root path.
I want the user be able to Edit the displayed ideas. So far i have this:
<% if #ideas.empty? %>
<p>Share your ideas! See what people think about it.</p>
<% else %>
<% #ideas.each do |idea| %>
<div class="panel panel-default">
<div class="panel-heading"><%= idea.name %></div>
<div class="panel-body"><%= idea.description %> <br>
<%= link_to 'Edit', edit_idea_path(idea.id) %>
</div>
</div>
<% end %>
<% end %>
I had an issue with an empty idea id which i solved by adding idea.id inside edit_idea_path
Now my question is, is that the proper, Rails way of doing it? In what other way can i fetch the idea object from this index page and use it in my ideas controller instead of static_pages controller?
I tried playing around with routing, but I have very vague understanding of it despite reading the guides and others code. I'd appreciate any insight about this matter.
First you need to understand that the requirement of your project defines what you should do in the code, whithout of concerning about the proper way to do something. You just need to follow the rails conventions.
http://guides.rubyonrails.org/active_record_basics.html#convention-over-configuration-in-active-record
Now, back to your question. You just need to create an action (that will handle a view) in your ideas_controller that will manage the edition of the data sended by de static_pages_controller, i will call it (just for example) edit_static_ideas and receive the data with params:
In your ideas_controller : app/controllers/ideas_controller.rb
def edit_static_ideas
#idea = Idea.find(params[:id])
end
Then you need to create the view in your views->ideas folder. An name it, just to continue my example i'll name it edit_static_idea.html.erb. And set the load of the data you get in #idea as a form or a form_for. Then you can submit that edited data and upload it into other action.
Then you have to configure your routes file and add
config/routes.rb
get 'edit_static_idea/:id', to: 'ideas#edit_static_idea', as: 'edit_ideas'
After that, if you run "rake routes" in your console (inside your rails project), you should see your new route (yay!)
Now you have to take the path in your route and use it in you static_pages_controller's view to redirect it to the edit_idea's view handle it by ideas_controller. And be sure that you also send the id of the selected item.
app/views/static_pages/home.html.erb:
<%= link_to 'Edit Idea', insert_your_edit_idea_obtainedinrakeroutes_path(id: idea.id) %>
At last, you only need to configure the form in your edit_static_idea.html.erb and assign it an upload/save route and redirect it to the view that you want.
for example:
In your routes file: config/routes.rb
patch 'save_edited_idea', to: 'ideas#save_edited_idea', as: 'save_edited_idea'
In your ideas_controller: app/controllers/ideas_controller.rb
def save_edited_idea
#idea = Idea.find(params[:id])
respond_to do |format|
if #idea.update(idea_params)
format.html { redirect_to the_view_that_you_want_path(id: #idea.id), notice: 'Data saved without problems.' }
else
flash.now[:alert] = "error"
format.html { render :offer }
end
end
end
I didn't wanted to be so detailed, because i wanted to help you to understand what you have to do. I hope it helps :P

How to find most recent post for each record in related table

I have a one to many relationship between 'challenge' and 'entry'. I am trying to create a page that shows the most recent entry for each challenge. I don't know how to do this. So far I have something which just shows all the entries only:
discovers_controller.rb
def index
#discovers = Entry.all
end
end
discovers.html.erb
<div id="grid-gallery" class="grid-gallery">
<section class="grid-wrap">
<ul class="grid">
<li class="grid-sizer"></li><!-- for Masonry column width -->
<% #discovers.each do |discover| %>
<li>
<figure>
<%= image_tag discover.picture.url if discover.picture? %>
<figcaption><p><%= discover.blob %></p></figcaption>
</figure>
</li>
<% end %>
</ul>
</section>
If you set up relation in standard way, you should be able request entries for each challenge in the way suslov mentioned in comments: challenge.entries
Then you just take the most recent - .last the easiest way to do it, but it could not suit you if you define most recent by update_at field, for example. So, you probably would want to sort it beforehand with .order('updated_at') in this case (or any other relevant attribute)
In you particular case to define last entries, you can use something like that in your controller
#discoveries = Challenge.all.map{|c| c.entries.last}
In your controller you can do:
#discovers = Entry.order('created_at DESC').all
However, I'd recommend you to use pagination instead of doing all in your query. As it will increase the page load time as the number of data in entries table increases.
UPDATE:
You ca create a scope in Entry model:
scope :last_entries, -> { order(:created_at => :desc).group(:challenge_id) }
then in your controller:
#discovers = Entry.last_entries #no need to do `all`, as it is default
But, I'd still suggest you to consider using pagination.

Resources