How to get user id in an order mailer - Spree - ruby-on-rails-3

Quite new to rails/spree and am trying to create a pdf uploader where users can upload images that will then be sent to the company but when I try to send it I get an undefined local variable or method for 'spree_current_user'.
This is the line that gives the error. I know this would normally grab the id (I have used the same line in controllers) but I am not sure why it wouldn't work within the order mailer.
pdfs = Pdf.where(user_id: spree_current_user.id, created_at: Date.today-1.hour)
Basically I'm just wondering if anybody knows what else I could do? I tried to pass it through the controller as a session[] but this didn't work either.
If there are any other files that you might need to look at then please let me know. Would very much appreciate any help !
Thanks in advance.

You can't access the session or Controller helpers (which spree_current_user is one of). You must pass controller-level information to the objects (mailers) you want them in.
So the calling code for the uploader object must pass in the user id into the object where you want it. Since you didn't specify what object that is (exactly) I can't really answer out of context. But as a general rule session-level concepts (like the current user) belong to the controller, and if you want them elsewhere (outside of the controller) you need to pass them along with the call to the objects that are called from the controller.
If that's not possible, a first-order association (like adding user_id to the object in question) is also a good solution, depending on your domain model.

I have solved this issue if anyone else is needing it. What I did was pass the user id through a hidden field in the view:
hidden_field_tag 'current_user', spree_current_user.id
Then I added it in the controller
OrderMailer.send_to_client(..., ..., ..., params[:current_user]).deliver
I then changed my original pdf line to account for pdfs created in between certain times:
pdfs = Pdf.where(user_id: current_user, pdf_updated_at: Time.now-1.hour..Time.now)
As well as sending it through in this method.
def send_to_client( ..., ..., ..., current_user)
Hope this helps if anyone is experiencing a similar issue :).

Related

Authorization with Devise and multiple levels

I need some help with the authorization. So far I was trying to solve it with the internal rails authorization combined with devise.
I have a user who is posting a request. If this request is private only a group of "reader" can see and answer the request. (This is number one)
Then the user give a rating to the answer of the reader. This should be accesible only for the user which received the answer and the "reader" who gave an answer.
So far I was using the following to limit access to the hidden requests:
before_filter :require_reader!, only: [:open_requests]
But if the request is not hidden, than still only the reader should be able to answer the request (but all can see it). Here I do not know how to manage this. Any Ideas?
To continue... I could not manage to solve the second problem (that the rating is seen only be the one who was placing the request and the reader).
Any ideas here?
Is cancancan maybe an option?
Best
witali
What you're doing does not quite follow the 'admin' pattern that's commonly setup with tools like Railsbricks. The 'admin' permissions pattern is typically a whole set of actions/views that are available only to admins, so often the entire Controller, or family of controllers, have the :require_admin! filter applied before every single action and view. Very simple permissions logic, and it depends only on the user and view.
Instead, what you've got is views with permissions that depend on your object's state as well as the user's status and the view. So you're going to have to write your own filter to use instead of using 'require_reader!'.
For example, you might have a RequestsController, and you could add to it:
before_action :must_be_able_to_view_request, except: [:index, :new, :create]
Then define that filter in the controller:
private
def must_be_able_to_view_request
if !current_user.is_reader? && !#request.ispublic
head :forbidden
end
end
If you need to use the same filter in other Controllers, then you can define it in your ApplicationController.

How do I utilize user input without putting info into a Model?

This is an incredibly newbish question, but I can't seem to find the answer.
I'm building an app that utilizes external APIs heavily, and I'm fairly new to Rails, so it's still a little rough to get around. I can't, for the life of me, figure out how to accept user input and execute a function in my app without writing to a model.
For example, I just want to let a user type in a Twitter username and have it display on the page. I know how to make a form to cache the search in a model, but I can't figure out how to just... make a function happen on a page. I've been breaking my brains on this for several days now.
Please help? :/
You don't need a model to use Rails, but if you don't need ActiveRecord at all, you might benefit from a lighter framework like Sinatra. That doesn't answer your question, but it's worth thinking about if you really have no database requirement for your application.
It sounds like you're just trying to access non-resourceful user input, which is accessible in the controller via the params hash. So, assuming you have set up a valid route for the form action, you use your controller to extract GET or POST parameters.
For example:
# You define a non-resourceful route in routes.rb for your form action.
get 'twitternames/show'
# Form action directs user to GET the following route after filling in the form.
http://example.com/twitternames/show?user=foo
# The controller action extracts the data.
def show
#user = params[:user]
# render the view unless you tell rails to do something else
end
# show.html.erb
<%= #user %>
Creating the right route is the key. Once you've defined a route that can break a URL into the proper segments, the rest will fall into place.

Is there a good methods to find user's all tags with acts-as-taggable-on?

I use acts-as-taggable-on https://github.com/mbleigh/acts-as-taggable-on for tagging user's post, I want to find one user's all post' all tags and list them, Is there a high performance method ?
You need to add acts_as_tagger to the User model
refer to https://github.com/mbleigh/acts-as-taggable-on#tag-ownership
then you can use the methods provided. If you're starting from a blank db, this should work but may need to run through some re-assigning loop to have the tagger association work.
Assuming your data is correct, you will then be able to do:
#some_user.owned_taggings
#some_user.owned_tags
Hope this helps

In Rails 3 app, how do I allow anonymous users to access a controller action only once?

For example, suppose I had a blog and anybody could read the articles, read the comments, and flag any comment as inappropriate. How do I prevent non-signed-in users from clicking the "Flag Comment" link more than once?
The "Flag Comment" link would be tied directly to a controller method for a Comment model.
I'm new to the idea of sessions and cookies (as well as Rails in general). I've read this on Sessions but I'm afraid I'm still a little confused.
I've considered creating a Base class called Guest, but I was wondering if I could avoid this and instead utilize session or cookies temp data.
Thanks in advance.
The basic idea could be the following (sorry, no code yet):
Define which information should be stored in a session and / or a cookie. I think it should be the id of the comment for each flagged comment. Store them in a hash like structure.
Make the link to flagging a comment depending on the content of the cookie. Something like that:
...
= link_to('flag comment', flag_comment_path(comment.id)) if ! cookies[:flagged_comments] || ! cookies[:flagged_comments][comment.id]
Set the cookies hash value when a comment is flagged (use here the local variable comment, this has to be set or known somewhere):
cookies[:flagged_comments] = Hash.new if ! cookies[:flagged_comments]
cookies[:flagged_comments][comment.id] = comment.id
I don't know if the code will work, but the idea should be clear. And yes, do that only to anonymous users (more dependent UI and controller functionality).
One more thing: I don't think you should use the session and the cookies for storing this information. And due to the fact that you have to notice when someone flags a comment in 2 different sessions, go with the cookies only.

When should an object be included as a member of another object, and when should it always standalone?

An example problem:
On Stack Overflow, a question page shows a number of different answers. In displaying these answers, the site also gives information about the author of the answer. This means that although the number of badges a given user has has nothing to do with an answer in and of itself, that data still needs to be retrieved in order to display the page.
From what I can see, there are three different ways to go about pulling this view data in a model:
A Post object could include a full User object as a member. The view would then access the user like this: $post->user->getReputation(). This seems cleaner, since a Controller could just request the posts and be done with it, but yet inefficient since a Post probably doesn't always need a full-blown User. I suppose it works well enough if the User object is relatively light, which it probably would be. The problem would then be that you would need to duplicate User retrieval code as part of the Post retrieval query.
The Post object could hold just an ID for a User. When the Post, or Posts, are returned to the Controller, the Controller could then extract the unique User IDs from the returned set and pass them to a User factory. The returned User objects would then be passed along with the original Posts set to the View as a separate collection. The view could then grab user info using something like $users[$post->getUserId()]->getReputation().
A hybrid approach: Include the User object inside the Post object, but have the unique id extraction and User retrieval as part of the Post retrieval method. i.e. Post::getPosts() would grab all relevant posts and convert them to objects with null User members, then it'd extract all user ids and pass them to User::getUsers(), then assign the Users to the relevant Posts before returning the set of Posts to the caller.
I guess what I'm getting at is, how do I know when an object needs to contain another object fundamentally? Is it unclean/a code smell to instead have such related objects returned separately, with neither object knowing the other has been retrieved. I'm leaning towards the separate retrieval concept - it seems the most efficient - but it really does feel like they're too related for that to make sense.
There is also a solution in between 1 and 2. You can have a lazy loading proxy for the user class. With this solution you can have best of both worlds because the proxy is interchangeable with the real thing so depending on the situation you can have the object itself or the proxy.
Edit:
I'll try to explain this with an example.
Say that you have a view where you don't need user info, then you can instruct/configure your post factory to use the lazy proxy (see wikipedia)for the user which will only contain an ID. So no access to users is needed.
In another view you occasionally need to access user info but only for some posts, here again you instruct/configure your factory to include the lazy proxy for the user.
But when you actually need access to the user info, you can access the proxy object that will then load the actual user object and redirect messages to it.
In yet another view you need both post and user info, so here you instruct your post factory to use actual user objects.
It seems to me that this is another case of dependency injection. A general enough idea that could help you.
DEPENDENCY INJECTION WIKI
Read something about the Inversion Of Control also.
why not add optional member to model to know informations?? you can ignore when you don't need and can use when you do need.