I currently save code like below in my user model.
User.where(type: "supercool").each do |user|
if user.score == 100
user.message = "Hello #{user.name}, you now have #{user.points} points!".html_safe
elsif user.address == "New York"
user.message = "You live in the same town as #{Person.where(address:"New York").first.name}"
user.save
end
I save these messages in my model, and print them out in the view by just calling User.find(params[:id]).messages in the controller.
The actual model code is much longer, as there are many unique messages based on different scenarios.
While this works, I would now like to add a link_to to objects that are mentioned in the messages.
For the first message, I want to save it so that when I send it to the view, it's in the form of
Hello <%= link_to user.name, user_path(user.id) %>, you now have <%= link_to user.points, leaderboard_path %> points!
I tried the below, but it doesn't work.
User.where(type: "supercool").each do |user|
if user.score == 100
user.message = "Hello #{link_to user.name, user}, you now have #{link_to user.points, leaderboard_path} points!".html_safe
user.save
end
How can I save erb in my string?
How about this? Use html tags instead of using link_to
User.where(type: "supercool").each do |user|
if user.score == 100
user.message = "Hello <a href=#{Rails.application.routes.url_helpers.user_path(user)}>#{user.name}</a>, you now have <a href=#{Rails.application.routes.url_helpers.leaderboard_path}>#{user.points}</a> points!".html_safe
user.save
end
end
And in your view, Just do
<%= user.message %>
This is not a very good pratice.
You can like:
class Model < ActiveRecord::Base
include Rails.application.routes.url_helpers
def example
ActionController::Base.helpers.link_to user.name, user
end
end
But using a helper or a erb template to show this to the user seems the best way.
Related
i built this form that generate me some chebox with value like "U6", "U8" eccc
<%= form.label "Seleziona Categorie" %>
<% TeamCategory::NAMES.each do |category| %>
<%= check_box_tag 'categories_selected[]', category -%>
<% end %>
Now i have to pass the value of selected check_box to a method in my model.
Now is:
def create_tournament_team_categories
TeamCategory::NAMES.each do |name|
team_category = TeamCategory.where(name: name).first_or_create
self.tournament_team_categories << TournamentTeamCategory.create(team_category: team_category)
end
end
I would like to replace the TeamCategory::NAMES.each do with "selected check_box each do" and TeamCategory.where(name: name) with the value selected.
Thank you in advance
I am a newbie with Rails. What I see is that you took the part of the form to create the team, right?
For your code straight forward it could be:
<%= form.label "Seleziona Categorie" %>
<% TeamCategory::NAMES.each do |name| %> #you are looping through team category NAMES constant
<%= check_box_tag 'category_names_selected[]', name %>
<% end %>
Your form as is allows more than one category to be selected.
For the method:
def create_tournament_team_categories(category_names_selected)
category_names_selected.each do |name|
team_category = name
self.tournament_team_categories << TournamentTeamCategory.create(team_category: team_category)
end
end
you will probably use this method in your teams_controller.rb. In the controller, you should be able to retrieve from params a freshly created array of selected names with something along the lines with this.
#category_names_selected = params[:category_names_selected]
I do not know how complicated your app is so it might also be nested under ["team"][:category_names_selected] or ["team"]["category_names_selected"] in your params hash.
To see the exact structure of the params hash and adjust the equation above you can add for example require 'pry' at the top of your controller file and then but the binding.pry just after the part where your method is executed. When you restart the server and the app hits this part of the controller you should be able to see the exact structure of your params hash in the terminal.
You can then pass the array to the method that you can call in the controller. Do not forget to add :category_names_selected to the strong params in the controller. I hope this helps.
Controller on line 30
def create
#tournament = Tournament.new(tournament_params)
#tournament.sport_club = current_user.sport_club
#category_names_selected = params[:category_names_selected]
if #tournament.save
redirect_to tournaments_path, notice: 'Torneo creato con successo'
end
end
Method create_tournament_team_categories in the model
after_create :create_tournament_team_categories
def create_tournament_team_categories(category_names_selected)
#category_names_selected.each do |name|
team_category = name
self.tournament_team_categories << TournamentTeamCategory.create(team_category: team_category)
end
end
I have this code in User#index view:
<%= User.find_each do |user| %>
<%= user.name %>
<% end %>
which returns the user names:
user1 user2 user3 ...
Then I move this code to the UserHelper:
module UserHelper
def get_users
User.find_each do |user|
user.name
end
end
end
And call it from the User#index view with:
<%= get_users %>
The problem is that this is not returning any user. If I use <%= get_users.class %> it outputs NilClass. Why is the helper method not returning the user names?
Your helper method implicitly returns the result of calling find_each, which is different than returning a collection of user names.
Think of it like running 5.times { |n| puts n }: what's the value of that? Not "0 1 2 3 4", but "5", because times returns what it was called on, not what's run in its block.
Your original code, by the way, returns the exact same thing--you are relying on a side effect inside the find_each block, i.e., appending user.name to the response.
If you want to return a collection of the users' names you'd want to map/etc. and grab each user's name. Or, IIRC, you can do a find and a pluck so you only get back the users' names instead of all user fields.
You can use as below also,
<%= User.all.map(&:name).join(' ') %>
I'm implementing SmsService to send text message to user's phone. The SmsService receives the text message content from SmsContent:
class SmsContent
def initialize(sms_type, data)
#sms_type = sms_type
#data = data
end
def get_content
sms_template_one_way = 'Hello #{customer_name}, this is your one way itinerary from #{depart_place} to #{arrive_place} ...'
sms_template_round_trip = 'Hello #{customer_name}, this is your round trip itinerary from #{depart_place} to #{arrive_place} ...'
customer_name = #data.customer_name
depart_place = #data.depart_place
arrive_place = #data.arrive_place
if #sms_type == 1
sms_content = sms_template_round_trip
else
sms_content = sms_template_one_way
end
sms_content
end
end
I have to store my message template as String variables. How can I refactor this code? Specifically, how can I store message templates in a file and automatically bind data to template?
class SmsContent
def initialize(sms_type, data); #sms_type, #data = sms_type, data end
def get_content
"Hello %{customer_name}, this is your %{sms_type} itinerary "\
"from %{depart_place} to %{arrive_place} ..." %
{
sms_type: #sms_type == 1 ? "round trip" : "one way",
customer_name: #data.customer_name,
depart_place: #data.depart_place,
arrive_place: #data.arrive_place,
}
end
end
First make a partial file under app/views/sms_content/_get_content.html.erb
_get_content.html.erb
<% if #sms_type == 1 %>
Hello <%= #data.customer_name %>, this is your one way itinerary from <%= #data.depart_place %> to <%= #data.arrive_place %> ...
<% else %>
Hello <%= #data.customer_name %>, this is your round trip itinerary from <%= #data.depart_place %> to <%= #data.arrive_place %> ...
<% end %>
In your SmsContent class get_content method
def get_content
render :partial => "sms_content/get_content"
end
This should work
As I indicated in my comment above, Rails' built-in I18n API is practically designed for this exact thing. First, store your template strings in the config/locales/ directory:
# config/locales/en.yml
en:
sms_template:
one_way:
Hello %{customer_name}, this is your one way itinerary
from %{depart_place} to %{arrive_place} ...
round_trip:
Hello %{customer_name}, this is your round trip itinerary
from %{depart_place} to %{arrive_place} ...
Note that this format uses %{...} a la sprintf for interpolation instead of #{...}.
Then:
def get_content
template_name = #sms_type == 1 ? "round_trip" : "one_way"
I18n.t("sms_template.#{template_name}", #data.attributes)
end
That's it! One thing to note: The above assumes that #data is an ActiveModel object (or something that responds to attributes with a Hash); if that's not the case you'll have to build a Hash first.
I'm trying to make a specific link in my application only visible to users who have the attribute :department equal to "Sales".
In other words, I've got a model Users, in which a user has a password, username, and department. The session saves the :user_id once the user is logged in.
What I would like to do is when my view is rendered, depending on the :department of the logged in user, either display, or don't display a specific link.
Here's the code I've got in my view, but I'm struggling with how to take the session info and find the department of the user from it.
<% if Users.where(id: session[:user_id])[:department] == "Sales" %>
<%= link_to 'New Request', new_request_path %>
<% else nil %>
<% end %>
I know it's bad to do a query anywhere other than the controller or model, so if you have any advice on how to better structure this logic as well, I would appreciate it.
I think what you want is:
<% user = User.find_by_id(session[:user_id]) %>
<% if user.present? && user[:department] == "Sales" %>
<%= link_to 'New Request', new_request_path %>
<% end %>
Personally, I'd put this into a helper method to clean it up:
In app/helpers/users_helper.rb:
def user_in_sales?
user = User.find_by_id(session[:user_id])
user.present? && user[:department] == "Sales"
end
Then your view:
<% if user_in_sales? %>
<%= link_to 'New Request', new_request_path %>
<% end %>
Personally, I'd strongly look into using something like cancan to handle this situation. I think you may find that you could use cancan as an effective authorization tool other places in your app, especially if you're doing logic like this elsewhere.
First, you're using an object oriented language. It would help you to quit getting hung up on implementation details (e.g. department == "Sales") and instead consider the intent or meaning you're trying to express and code to meet that. For example:
if current_user.works_in?(:jewelry)
link_to 'Request Receipt', new_request_path
end
Your models should expose a public interface that allows other objects in your code (like your controller) to get the information they need (i.e. whether or not a user has an association with a department) without knowledge of or concern for the underlying data storage schema.
class User
def works_in?(department_name)
departments.pluck(:name).include?(department_name.to_s)
end
end
I'm building a small ecommerce site that sells a variety of mens and womens clothing. i would like to render a partial based on which taxonomy the user is in. For example, if the user is at mysite.com/t/women/pants I would like to render _women.html.erb, or, if the user is at mysite.com/t/men/shirts I would like to render _men.html.erb.
I have a Taxonomy model that has_many taxons, and the Taxon model has_many products.
In taxons_controller.rb I have:
def show
#taxon = Taxon.find_by_permalink(params[:id])
return unless #taxon
#taxonomy = Spree::Taxonomy.all
#taxon_title = Spree::Taxon.all
#searcher = Spree::Config.searcher_class.new(params.merge(:taxon => #taxon.id))
#searcher.current_user = try_spree_current_user
#searcher.current_currency = current_currency
#products = #searcher.retrieve_products
respond_with(#taxon)
end
And in taxons#show I have: (which I know is wrong)
<% #taxon_title.each do |title| %>
<% #taxonomy.each do |taxonomy| %>
<% if title.name == taxonomy.name %>
<%= render "spree/shared/#{title.name.downcase}" %>
<% end %>
<% end %>
<% end %>
When I go to mysite.com/t/women/long-sleeve the rails debugger displays :
controller: spree/taxons
action: show
id: women/long-sleeve
How do I access the id of the action im inside, so that in the controller/view I can do something like:
'if id equals 'women' render "spree/shared/#{title.name.downcase}"'
where title is the name of the taxonomy?
I imagine I need to find(params[:something] in the show action of the controller, but I'm a little unclear about params.
*
*
*
#beck03076 That's a great trick. Thank you very much. But it's still not working.
In my controller I put:
#taxon_id = Spree::Taxon.find(params[:id])
Then in the action I put:
render 'spree/shared/women' if #taxon_id == params[:id]
And when I load the page it says 'the page you were looking for doesn't exist'. My partial is in the correct directory. Is my syntax correct?
My params are:
{"controller"=>"spree/taxons", "action"=>"show", "id"=>"women/long-sleeve"}
Thanks again for your help!
Whenever you are unclear about params, just put the lines below in the action and execute the action.
p "****************************"
p params
p "****************************"
Now, goto the terminal in which you started your server.
Locate those two "*******" and everything thats in between them are params.
params is basically a ruby hash.
example:
params look like this, {:controller => "hello",:action => "bye", :id => 7, :others => "OK"}
In your controller to access the id, use params[:id].(=7)
to access others, use params[:others].(="OK")