actually i use restful-authentication but ai need call method logged_in from MODEL (no controller) distinct of user.
can you help me...
example:
modelx.rb
def price
if logged_in?
#product.price = current_user.prices
else
#product.price = 0
end
end
It's a better design to pass that information in from where you are calling the method.
def price(logged_in = false)
if logged_in
#product.price = current_user.prices
else
#product.price = 0
end
end
Calling it from the controller or view:
#modelx.price(logged_in?)
Related
I am trying to pass stored_products from shopify into a Rails app but keep getting a home controller error at https://f588240c.ngrok.io/ i have made updates, with no luck and restarted the server a number of times with no luck.
Any help would be welcomed. Heres the code
class Api::V1::HomeController < ShopifyApp::AuthenticatedController
def index
#products = ShopifyAPI::Product.find(:all, params: { limit: 10 })
#products.each do |product|
StoredProduct.where(shopify_id: product.id)
.first_or_create do |stored_product|
stored_product.shopify_id = product.id
stored_product.shopify_title = product.title
stored_product.shopify_handle = product.handle
stored_product.shopify_image_url = product.image.src
stored_product.shop_id = #shop.id
stored_product.save
product.images.each do |image|
ProductImage.where(shopify_id: image.id)
.first_or_create do |product_image|
product_image.image_url = image.src
product_image.stored_product_id = stored_product_id
product_image.shopify_id = image.id
end
end
end
end
#stored_products = StoredProduct.belongs_to_shop(#shop.id)
end
end
From the authenticated controller
private
def set_shop
#shop = Shop.find_by(id: session[:shopify])
set_locale
end
from the store_products.rb file
class StoredProduct < ApplicationRecord
belongs_to :shop
has_many :product_images
scope :belongs_to_shop, -> shop_id { where(shop_id: shop_id) }
end
For this specific issue/code tutorial, the private set_shop method should be set like follows:
def set_shop
#shop = Shop.find_by(id: session[:shop_id])
set_locale
end
The other answer has params instead of session
The problem is that #shop is nil. The error message says it cannot call the method .id on NilClass.
In the image I can see that you have a shop_id in the params so you might just need to change your code here:
def set_shop
#shop = Shop.find_by(id: params[:shop_id])
set_locale
end
But that depends on your code, so please double check.
I'm a beginner trying out some aspects pertaining to enrollments in my rails app. Users have many enrollments; enrollments belong to a lesson; enrollments have many word_expositions and scrambled_words.
I wrote a helper method in the lessons controller to produce a list of enrolled users, to display in each lesson show page:
helper_method :enrolled_users
def enrolled_users
lesson = Lesson.find(params[:id])
enrollments = lesson.enrollments
enrolled_users = enrollments.map { |enrollment| enrollment.user }
end
I am now trying to implement a completed_expos helper so that I can indicate next to each user whether they have completed the expositional component of my app. What I have is:
helper_method :completed_expos
def completed_expos
lesson = Lesson.find(params[:id])
completed_expos = enrolled_users.map do |user|
current_enrollment = lesson.enrollment_for(user)
all_expos = current_enrollment.word_expositions
all_expos.all? { |expos| expos.completed == true }
end
end
I would like to add a notice next to each listed user regarding whether they completed the expos. So what I tried is:
<% enrolled_users.each do |user| %>
<ul>
<li><%= user.username %></li>
<% if completed_expos.include?(user) %>
completed
<% end %>
</ul>
<% end %>
but the effect is that, although enrolled users are listed, there is no indication as to expo completion in those places where it should list it. How can I go about selecting this subgroup of users?
From what I can get from your code is that your "completed_expos" method will always return an array of Boolean values (true, false) rather than a list of users, so it could never include the user you specify.
I guess what you might want to do was to use select instead of map.
enrolled_users.select do |user|
current_enrollment = lesson.enrollment_for(user)
all_expos = current_enrollment.word_expositions
all_expos.all? { |expos| expos.completed == true }
end
Also, let me say that you don't need to assign the values in each of your methods to a variable with the same name as the method. Eg.
def enrolled_users
lesson = Lesson.find(params[:id])
enrollments = lesson.enrollments
enrolled_users = enrollments.map { |enrollment| enrollment.user }
end
Could be
def enrolled_users
lesson = Lesson.find(params[:id])
enrollments = lesson.enrollments
enrollments.map { |enrollment| enrollment.user }
end
The problem is the helper wasn't returning a user, as to map it into the array:
helper_method :completed_expos
def completed_expos
lesson = Lesson.find(params[:id])
completed_expos = enrolled_users.map do |user|
current_enrollment = lesson.enrollment_for(user)
all_expos = current_enrollment.word_expositions
user if all_expos.all? { |expos| expos.completed == true }
end
end
I created this class for assembling the text based on the length of the product attributes for sharing on twitter.
My questions:
Is this the good approach to tackle the problem? If not this then what? (where should I put the class and the methods, how to invoke it, etc.)
If this is the good approach then what should be changed? For instance I feel the def twitter_share_text shouldn't be in the product.rb.
show.html.erb
<a class="twitter-share" data-behavior="twitter-share"
data-twittertext="<%= #product.twitter_share_text %>"
data-twitterurl="<%= product_url(#product) %>"
data-twitteranchor>
<i class="fa fa-lg fa-twitter"></i>
</a>
product.rb
def twitter_share_text
TwitterProductShare.new(self).return_text
end
app/services/twitter_product_share.rb
class TwitterProductShare
URL_LENGTH = 23 #defined by twitter API
SPACE_LENGTH = 1
TWITTER_MAX = 140
attr_reader :name, :oneliner
def initialize(product)
#name = product.name
#oneliner = product.oneliner
end
def return_text
if full_length <= TWITTER_MAX
return basic_text
else
return basic_text[0...-(difference + text_end.length)] + text_end
end
end
private
def basic_text
"#{name}: #{oneliner}"
end
def difference
full_length - TWITTER_MAX
end
def full_length
basic_text.length + SPACE_LENGTH + URL_LENGTH
end
def text_end
"..."
end
end
I think code like that belongs into a view helper:
# in app/helpers/product_helper.rb
def twitter_share_link(product)
data = {
behavior: 'twitter-share',
twittertext: TwitterProductShare.new(product).return_text,
twitterurl: product_url(product),
twitteranchor: 'twitteranchor'
}
link_to(class: 'twitter-share', data: data) do
tag(:i, class: 'fa fa-lg fa-twitter')
end
end
In your view use this helper like this:
<%= twitter_share_link(#product) %>
Or you could even return the whole data hash from the TwitterProductShare.
I want to pass the value of a form to a Controller that should call a method from the Model for searching products.
I want to pass the category_id and the string that the user writes at the textfield.
I would pass to the model even the blank value of params (if the user doesn't write something on the search bar or choose none category)
I want to save even the blank value cause in the model, the SQL blank variable take "all" things.
And this is good a cause if there is something in the params , the SQL will find that thing, BUT if there is nothing in the params, the SQL will take all products.
I'm not able to save the value of params in varibiles cause if params is blank it returns to me this error:
undefined method `[]' for nil:NilClass
I hope you understand me and what I want to do.
In other words , I want to use a simple assignment to pass a value (even blank values) to a model to do a SQL query. In one shoot of code I want to program two cases.
Here my code.
In my Controller:
...
if params[:search]
#search_name = params[:search]
end
if params[:category][:name]
#category = params[:category][:name]
end
#products = Product.search(#search_name,#category)
...
In my Model:
def self.search(search_name,category)
ricerca = Product.where("category_id = ? ",category)
ricerca = ricerca.where("title like ? ", "%#{search_name}%")
end
You can get category parameters by defining a method like,
def category_params
params.fetch(:category, {})
end
And, then look up for Products by,
#search_name = params[:search]
#category = category_params[:name]
#products = Product.search(#search_name, #category)
In my opinion, if you are making a direct query on Product, then you should do like,
def product_params
params.fetch(:product, {})
end
#category = product_params[:category_id]
#title = product_params[:title]
#products = Product.search(#category, #title)
And in product model,
def self.search(category, title)
where("category_id = ? AND title LIKE ?", category, "%#{title}%")
end
Try this:
#search_name = params[:search]
#category = (params[:category].blank? ? nil : params[:category][:name])
#products = Product.search(#search_name,#category)
#Vito, change the line -> #category = params[:category][:name] in your controller by
#category = params[:category].present? ? params[:category][:name]
the issue is when you don't select the category then params[:category] comes nil and you are fetching name from params[:category] that's why error "undefined method `[]' for nil:NilClass" is comming.
Hope this will resolve your problem.
i still have problems , cause when i wrote
if params[:category]
#category = params[:category][:name]
else
#category = " "
end
if params[:search]
#nome_ricerca = params[:search]
else
#nome_ricerca = " "
end
#products = Product.search(#nome_ricerca,#category)
i have this problem:
Showing C:/Bitnami/depot/app/views/store/index.html.erb where line #18 raised:
undefined method `name' for "":String
Extracted source (around line #18):
<p>
<%= label_tag :search, 'Search:' %>
<%= text_field_tag :search, params[:search] %>
<%= collection_select :category, :name, Category.all, :id, :name, {:prompt => 'All Categories'} %>
<%= submit_tag "Search", name: nil %>
</p>
what is this?
Ok, i fixed the problem
it was (i think) concerning the fact that i used #category as variable name
maybe the view gets in confusion for this
i call #category in #cat and the problem disappears
But , now the problem is that the SQL query doesn't return all the category if i pass "" in the variable #cat
How can i have all the result of a query? with like %% it works but with
category_id = "" no. why?
I post the code fixed for others:
In Controller:
if params[:category]
#cat = params[:category][:name]
else
#cat = ''
end
if params[:search]
#nome_ricerca = params[:search]
else
#nome_ricerca = ''
end
#products = Product.search(#nome_ricerca,#cat)
In model:
def self.search(nome_ricerca,categoria)
ricerca = Product.where("title like ? AND category_id = ? ", "%#{nome_ricerca}%",categoria)
end
LAST POST:
PROBLEM FIXED:
In Controller
#stringa_sql = ""
if params[:search]
#nome_ricerca = params[:search]
else
#nome_ricerca = ''
end
#stringa_sql = "title like "+"'%"+#nome_ricerca+"%'"
if params[:category]
if params[:category][:name] != ""
#cat = params[:category][:name]
#stringa_sql += " AND category_id = "+#cat
else
#cat = ''
end
end
#products = Product.search(#stringa_sql)
In Model:
def self.search(stringa_sql)
ricerca = Product.where(stringa_sql)
end
Question: does this solution suffer Sql Injection ?
Thx all :)
I Hope this solution will help someone.
I am studying pragmatic bookshelf lessons. I try to make a session counter.
my store controller is
class StoreController < ApplicationController
def increment_counter
if session[:counter].nil?
session[:counter] = 0
end
session[:counter] += 1
end
def index
#count = increment_counter
#products = Product.all
#cart = current_cart
#time = Time.now
#shown_message = "You've been here #{#count} times" if increment_counter >5
end
end
and my view is
<h5><p><%= #shown_message %></p></h5>..
until 5 times it does not work . but after it starts to count as 5,7,9,11. . what is wrong with my session[:counter]?
You call increment_counter twice in your action : first when setting #count, and then again in your condition for #shown_message.
In complement to ksol answer. Use #count in the last call.
def index
#count = increment_counter
#products = Product.all
#cart = current_cart
#time = Time.now
#shown_message = "You've been here #{#count} times" if #count >5
end
In your store_controller.rb better code like that:
before_action :session_counter
def session_counter
if session[:counter].nil?
session[:counter] = 0
end
session[:counter] += 1
#session_counter = session[:counter]
end
In store.html.erb like that:
<p>
<% if #counter>5 %>
<%= "U have visit the store #{#session_counter} times!" %>
<% end %>
</p>
looks a pretty nice and works easy.