How do I use user_helper method globally throughout the app views? - railstutorial.org

I finished chapter 8 on Michael Hartl's Rails Tutorial, so I have the app set up to sign users up & sign in and out.
What I am trying to do user a User Helper method inside the application.html.erb (or more specifically inside a _header.html.erb partial).
I want to use the gravatar_for method (Defined in the user_helper.rb) to show the user's gravatar picture and users name instead of having the word "Account" with the drop down.
module UsersHelper
# Returns the Gravatar for the given user.
def gravatar_for(user, options = { size: 150})
gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
size = options[:size]
gravatar_url = "http://gravatar.com/avatar/#{gravatar_id}?s=#{size}"
image_tag(gravatar_url, alt: user.name, class: "gravatar")
end
end
On the show.html.erb page I have the following code
<% provide(:title, #user.name ) %>
<div class="row">
<aside class="span6">
<section>
<h1>
<%= gravatar_for #user %>
<%= #user.name %>
</h1>
</section>
</aside>
</div>
And that shows the user's gravatar and name on their profile page. So what I tried to do was add those same methods to the header partial like so;
<% if signed_in? %>
<li id="fat-menu" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<span id="small">
<%= gravatar_for #user %><%= #user.name %><b class="caret"></b>
</span>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Profile", current_user %></li>
<li><%= link_to "Settings", '#' %></li>
<li class="divider"></li>
<li><%= link_to "Sign out", signout_path, method: "delete" %></li>
</ul>
</li>
<% else %>
<li id="cta"><%= link_to "+ Sign up", signup_path %></li>
<li><%= link_to "Sign in", signin_path %></li>
<% end %>
And that code shows up completely fine on the show.html.erb page, which I am assuming is because its the show action on the Users controller. But when I try to click to the home page or really any other page outside of the Users View then I get the error
NoMethodError in Pages#about
undefined method `email' for nil:NilClass
So I guess my question is how do I make the gravatar for method and the #user.name available to all the views throughout the application. I feel as if the answer should be fairly simple, but i'm pretty new to rails, so any help would be greatly appreciated!

Put the method in the ApplicationHelper instead of the UserHelper. Here is an example of something similar I did in my own app: https://github.com/NatashaTheRobot/tinysale/blob/master/app/helpers/application_helper.rb

Related

Phoenix framework: Where does resource's default form #action attribute for all resources come from?

The command
mix phx.gen.html Blog Post posts title body:text
generates among other files the template form.html.eex for the add/edit posts form, which looks like this:
<%= form_for #changeset, #action, fn f -> %>
<%= if #changeset.action do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below.</p>
</div>
<% end %>
<div class="form-group">
<%= label f, :title, class: "control-label" %>
<%= text_input f, :title, class: "form-control" %>
<%= error_tag f, :title %>
</div>
<div class="form-group">
<%= label f, :body, class: "control-label" %>
<%= textarea f, :body, class: "form-control" %>
<%= error_tag f, :body %>
</div>
<div class="form-group">
<%= submit "Submit", class: "btn btn-primary" %>
</div>
<% end %>
The form_for function gets #action argument which is not present in the PostController, so where does it come from? I couldn't find.
In my installation I have a plug MyProject.Locale which redirects all unlocalized requests to localized ones like:
/posts --> /de/posts
And I have the :locale scope in my router
scope "/:locale", MyProject.Web, as: :locale do
pipe_through :browser
get "/", PageController, :index
resources "/posts", PostController
end
The default #action doesn't take the scope's locale chunk into account and sends the POST request to the /posts url, which is redirected by my MyProject.Locale plug to /de/posts as GET request (it uses the function Phoenix.Controller.redirect(to:...)). I want the form to send the POST request to the localized path.
So, can we override this #action argument for all resources somewhere in one place or do we have to provide it in each controller in render function call
render(conn, "new.html", changeset: changeset, action: action)
or the only option is to change the form templates for all resources?

Random posts in Hexo

I wanted to show 5 random posts on my home page using Hexo, but can't seem to get it working?! I changed 'date' to 'random' but didn't work.
The code:
<ul>
<% site.posts.sort('date', -1).limit(5).each(function(post){ %>
<li>
<%= post.title || '(no title)' %>
</li>
<% }) %>
</ul>
shuffle or the alias random will work:
<ul>
<% site.posts.random().limit(5).each(function(post){ %>
<li>
<%= post.title || '(no title)' %>
</li>
<% }) %>
</ul>
How it works:
Hexo uses Warehouse for its database. posts is a Query object. So to modify the posts in the future just find the right database Query method in the warehouse API. Each Query method returns a modified copy of the previous Query so that the methods can be chained. So if you want to modify it again just find another method and chain it. Hope this helps!

Standard Rails form + Cocoon gem: undefined method `new_record?' for nil:NilClass error

I'm following this tutorial and the author is using Slim. Since I more familiar with standard Rails form, I try to change the slim markup to normal form like so:
new.html.erb
<%= render 'form' %>
_form.html.erb
<%= form_for(#user) do |f| %>
<%= f.text_field :name %>
<br><br>
<%= fields_for :user_photos do |photo| %>
<%= render "user_photo_fields", f: photo %>
<span class="links">
<%= link_to_add_association "add photo", f, :user_photos %>
</span>
<% end %>
<%= f.submit %>
<% end %>
_user_photo_fields.html.erb
<div class="nested-fields">
<div class="field">
<%= f.file_field :photo %>
</div>
<%= link_to_remove_association "remove", f %>
</div>
And, this is my models:
class User < ActiveRecord::Base
has_many :user_photos
validates_presence_of :name
accepts_nested_attributes_for :user_photos, allow_destroy: true
end
class UserPhoto < ActiveRecord::Base
belongs_to :user
mount_uploader :photo, PhotoUploader
end
And lastly, strong params inside the users_controller.rb. I didn't touch the rest methods inside the controller because I'm using rails g scaffold user name:string generator.
def user_params
params.require(:user).permit(:name, user_photos_attributes: [:id, :photo, :_destroy])
end
I get this error:
undefined method `new_record?' for nil:NilClass
What am I missing here?
I believe it's just a simple typo - your fields_for :user_photos should be f.fields_for :user_photos (so that it's properly connected to the parent form).
please try with this.
class User < ActiveRecord::Base
has_many :user_photos
validates_presence_of :name
accepts_nested_attributes_for :user_photos, allow_destroy: true
end
can you try to fix this by removing the f
<div class="nested-fields">
<div class="field">
<%= file_field :photo %>
</div>
<%= link_to_remove_association "remove" %>
</div>

Rails, choosing option in drop-down filters values in second drop-down

I'm trying to create some pages in my rails app, using bits and pieces of what I've learned from some Railscasts. My environment is as follows:
Rails 3.2.13
ruby 1.9.3p448
Using the chosen gem
Database SQLite
When I want to create a new profile, I would visit localhost:3000/profiles/new.
There I have a text box for my profile called Name. Next I have a drop-down
where the use can choose what profile type - Admin, Editor or User. Once an
option is selected, another drop-down becomes visible - Traits. The user can
then choose 1 or many traits.
For each profile type (Admin, Editor, User) there are different traits. So the
Traits model has fields name and trait_type where trait_type would have a value
of either Admin, Editor or User.
I'm having trouble coding the view, assuming I should code there, but maybe I
should be in a controller, getting the Traits drop-down to display only say
Admin traits if I choose a profile type of Admin.
Can someone please give me a nudge in a positive direction? Please keep in mind
that I'm new to this. Hope I am providing enough, and not too much information.
Note: The console.log entries in my profiles.js.coffee file is temporary, just
so I can see what is going on.
Thanks,
HoGi
-------------------------------------------------
/app/assets/javascripts/application.js
-------------------------------------------------
//= require jquery
//= require jquery_ujs
//= require chosen-jquery
//= require_tree .
-------------------------------------------------
-------------------------------------------------
/app/assets/javascripts/profiles.js.coffee
-------------------------------------------------
jQuery ->
$('#profile_trait_ids').chosen()
jQuery ->
$('#profile_trait_ids').parent().hide()
prof_types = $('#profile_prof_type').html()
console.log(prof_types)
$('#profile_prof_type').change ->
prof_type = $('#profile_prof_type :selected').text()
console.log(prof_type)
$('#profile_trait_ids').parent().show()
-------------------------------------------------
-------------------------------------------------
/app/assets/stylesheets/application.css
-------------------------------------------------
*= require_self
*= require chosen
*= require_tree .
*/
-------------------------------------------------
-------------------------------------------------
/app/models/profile.rb
-------------------------------------------------
class Profile < ActiveRecord::Base
attr_accessible :active, :name, :prof_type, :trait_ids
has_many :traitships
has_many :traits, through: :traitships
PROFILE_TYPES = ["Admin", "Editor", "User"]
end
-------------------------------------------------
-------------------------------------------------
/app/models/trait.rb
-------------------------------------------------
class Trait < ActiveRecord::Base
attr_accessible :active, :name, :trait_type
has_many :traitships
has_many :profiles, through: :traitships
end
-------------------------------------------------
-------------------------------------------------
/app/models/traitship
-------------------------------------------------
class Traitship < ActiveRecord::Base
#attr_accessible :profile_id, :traid_id
belongs_to :profile
belongs_to :trait
end
-------------------------------------------------
-------------------------------------------------
/app/views/_form.html.erb
-------------------------------------------------
<%= form_for(#profile) do |f| %>
<% if #profile.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#profile.errors.count, "error") %> prohibited this profile from being saved:</h2>
<ul>
<% #profile.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :prof_type, 'Profile Type' %><br />
<%= f.select :prof_type, Profile::PROFILE_TYPES, prompt: 'Select a type' %>
</div>
<div class="field">
<%= f.label :trait_ids, "Traits" %><br />
<%= f.collection_select :trait_ids, Trait.order(:name), :id, :name, {}, { multiple: true } %>
</div>
<div class="field">
<%= f.label :active %><br />
<%= f.check_box :active %>
</div>
<div class="actions">
<%= f.submit 'Update' %>
</div>
<% end %>
-------------------------------------------------
UPDATED CONTROLLER:
(traits_controller)
# GET /traits/:trait_type/trait_options
# GET /traits/:trait_type/trait_options.json
def trait_options
#traits = Trait.order(:name).where("trait_type like ?", params[:trait_type])
respond_to do |format|
format.html # trait_options.html.erb
format.json { render json: #traits }
end
end
Part 1
You should add a new action to your controller (traits_controller) that takes as input one parameter profile_type and returns all traits for that profile_type as json/xml.
Part 2
Once you have this ready, You should call this action via ajax on on_change event of your profile_type dropdown. Use that data received to construct the new traits dropdown.
chosen, select2 etc, should make this very easy to accomplish once your part 1 is ready.
Update
I have never used chosen myself. But looking at its documentation, something like this might work for you
$('#profile_type').on('change', function() {
$("#traits").chosen().change( … );
$("#traits").trigger("chosen:updated");
});
This Railscast (Episode #258) demonstrates how a chosen select is populated using json data
If it is possible to drop chosen in favor of select2, I highly recommend you do it.

Rhomobile search question

I try to make rhomobile search in Fixed DB.
But it returns ALL entries in DB instead of the ones with given QID
<%=#questions.id%>
<% #antworts = Antwort.find(:conditions=>{'qid'=>#questions.id})%>
<% #antworts.each do |antwort| %>
<li>
<a href="sdfsdf">
<%= antwort.antwort %>
</a>
</li>
<% end %>
</ul>
Any idea why?
You need to pass :first or :all in the first argument:
Antwort.find(:all, :conditions=>{'qid'=>#questions.id})
Or change the method to find_all:
Antwort.find_all(:conditions=>{'qid'=>#questions.id})