How to make an object appear different to the poster in Ruby on Rails? - ruby-on-rails

I'm working on a project that will allow people to create groups then send a task to all of the people who are apart of that group. When the person who matches the same user_id as the value attached to the task, I would like it for the task to appear different (different text on it and some other stuff) and when you click it, it shows analytics for that task. I just need to know what it takes for me to pull of altered versions of an object for the person who posted it. Thanks for any help. I may be too vague here, I'm still very new to Rails.

If a task belongs to a user, and you have access to current_user (if you're using devise it's built in, w/ bcrypt you'll have to write yourself), an easy way to do this in the views would be to say something like:
<% if task.user_id == current_user.id %>
<-- stuff you want to show the assigned user -->
<% else %>
<-- stuff you want to show everyone else -->
<% end %>
Assuming you're using erb. But you get the gist.

Related

In Rails, can I lookup a relation without explicitly looking it up in the controller?

I’m using Rails 4.2.5. In my model, my user has an attribute, “avatar_file_id” which links to a table in which the filename is defined. The “avatar_files” table has the fields
id
file
When the user is logged in, I want to display the avatar image on my page, but I’m having trouble figuring out how. In my controller, I have a reference to the logged in user (#current_user), and so I have
<%= image_tag "avatar_images/#{current_user.avatar_file_id}", alt: current_user.name %>
but clearly, this will only attempt to lookup a file where the filename is the id, which is not how things are setup. Do I need to explictly lookup the image file in my controller and then include that variable on the page or is there some slicker way of getting the image path given only the user object?
Thanks, - Dave
You can do something like
<%= image_tag "avatar_images/#{Avatar.find(current_user.avatar_file_id).file}", alt: current_user.name %>
But you skip a lot of safeguards to do it this way (i.e. what if a user hasn't uploaded an avatar image?) and if you put that sort of stuff in your view things really start to get messy.
Generally you want as little logic in your views as possible since it's much harder debug html/Ruby than the pure Ruby in your controller so it's probably better just to load the object in your controller and pass it through in a variable.

Where do I save a variable that should not be overwritten when I refresh the page in rails

I am pretty new to Rails and Ruby and still wrapping my head around the hole concept of Rails.
What I want to do:
I'm creating a shift-planner with a view of one week and want to create a button that will show the next/last week.
What I did:
I have 3 tables that are relevant. shift, person and test (contains types of shifts)
Where both Test and Person have one to many relations to Shift.
In my controller I did the following:
def index
#todos = Todo.all
#shifts = Shift.all
#people = Person.all
#start_of_week = Date.new(2015,8,7)
#end_of_week = Date.new(2015,8,11)
view:
<% person.shifts.where(:date_of_shift => #start_of_week..#end_of_week).order(:date_of_shift).each do |shift| %>
<td>
<%="#{shift.test.name} #{shift.date_of_shift}"%>
</td>
<%end%>
My Idea was I would make a link where I would increment both Dates and refresh my Page
<a href="/todos/new">
Next Week
<% #start_of_week += 7 %>
<% #end_of_week += 7 %>
</a>
Unfortuately that doesn't work. Cause everytime I call the index function in my controller it sets the date on the default value.
And I'm pretty clueless how to fix this problem in a rails way.
My only would be to somehow pass the dates as parameter to the index function or something like that.
The general structure is:
I scaffolded a Todo view/controller/db just for the sake of having a view / controller and my 3 tables.
Thx for the help.
PS: I'm using the current version of ruby and rails on lubuntu15 (shouldn't be really releveant^^)
The controller method will be invoked every time someone loads the page. If you want to have temporarily persistent storage you should look into cookies (generally sessions are easier to use but in your case it might be relevant to let the client change the data too, click on back/forward buttons and you don't want to have a HTTP request for every little interaction, right?). You can find the relevant documentation here.
Using the variable could look like this:
# in the controller
cookies[:start_of_week] ||= Date.new(2015,8,7)
# in the view
cookies[:start_of_week]
Maybe you want to work with an integer instead of a date object here if you plan on using it on the client side, but then you would have to take that into account in your views.
Edit: On re-reading your question I realized that my answer didn't address several things.
Why is the code you tried not working?
<a href="/todos/new">
Next Week
<% #start_of_week += 7 %>
<% #end_of_week += 7 %>
</a>
When writing your views you have to be aware that it will be evaluated on the server side and then be sent to the client side (web browser in this case). You increment the instance values #start_of_week and #end_of_week when the page is rendered but not later.
So either you have the link go to a special action in your controller that will handle the new value set the cookie/session variable (later one is an option only in this case) and render a new page and send it back to the user or you use Javascript and do this on the client side and change the cookie so no unescessary additonal requests have to be made (but then thinking about it you will most probably need to load data from the server anyway so it might not make any difference which one you take).

Allows user to edit pages that contain variables [duplicate]

This question already has an answer here:
How to render a string as an erb file?
(1 answer)
Closed 9 years ago.
I have some editable pages that are stored as text in my database. These pages will be called in my view like...
#app/views/static_pages/scheduling_text.html.erb
<%= Page.find_by_name("New Registration").content %>
Page.content is of type 'text' (not string). A portion of the text that contains variables would look like...
You have successfully registered for New Student Orientation on #{<%= #registration.orientation.class_date %>} at...
If course when I call this content in the view, I just get the text, not the model values. How can I make these pages access the model values? I also tried adding #{} around the text without success.
This seems to be a duplicate of Rails: storing erb templates in database
Given that, this should do the trick for you, or at least be close enough to get you started:
<%= sanitize ERB.new(Page.find_by_name("New Registration").content).run %>
Additionally, you can remove the sanitize if content is not user-supplied (this is primarily a security concern).
I've done something exactly like this using HAML processing:
= sanitize Haml::Engine.new(article.content).render
For reference, here's the appropriate ERB documentation: http://ruby-doc.org/stdlib-2.0.0/libdoc/erb/rdoc/ERB.html
OK, after much wailing and gnashing of teeth here is the the solution I cam up with. First I am using mustache. This is much safer than storing erb in the templates and prevents malicious injection of sql into your app. I simply added 'mustache' to my gemfile rather than mustache-rails as it seems to be more up to date. I then created a simple Page model with two attributes: :name and :content. I am using the page model to store the raw mustache code.
Here are the relevant files...
In my controller I call...
#app/controllers/registrations_controller.rb
def create
#registration = Registration.new(params[:registration])
respond_to do |format|
if #registration.save
if #registration.orientation != nil
format.html { render "scheduling_text.html.erb" }
Then my view looks like...
#app/views/registrations/scheduling_text.html.erb
<%= Mustache.render(Page.find_by_name("New Registration").content, {:registration => #registration }).html_safe %>
<%= link_to 'Back', orientations_path %>
...
Then in my page model I have something like...
You have successfully registered for New Student Orientation on {{ registration.orientation.class_date }} at {{ registration.orientation.class_time}}. Please arrive 10 minutes prior to your scheduled Orientation. Remember, you must attend this Orientation session before you may register for classes. ...
Using a page model with scaffolding like this works well because it gives you the new, update, and create actions that will allow users to edit content. Note, they can easily mess up your ruby variables, so thats the downside. Just let your users know to not munk with anything that is between {{}}.
Hope this helps someone else out.

Ruby on Rails (3) hiding parts of the view

I am working on a Ruby on Rails 3 web application.
I have a table named User with a coulmn named role. I am looking for the best way to hide parts of the view from users that have the "wrong" role for those parts of the view.
For example I want all users to be able to see the users index page, but i want only users with a role - admin to be able to edit other users.
So first I block the edit action using filter_by, but what I also want is make the edit button not to appear.
The current user is saved in the session, so checking the user role is very simple.
What I am asking, is there an easy way to do so besides the obvious if statement before each button I want to hide. I would think that rails would have an easy way to do this type of thing, I couldn't find one.
You may want to use Devise and CanCan.
https://github.com/plataformatec/devise
https://github.com/ryanb/cancan
Here is a RailCast tutorial
http://railscasts.com/episodes/192-authorization-with-cancan
if you wanted to clean it up a tiny bit you could write yourself an application helper:
def if_admin(user)
if(user.is_admin? && block_given?)
yield
return
end
end
then in your view you could write:
<% if_admin(#user) do %>
<some admin only html />
<% end %>

Rails user authorization

I am currently building a Rails app, and trying to figure out the best way to authenticate that a user owns whatever data object they are trying to edit.
I already have an authentication system in place (restful-authentication), and I'm using a simple before_filter to make sure a user is logged in before they can reach certain areas of the website.
However, I'm not sure the best way to handle a user trying to edit a specific piece of data - for example lets say users on my site can own Books, and they can edit the properties of the book (title, author, pages, etc), but they should only be able to do this for Books that -they- own.
In my 'edit' method on the books controller I would have a find that only retrieved books owned by the current_user. However, if another user knew the id of the book, they could type in http://website.com/book/7/edit , and the controller would verify that they are logged in, then show the edit page for that book (seems to bypass the controller).
What is the best way to handle this? Is it more of a Rails convention routing issue that I don't understand (being able to go straight to the edit page), or should I be adding in a before_find, before_save, before_update, after_find etc callbacks to my model?
check out the following gems:
cancan
devise
authlogic
and don't miss Ryan's great railscasts on the above
this will give access to anyone who changes the value in the address bar
#book = Book.find(params[:id])
but if you go through the association of the logged on user rails (ActiveRecord) will automatically update the sql query
#book = current_user.books.find(params[:id])
of course this assumes that your books table has a user_id column
You may need an authorization plugin. I had some experience use this plugin a while back. This article also has an overview:
You might also take a look at Declarative Authorization
Hey I have recently done this myself. The easiest way to do this is to have the edit feature display on the page but incase it in a method such as the following:
<%if current_user %>
<% if current_user.id == wishlist.user_id %>
<div id="text3"><%= link_to 'Edit', edit_wishlist_path(#wishlist) %></div><br />
<%end%>
<%end%>
Is this what you were hoping for?

Resources