Hanami, show 'post' controller/view - ruby

I don't understand Hanami, I've created Message model, and I want to pull from DB message by params[:id]. The way we do it in Rails #message = Message.find(params[:id].
I read documentation, and what I did after. My Controller (for show):
def call(params)
#message = MessageRepository.find(params[:id])
end
And my erb:
<%= #message.title %>
But it gives me error:
NoMethodError: undefined method `title' for nil:NilClass
What I did wrong?

At the controller call expose :message, then you can use it in the view or in the template as local variable (without the #).

Related

NoMethodError in Users#unsubscribe

I am working on implementing unsubscribe link to my rails mailer. Unfortunately, my code breaks with this:
NoMethodError in Users#unsubscribe - undefined method `unsubscribe_hash' for nil:NilClass
which points to /app/views/users/unsubscribe.html.erb line #3
<h4>Unsubscribe from Mysite Emails</h4>
<p>By unsubscribing, you will no longer receive email...</p>
<%= simple_form_for(#user, unsubscribe_path(id: #user.unsubscribe_hash)) do |f| %>
<%= f.hidden_field(:subscription, value: false) %>
<%= f.submit 'Unsubscribe' %>
<%= link_to 'Cancel', root_url %>
<% end %>
my user_controller is as shown below
class UsersController < ApplicationController
protect_from_forgery
def new
#user = User.new
end
def create
#user = User.new(secure_params)
if #user.save
flash[:notice] = "Thanks! You have subscribed #{#user.email} for Jobs Alert."
else
flash[:notice] = 'Error Subscribing! Kindly check your email and try again.'
end
redirect_to root_path
end
def unsubscribe
user = User.find_by_unsubscribe_hash(params[:unsubscribe_hash])
#user = User.find_by_unsubscribe_hash(user)
end
def update
#user = User.find(params[:id])
if #user.update(secure_params)
flash[:notice] = 'Subscription Cancelled'
redirect_to root_url
else
flash[:alert] = 'There was a problem'
render :unsubscribe
end
end
private
def secure_params
params.require(:user).permit(:email, :subscription)
end
end
Route.rb
resources :users, only: [:new, :create]
get 'users/:unsubscribe_hash/unsubscribe' => 'users#unsubscribe', as: :unsubscribe
patch 'users/update'
user.rb
class User < ActiveRecord::Base
before_create :add_unsubscribe_hash, :add_true_to_users_table
validates :email, :uniqueness => true
validates_presence_of :email
validates_format_of :email, :with => /\A[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i
private
def add_unsubscribe_hash
self.unsubscribe_hash = SecureRandom.hex
end
def add_true_to_users_table
self.subscription = true
end
end
unsubscribe link in the email which calls unsubscribe action
# app/views/job_notifier/send_post_email.html.erb
...
<%= link_to "Unsubscribe", unsubscribe_url(id: #unsubscribe) %>.
diagrammatic view of the error
Its seems that I am missing something, do I need to define something in my users_controller? I have never in my life being able to solve NoMethodError or I don't understand what it's all about.
You get that error because #user (set in UsersController#unsubscribe) is nil. That is what the "for nil:NilClass" in undefined methodunsubscribe_hash' for nil:NilClass` is referring to.
This method doesn't seem correct:
def unsubscribe
user = User.find_by_unsubscribe_hash(params[:unsubscribe_hash])
#user = User.find_by_unsubscribe_hash(user)
end
You are looking up a user by unsubscribe_hash and assigning it to user, and then looking up user by unsubscribe_hash again but passing in user as the value to find_by_unsubscribe_hash.
I believe something like this is more as intended:
def unsubscribe
#user = User.find_by_unsubscribe_hash(params[:unsubscribe_hash])
end
Whenever you see any error messages in ruby of the format:
undefined method 'method_name' for nil:NilClass
you are being told you are trying to call something on a nil object and so the focus of your attention should be on why is that object nil. You are also told in your log where the error occurs - in your case it refers to the line, which refers to #user in #user.unsubscribe_hash in your form declaration.
So #user is nil and in this case it's nil because your controller responsible for rendering the form isn't setting #user:
user = User.find_by_unsubscribe_hash(params[:unsubscribe_hash])
#user = User.find_by_unsubscribe_hash(user)
Now quite why you are attempting to find the user and then pass that user into the second line to find #user is beyond me, but anyway the real issue is that you have no user that matches params[:unsubscribe_hash]
So the issue is related to whatever is invoking your unsubscribe action ... you have neglected to add that to your question so I cannot help with that but that is where your focus start.

Reading Rails database values from a URL

In my ruby on rails project, I have a share model which stores share basic values like share name, market cap, current value, book value etc. In rails, when I want to create a new share record, instead of user entering the details, I want them to enter a URL from a financial website and I want my code to read the share basic parameters from the financial website. URL is not stored in the database.
for example: If the user enters http://www.moneycontrol.com/india/stockpricequote/food-processing/nestleindia/NI. My code should read below parameters and store it in database.
name: Nestle , price: 5628, market cap: 54,366.89, book value: 352.69 etc
I read webpages using Nokogiri. And since reading from web takes time, I have to use delayed_job as well.
My new.html.erb has only one input which is URL which sends a post request to "create" action. Now URL is not part of my model. I have declared a :url parameter inside the model as below:
class Share < ActiveRecord::Base
attr_accessor :url
end
Now I am bit confused as to how to handle this url in my model/controller. Which is the best place to implement URL reading method? is it controller or model?
If I pass the url to model, how to implement the method to get url and read the parameters?
If I read the parameters in controller, how do I pass them to model?
I am not able to access the url parameter inside my controller as well. When I call my method to readthe webpage, I get an error saying, empty url is passed:
My new.html.erb:
<%= form_for(#share) do |f| %>
<p>
<%= f.label :url %>
<%= f.text_field :url, autofocus: true %>
</p>
<p>
<%= f.submit 'Pull the data'%>
</p>
<% end %>
and my current create method in my controller:
def create
#url = params[:url]
#readShareBasic(url) is a method to read the website and return a hash
#share = Share.new(readShareBasic(url)).permit(:name, :current_price, :year_low, :year_high, :current_PE_ratio, :market_cap, :book_value, :description, :price_to_book_value))
redirect_to shares_url
end
Here in controller, I am not able to access the content of params[:url] either.
thanks in advance
Use the controller create method to get the url and create/save a new share instance. You don't need the accessor in the model. If you look in the source code of your form, you'll see how the form data is being passed.
In the controller, its better to separate the strong params into its own method.
def
#url = params[:share][:url]
#share = Share.new(share_params)
#share_details = readShareBasic(#url)
# assign values from readShareBasic to the share instance as needed
# save share
end
private
def share_params
params.require(:share).permit(:name, :current_price, :year_low, :year_high, :current_PE_ratio, :market_cap, :book_value, :description, :price_to_book_value, :url)
end

form_tag calling an instance of a class on the controller

I am trying to use a form_tag on a Rails application that, when submitted, call an instance of a class on the controller.
View
form_tag '/order', method: :get
select_tag 'type', options_for_select(#options_for_type, #type)
text_field_tag 'numbers', nil, placeholder: "100"
submit_tag "Get Info"
controller
def order
#order = Order.new(params_here).fetch_info
#type = params[:type] || "type1"
#options_for_type = [["type1", "type1"], ["type2", "type2"]]
...
end
This class sends some API requests (JSON).
Now problem is, I am getting an error from the API that some parameters are missing, which is expected since I haven't submitted the form with all the params, but it seems the class is called automatically when the page is loaded. I would have expected the class to be called only when the submit button is pressed?
Can you make the form_tag sort of a block? Like:
form_tag '/order', method: :get do
# All form elements
end
Maybe displaying your route here can also help.

undefined method `refreshProfile_affinity_path' for #<#<Class:0x8daee70>:0x8dbdc30>

I'm getting the error in the title. I am not sure how exactly to write the routes, controller, and index.
I am trying to create a 'Refresh' button in an index.html.erb view shown below:
...
<td><%= link_to 'Refresh', refreshProfile_affinity_path(a), method: :put %></td>
...
It is using this route in routes.rb:
resources :affinities
put 'affinities/refreshProfile/:id' => 'affinities#refreshProfile'
It is trying to access the following method in the affinities_controller.erb:
...
def refreshProfile
#affinity = Affinity.find(params[:id])
new_profile_affinity = User.find(#affinity.user_A_id).profile_affinity_with(User.find(#affinity.user_B_id))
if #affinity.update_attributes(:integer, new_profile_affinity)
redirect_to #affinity
end
end
...
What could be wrong? Any help is greatly appreciated!
You need to add an as: to your route, this is what specifies the prefix for the helper method and is why you're currently getting an undefined method error e.g.
put 'affinities/refreshProfile/:id' => 'affinities#refreshProfile',
as: 'refreshProfile_affinity'
refreshProfile_affinity_path would then work, or you could give it a shorter, snappier name e.g. as: 'refreshProfile' and then use refreshProfile_path.

Undefined method 'to_i' for :Symbol

RoR novice here, appreciate any help.
I have the following error:
undefined method `to_i' for :funding_level:Symbol
Am trying to pass both funding_level and investment_id parameters from link_to into the new method in my controller.
From my understanding, the 100 value gets passed as a Symbol and not an Object, causing problems when I then try to assign it to #funding_level, an integer variable.
Thanks!
HTML:
<div id="investment-status">
<%= link_to "$100", new_project_funding_path(funding_level: 100,investment_id: #project.id), class: 'btn' %>
</div>
Controller:
def new
#investment = Project.find(params[:investment_id])
#funding_offered = :funding_level
#project_funding = current_user.project_fundings.new(investment: #investment, funding_offered: #funding_offered)
end
Shouldn't be this instead ?
#funding_offered = params[:funding_level]

Resources